[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/celerity/controller/ -> CelerityResourceController.php (source)

   1  <?php
   2  
   3  abstract class CelerityResourceController extends PhabricatorController {
   4  
   5    protected function buildResourceTransformer() {
   6      return null;
   7    }
   8  
   9    public function shouldRequireLogin() {
  10      return false;
  11    }
  12  
  13    public function shouldRequireEnabledUser() {
  14      return false;
  15    }
  16  
  17    public function shouldAllowPartialSessions() {
  18      return true;
  19    }
  20  
  21    abstract public function getCelerityResourceMap();
  22  
  23    protected function serveResource($path, $package_hash = null) {
  24      // Sanity checking to keep this from exposing anything sensitive, since it
  25      // ultimately boils down to disk reads.
  26      if (preg_match('@(//|\.\.)@', $path)) {
  27        return new Aphront400Response();
  28      }
  29  
  30      $type = CelerityResourceTransformer::getResourceType($path);
  31      $type_map = self::getSupportedResourceTypes();
  32  
  33      if (empty($type_map[$type])) {
  34        throw new Exception('Only static resources may be served.');
  35      }
  36  
  37      $dev_mode = PhabricatorEnv::getEnvConfig('phabricator.developer-mode');
  38  
  39      if (AphrontRequest::getHTTPHeader('If-Modified-Since') && !$dev_mode) {
  40        // Return a "304 Not Modified". We don't care about the value of this
  41        // field since we never change what resource is served by a given URI.
  42        return $this->makeResponseCacheable(new Aphront304Response());
  43      }
  44  
  45      $is_cacheable = (!$dev_mode) &&
  46                      $this->isCacheableResourceType($type);
  47  
  48      $cache = null;
  49      $data = null;
  50      if ($is_cacheable) {
  51        $cache = PhabricatorCaches::getImmutableCache();
  52  
  53        $request_path = $this->getRequest()->getPath();
  54        $cache_key = $this->getCacheKey($request_path);
  55  
  56        $data = $cache->getKey($cache_key);
  57      }
  58  
  59      if ($data === null) {
  60        $map = $this->getCelerityResourceMap();
  61  
  62        if ($map->isPackageResource($path)) {
  63          $resource_names = $map->getResourceNamesForPackageName($path);
  64          if (!$resource_names) {
  65            return new Aphront404Response();
  66          }
  67  
  68          try {
  69            $data = array();
  70            foreach ($resource_names as $resource_name) {
  71              $data[] = $map->getResourceDataForName($resource_name);
  72            }
  73            $data = implode("\n\n", $data);
  74          } catch (Exception $ex) {
  75            return new Aphront404Response();
  76          }
  77        } else {
  78          try {
  79            $data = $map->getResourceDataForName($path);
  80          } catch (Exception $ex) {
  81            return new Aphront404Response();
  82          }
  83        }
  84  
  85        $xformer = $this->buildResourceTransformer();
  86        if ($xformer) {
  87          $data = $xformer->transformResource($path, $data);
  88        }
  89  
  90        if ($cache) {
  91          $cache->setKey($cache_key, $data);
  92        }
  93      }
  94  
  95      $response = new AphrontFileResponse();
  96      $response->setContent($data);
  97      $response->setMimeType($type_map[$type]);
  98  
  99      // NOTE: This is a piece of magic required to make WOFF fonts work in
 100      // Firefox. Possibly we should generalize this.
 101      if ($type == 'woff') {
 102        // We could be more tailored here, but it's not currently trivial to
 103        // generate a comprehensive list of valid origins (an install may have
 104        // arbitrarily many Phame blogs, for example), and we lose nothing by
 105        // allowing access from anywhere.
 106        $response->addAllowOrigin('*');
 107      }
 108  
 109      return $this->makeResponseCacheable($response);
 110    }
 111  
 112    public static function getSupportedResourceTypes() {
 113      return array(
 114        'css' => 'text/css; charset=utf-8',
 115        'js'  => 'text/javascript; charset=utf-8',
 116        'png' => 'image/png',
 117        'gif' => 'image/gif',
 118        'jpg' => 'image/jpeg',
 119        'swf' => 'application/x-shockwave-flash',
 120        'woff' => 'font/woff',
 121        'eot' => 'font/eot',
 122        'ttf' => 'font/ttf',
 123      );
 124    }
 125  
 126    private function makeResponseCacheable(AphrontResponse $response) {
 127      $response->setCacheDurationInSeconds(60 * 60 * 24 * 30);
 128      $response->setLastModified(time());
 129  
 130      return $response;
 131    }
 132  
 133  
 134    /**
 135     * Is it appropriate to cache the data for this resource type in the fast
 136     * immutable cache?
 137     *
 138     * Generally, text resources (which are small, and expensive to process)
 139     * are cached, while other types of resources (which are large, and cheap
 140     * to process) are not.
 141     *
 142     * @param string  Resource type.
 143     * @return bool   True to enable caching.
 144     */
 145    private function isCacheableResourceType($type) {
 146      $types = array(
 147        'js' => true,
 148        'css' => true,
 149      );
 150  
 151      return isset($types[$type]);
 152    }
 153  
 154    private function getCacheKey($path) {
 155      return 'celerity:'.$path;
 156    }
 157  
 158  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1