Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,19 @@
<version>0.2</version>
<develStage>alpha</develStage>
<compatibility>
<ver>4.6</ver>
<ver>4.7</ver>
<ver>5.0</ver>
<ver>5.27</ver>
</compatibility>
<comments></comments>
<comments/>
<civix>
<namespace>CRM/Splitgroup</namespace>
<format>23.02.1</format>
</civix>
<mixins>
<mixin>menu-xml@1.0.0</mixin>
<mixin>smarty-v2@1.0.1</mixin>
</mixins>
<classloader>
<psr0 prefix="CRM_" path="."/>
<psr4 prefix="Civi\" path="Civi"/>
</classloader>
</extension>
31 changes: 31 additions & 0 deletions mixin/menu-xml@1.0.0.mixin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

/**
* Auto-register "xml/Menu/*.xml" files.
*
* @mixinName menu-xml
* @mixinVersion 1.0.0
*
* @param CRM_Extension_MixInfo $mixInfo
* On newer deployments, this will be an instance of MixInfo. On older deployments, Civix may polyfill with a work-a-like.
* @param \CRM_Extension_BootCache $bootCache
* On newer deployments, this will be an instance of MixInfo. On older deployments, Civix may polyfill with a work-a-like.
*/
return function ($mixInfo, $bootCache) {

/**
* @param \Civi\Core\Event\GenericHookEvent $e
* @see CRM_Utils_Hook::xmlMenu()
*/
Civi::dispatcher()->addListener('hook_civicrm_xmlMenu', function ($e) use ($mixInfo) {
if (!$mixInfo->isActive()) {
return;
}

$files = (array) glob($mixInfo->getPath('xml/Menu/*.xml'));
foreach ($files as $file) {
$e->files[] = $file;
}
});

};
101 changes: 101 additions & 0 deletions mixin/polyfill.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

/**
* When deploying on systems that lack mixin support, fake it.
*
* @mixinFile polyfill.php
*
* This polyfill does some (persnickity) deduplication, but it doesn't allow upgrades or shipping replacements in core.
*
* Note: The polyfill.php is designed to be copied into extensions for interoperability. Consequently, this file is
* not used 'live' by `civicrm-core`. However, the file does need a canonical home, and it's convenient to keep it
* adjacent to the actual mixin files.
*
* @param string $longName
* @param string $shortName
* @param string $basePath
*/
return function ($longName, $shortName, $basePath) {
// Construct imitations of the mixin services. These cannot work as well (e.g. with respect to
// number of file-reads, deduping, upgrading)... but they should be OK for a few months while
// the mixin services become available.

// List of active mixins; deduped by version
$mixinVers = [];
foreach ((array) glob($basePath . '/mixin/*.mixin.php') as $f) {
[$name, $ver] = explode('@', substr(basename($f), 0, -10));
if (!isset($mixinVers[$name]) || version_compare($ver, $mixinVers[$name], '>')) {
$mixinVers[$name] = $ver;
}
}
$mixins = [];
foreach ($mixinVers as $name => $ver) {
$mixins[] = "$name@$ver";
}

// Imitate CRM_Extension_MixInfo.
$mixInfo = new class() {

/**
* @var string
*/
public $longName;

/**
* @var string
*/
public $shortName;

public $_basePath;

public function getPath($file = NULL) {
return $this->_basePath . ($file === NULL ? '' : (DIRECTORY_SEPARATOR . $file));
}

public function isActive() {
return \CRM_Extension_System::singleton()->getMapper()->isActiveModule($this->shortName);
}

};
$mixInfo->longName = $longName;
$mixInfo->shortName = $shortName;
$mixInfo->_basePath = $basePath;

// Imitate CRM_Extension_BootCache.
$bootCache = new class() {

public function define($name, $callback) {
$envId = \CRM_Core_Config_Runtime::getId();
$oldExtCachePath = \Civi::paths()->getPath("[civicrm.compile]/CachedExtLoader.{$envId}.php");
$stat = stat($oldExtCachePath);
$file = Civi::paths()->getPath('[civicrm.compile]/CachedMixin.' . md5($name . ($stat['mtime'] ?? 0)) . '.php');
if (file_exists($file)) {
return include $file;
}
else {
$data = $callback();
file_put_contents($file, '<' . "?php\nreturn " . var_export($data, 1) . ';');
return $data;
}
}

};

// Imitate CRM_Extension_MixinLoader::run()
// Parse all live mixins before trying to scan any classes.
global $_CIVIX_MIXIN_POLYFILL;
foreach ($mixins as $mixin) {
// If the exact same mixin is defined by multiple exts, just use the first one.
if (!isset($_CIVIX_MIXIN_POLYFILL[$mixin])) {
$_CIVIX_MIXIN_POLYFILL[$mixin] = include_once $basePath . '/mixin/' . $mixin . '.mixin.php';
}
}
foreach ($mixins as $mixin) {
// If there's trickery about installs/uninstalls/resets, then we may need to register a second time.
if (!isset(\Civi::$statics[$longName][$mixin])) {
\Civi::$statics[$longName][$mixin] = 1;
$func = $_CIVIX_MIXIN_POLYFILL[$mixin];
$func($mixInfo, $bootCache);
}
}
};
51 changes: 51 additions & 0 deletions mixin/smarty-v2@1.0.1.mixin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

/**
* Auto-register "templates/" folder.
*
* @mixinName smarty-v2
* @mixinVersion 1.0.1
* @since 5.59
*
* @param CRM_Extension_MixInfo $mixInfo
* On newer deployments, this will be an instance of MixInfo. On older deployments, Civix may polyfill with a work-a-like.
* @param \CRM_Extension_BootCache $bootCache
* On newer deployments, this will be an instance of MixInfo. On older deployments, Civix may polyfill with a work-a-like.
*/
return function ($mixInfo, $bootCache) {
$dir = $mixInfo->getPath('templates');
if (!file_exists($dir)) {
return;
}

$register = function() use ($dir) {
// This implementation has a theoretical edge-case bug on older versions of CiviCRM where a template could
// be registered more than once.
CRM_Core_Smarty::singleton()->addTemplateDir($dir);
};

// Let's figure out what environment we're in -- so that we know the best way to call $register().

if (!empty($GLOBALS['_CIVIX_MIXIN_POLYFILL'])) {
// Polyfill Loader (v<=5.45): We're already in the middle of firing `hook_config`.
if ($mixInfo->isActive()) {
$register();
}
return;
}

if (CRM_Extension_System::singleton()->getManager()->extensionIsBeingInstalledOrEnabled($mixInfo->longName)) {
// New Install, Standard Loader: The extension has just been enabled, and we're now setting it up.
// System has already booted. New templates may be needed for upcoming installation steps.
$register();
return;
}

// Typical Pageview, Standard Loader: Defer the actual registration for a moment -- to ensure that Smarty is online.
\Civi::dispatcher()->addListener('hook_civicrm_config', function() use ($mixInfo, $register) {
if ($mixInfo->isActive()) {
$register();
}
});

};
Loading