$relPath) * * Note: Treat as private. This is only public to facilitate debugging. */ public $relPaths = FALSE; /** * @var array($key => $relUrl) * * Derived from $relPaths. On Unix systems (where file-paths and * URL-paths both use '/' separator), this isn't necessary. On Windows * systems, this is derived from $relPaths. * * Note: Treat as private. This is only public to facilitate debugging. */ public $relUrls = FALSE; /** * @param string $baseDir local path to the container * @param string $baseUrl public URL of the container * @param CRM_Utils_Cache_Interface $cache * @param string $cacheKey unique name for this container */ public function __construct($baseDir, $baseUrl, CRM_Utils_Cache_Interface $cache = NULL, $cacheKey = NULL) { $this->cache = $cache; $this->cacheKey = $cacheKey; $this->baseDir = rtrim($baseDir, '/'); $this->baseUrl = rtrim($baseUrl, '/'); } /** * {@inheritdoc} */ public function checkRequirements() { $errors = array(); if (empty($this->baseDir) || !is_dir($this->baseDir)) { $errors[] = array( 'title' => ts('Invalid Base Directory'), 'message' => ts('An extension container has been defined with a blank directory.'), ); } if (empty($this->baseUrl)) { $errors[] = array( 'title' => ts('Invalid Base URL'), 'message' => ts('An extension container has been defined with a blank URL.'), ); } return $errors; } /** * {@inheritdoc} */ public function getKeys() { return array_keys($this->getRelPaths()); } /** * {@inheritdoc} */ public function getPath($key) { return $this->baseDir . $this->getRelPath($key); } /** * {@inheritdoc} */ public function getResUrl($key) { if (! $this->baseUrl) { CRM_Core_Session::setStatus( ts('Failed to determine URL for extension (%1). Please update Resource URLs.', array( 1 => $key, 2 => CRM_Utils_System::url('civicrm/admin/setting/url', 'reset=1'), ) ) ); } return $this->baseUrl . $this->getRelUrl($key); } /** * {@inheritdoc} */ public function refresh() { $this->relPaths = NULL; if ($this->cache) { $this->cache->delete($this->cacheKey); } } /** * @return string */ public function getBaseDir() { return $this->baseDir; } /** * Determine the relative path of an extension directory * * @param $key * * @throws CRM_Extension_Exception_MissingException * @return string */ protected function getRelPath($key) { $keypaths = $this->getRelPaths(); if (!isset($keypaths[$key])) { throw new CRM_Extension_Exception_MissingException("Failed to find extension: $key"); } return $keypaths[$key]; } /** * Scan $basedir for a list of extension-keys * * @return array($key => $relPath) */ protected function getRelPaths() { if (!is_array($this->relPaths)) { if ($this->cache) { $this->relPaths = $this->cache->get($this->cacheKey); } if (!is_array($this->relPaths)) { $this->relPaths = array(); $infoPaths = CRM_Utils_File::findFiles($this->baseDir, 'info.xml'); foreach ($infoPaths as $infoPath) { $relPath = CRM_Utils_File::relativize(dirname($infoPath), $this->baseDir); try { $info = CRM_Extension_Info::loadFromFile($infoPath); } catch (CRM_Extension_Exception_ParseException $e) { CRM_Core_Session::setStatus(ts('Parse error in extension: %1', array( 1 => $e->getMessage(), )), '', 'error'); CRM_Core_Error::debug_log_message("Parse error in extension: " . $e->getMessage()); continue; } $this->relPaths[$info->key] = $relPath; } if ($this->cache) { $this->cache->set($this->cacheKey, $this->relPaths); } } } return $this->relPaths; } /** * Determine the relative path of an extension directory * * @param $key * * @throws CRM_Extension_Exception_MissingException * @return string */ protected function getRelUrl($key) { $relUrls = $this->getRelUrls(); if (!isset($relUrls[$key])) { throw new CRM_Extension_Exception_MissingException("Failed to find extension: $key"); } return $relUrls[$key]; } /** * Scan $basedir for a list of extension-keys * * @internal param string $dirSep the local system's directory separator * @return array($key => $relUrl) */ protected function getRelUrls() { if (DIRECTORY_SEPARATOR == '/') { return $this->getRelPaths(); } if (!is_array($this->relUrls)) { $this->relUrls = self::convertPathsToUrls(DIRECTORY_SEPARATOR, $this->getRelPaths()); } return $this->relUrls; } /** * Convert a list of relative paths to relative URLs. * * Note: Treat as private. This is only public to facilitate testing. * * @param string $dirSep * @param array $relPaths ($key => $relPath) * @return array($key => $relUrl) */ public static function convertPathsToUrls($dirSep, $relPaths) { $relUrls = array(); foreach ($relPaths as $key => $relPath) { $relUrls[$key] = str_replace($dirSep, '/', $relPath); } return $relUrls; } }