3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.3 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
29 * This class proivdes various helper functions for locating extensions
30 * data. It's designed for compatibility with pre-existing functions from
31 * CRM_Core_Extensions.
33 * Most of these helper functions originate with the first major iteration
34 * of extensions -- a time when every extension had one eponymous PHP class,
35 * when there was no PHP class-loader, and when there was special-case logic
36 * sprinkled around to handle loading of "extension classes".
38 * With module-extensions (Civi 4.2+), there are no eponymous classes --
39 * instead, module-extensions follow the same class-naming and class-loading
40 * practices as core (and don't require special-case logic for class
41 * loading). Consequently, the helpers in here aren't much used with
45 * @copyright CiviCRM LLC (c) 2004-2013
49 class CRM_Extension_Mapper
{
52 * An URL for public extensions repository
54 //CONST DEFAULT_EXTENSIONS_REPOSITORY = 'http://civicrm.org/extdir/ver={ver}|cms={uf}';
57 * Extension info file name
59 const EXT_TEMPLATES_DIRNAME
= 'templates';
62 * @var CRM_Extension_Container_Interface
67 * @var array (key => CRM_Extension_Info)
69 protected $infos = array();
74 protected $moduleExtensions = NULL;
77 * @var CRM_Utils_Cache_Interface
83 protected $civicrmPath;
85 protected $civicrmUrl;
87 public function __construct(CRM_Extension_Container_Interface
$container, CRM_Utils_Cache_Interface
$cache = NULL, $cacheKey = NULL, $civicrmPath = NULL, $civicrmUrl = NULL) {
88 $this->container
= $container;
89 $this->cache
= $cache;
90 $this->cacheKey
= $cacheKey;
92 $this->civicrmUrl
= rtrim($civicrmUrl, '/');
94 $config = CRM_Core_Config
::singleton();
95 $this->civicrmUrl
= rtrim($config->resourceBase
, '/');
98 $this->civicrmPath
= rtrim($civicrmPath,'/');
100 global $civicrm_root;
101 $this->civicrmPath
= rtrim($civicrm_root,'/');
106 * Given the class, provides extension's key.
110 * @param string $clazz extension class name
112 * @return string name of extension key
114 public function classToKey($clazz) {
115 return str_replace('_', '.', $clazz);
119 * Given the class, provides extension path.
123 * @param string $key extension key
125 * @return string full path the extension .php file
127 public function classToPath($clazz) {
128 $elements = explode('_', $clazz);
129 $key = implode('.', $elements);
130 return $this->keyToPath($key);
134 * Given the string, returns true or false if it's an extension key.
138 * @param string $key a string which might be an extension key
140 * @return boolean true if given string is an extension name
142 public function isExtensionKey($key) {
143 // check if the string is an extension name or the class
144 return (strpos($key, '.') !== FALSE) ?
TRUE : FALSE;
148 * Given the string, returns true or false if it's an extension class name.
152 * @param string $clazz a string which might be an extension class name
154 * @return boolean true if given string is an extension class name
156 public function isExtensionClass($clazz) {
158 if (substr($clazz, 0, 4) != 'CRM_') {
159 return (bool) preg_match('/^[a-z0-9]+(_[a-z0-9]+)+$/', $clazz);
165 * @param string $key extension fully-qualified-name
166 * @return object CRM_Extension_Info
168 public function keyToInfo($key, $fresh = FALSE) {
169 if ($fresh ||
!array_key_exists($key, $this->infos
)) {
171 $this->infos
[$key] = CRM_Extension_Info
::loadFromFile($this->container
->getPath($key) . DIRECTORY_SEPARATOR
. CRM_Extension_Info
::FILENAME
);
172 } catch (CRM_Extension_Exception
$e) {
173 // file has more detailed info, but we'll fallback to DB if it's missing -- DB has enough info to uninstall
174 $this->infos
[$key] = CRM_Extension_System
::singleton()->getManager()->createInfoFromDB($key);
175 if (!$this->infos
[$key]) {
180 return $this->infos
[$key];
184 * Given the key, provides extension's class name.
188 * @param string $key extension key
190 * @return string name of extension's main class
192 public function keyToClass($key) {
193 return str_replace('.', '_', $key);
197 * Given the key, provides the path to file containing
198 * extension's main class.
202 * @param string $key extension key
204 * @return string path to file containing extension's main class
206 public function keyToPath($key) {
207 $info = $this->keyToInfo($key);
208 return $this->container
->getPath($key) . DIRECTORY_SEPARATOR
. $info->file
. '.php';
212 * Given the key, provides the path to file containing
213 * extension's main class.
216 * @param string $key extension key
217 * @return string local path of the extension source tree
219 public function keyToBasePath($key) {
220 if ($key == 'civicrm') {
221 return $this->civicrmPath
;
223 return $this->container
->getPath($key);
227 * Given the key, provides the path to file containing
228 * extension's main class.
232 * @param string $key extension key
234 * @return string url for resources in this extension
236 public function keyToUrl($key) {
237 if ($key == 'civicrm') {
238 return $this->civicrmUrl
;
241 return $this->container
->getResUrl($key);
245 * Fetch the list of active extensions of type 'module'
247 * @param $fresh bool whether to forcibly reload extensions list from canonical store
248 * @return array - array(array('prefix' => $, 'file' => $))
250 public function getActiveModuleFiles($fresh = FALSE) {
251 $config = CRM_Core_Config
::singleton();
252 if ($config->isUpgradeMode() ||
!defined('CIVICRM_DSN')) {
253 return array(); // hmm, ok
256 $moduleExtensions = NULL;
257 if ($this->cache
&& !$fresh) {
258 $moduleExtensions = $this->cache
->get($this->cacheKey
. '/moduleFiles');
261 if (!is_array($moduleExtensions)) {
262 // Check canonical module list
263 $moduleExtensions = array();
265 SELECT full_name, file
266 FROM civicrm_extension
270 $dao = CRM_Core_DAO
::executeQuery($sql);
271 while ($dao->fetch()) {
273 $moduleExtensions[] = array(
274 'prefix' => $dao->file
,
275 'filePath' => $this->keyToPath($dao->full_name
),
277 } catch (CRM_Extension_Exception
$e) {
278 // Putting a stub here provides more consistency
279 // in how getActiveModuleFiles when racing between
280 // dirty file-removals and cache-clears.
281 CRM_Core_Session
::setStatus($e->getMessage(), '', 'error');
282 $moduleExtensions[] = array(
283 'prefix' => $dao->file
,
290 $this->cache
->set($this->cacheKey
. '/moduleFiles', $moduleExtensions);
293 return $moduleExtensions;
296 public function isActiveModule($name) {
297 $activeModules = $this->getActiveModuleFiles();
298 foreach ($activeModules as $activeModule) {
299 if ($activeModule['prefix'] == $name) {
307 * Get a list of all installed modules, including enabled and disabled ones
309 * @return array CRM_Core_Module
311 public function getModules() {
313 $dao = new CRM_Core_DAO_Extension();
314 $dao->type
= 'module';
316 while ($dao->fetch()) {
317 $result[] = new CRM_Core_Module($dao->full_name
, $dao->is_active
);
323 * Given the class, provides the template path.
327 * @param string $clazz extension class name
329 * @return string path to extension's templates directory
331 public function getTemplatePath($clazz) {
332 $path = $this->container
->getPath($this->classToKey($clazz));
333 return $path . DIRECTORY_SEPARATOR
. self
::EXT_TEMPLATES_DIRNAME
;
335 $path = $this->classToPath($clazz);
336 $pathElm = explode(DIRECTORY_SEPARATOR, $path);
338 return implode(DIRECTORY_SEPARATOR, $pathElm) . DIRECTORY_SEPARATOR . self::EXT_TEMPLATES_DIRNAME;
343 * Given te class, provides the template name.
344 * @todo consider multiple templates, support for one template for now
348 * @param string $clazz extension class name
350 * @return string extension's template name
352 public function getTemplateName($clazz) {
353 $info = $this->keyToInfo($this->classToKey($clazz));
354 return (string) $info->file
. '.tpl';
357 public function refresh() {
358 $this->infos
= array();
359 $this->moduleExtensions
= NULL;
361 $this->cache
->delete($this->cacheKey
. '/moduleFiles');