drupal-civicrm/sites/all/modules/civicrm/Civi/Angular/ChangeSet.php
2018-01-14 13:10:16 +00:00

192 lines
4.8 KiB
PHP

<?php
namespace Civi\Angular;
class ChangeSet implements ChangeSetInterface {
/**
* Update a listing of resources.
*
* @param array $changeSets
* Array(ChangeSet).
* @param string $resourceType
* Ex: 'requires', 'settings'
* @param array $resources
* The list of resources.
* @return mixed
*/
public static function applyResourceFilters($changeSets, $resourceType, $resources) {
if ($resourceType === 'partials') {
return self::applyHtmlFilters($changeSets, $resources);
}
foreach ($changeSets as $changeSet) {
/** @var ChangeSet $changeSet */
foreach ($changeSet->resFilters as $filter) {
if ($filter['resourceType'] === $resourceType) {
$resources = call_user_func($filter['callback'], $resources);
}
}
}
return $resources;
}
/**
* Update a set of HTML snippets.
*
* @param array $changeSets
* Array(ChangeSet).
* @param array $strings
* Array(string $path => string $html).
* @return array
* Updated list of $strings.
* @throws \CRM_Core_Exception
*/
private static function applyHtmlFilters($changeSets, $strings) {
$coder = new Coder();
foreach ($strings as $path => $html) {
/** @var \phpQueryObject $doc */
$doc = NULL;
// Most docs don't need phpQueryObject. Initialize phpQuery on first match.
foreach ($changeSets as $changeSet) {
/** @var ChangeSet $changeSet */
foreach ($changeSet->htmlFilters as $filter) {
if (preg_match($filter['regex'], $path)) {
if ($doc === NULL) {
$doc = \phpQuery::newDocument($html, 'text/html');
if (\CRM_Core_Config::singleton()->debug && !$coder->checkConsistentHtml($html)) {
throw new \CRM_Core_Exception("Cannot process $path: inconsistent markup. Use check-angular.php to investigate.");
}
}
call_user_func($filter['callback'], $doc, $path);
}
}
}
if ($doc !== NULL) {
$strings[$path] = $coder->encode($doc);
}
}
return $strings;
}
/**
* @var string
*/
protected $name;
/**
* @var array
* Each item is an array with keys:
* - resourceType: string
* - callback: function
*/
protected $resFilters = array();
/**
* @var array
* Each item is an array with keys:
* - regex: string
* - callback: function
*/
protected $htmlFilters = array();
/**
* @param string $name
* Symbolic name for this changeset.
* @return \Civi\Angular\ChangeSetInterface
*/
public static function create($name) {
$changeSet = new ChangeSet();
$changeSet->name = $name;
return $changeSet;
}
/**
* Declare that $module requires additional dependencies.
*
* @param string $module
* @param string|array $dependencies
* @return ChangeSet
*/
public function requires($module, $dependencies) {
$dependencies = (array) $dependencies;
return $this->alterResource('requires',
function ($values) use ($module, $dependencies) {
if (!isset($values[$module])) {
$values[$module] = array();
}
$values[$module] = array_unique(array_merge($values[$module], $dependencies));
return $values;
});
}
/**
* Declare a change to a resource.
*
* @param string $resourceType
* @param callable $callback
* @return ChangeSet
*/
public function alterResource($resourceType, $callback) {
$this->resFilters[] = array(
'resourceType' => $resourceType,
'callback' => $callback,
);
return $this;
}
/**
* Declare a change to HTML.
*
* @param string $file
* A file name, wildcard, or regex.
* Ex: '~/crmHello/intro.html' (filename)
* Ex: '~/crmHello/*.html' (wildcard)
* Ex: ';(Edit|List)Ctrl\.html$;' (regex)
* @param callable $callback
* Function which accepts up to two parameters:
* - phpQueryObject $doc
* - string $path
* @return ChangeSet
*/
public function alterHtml($file, $callback) {
$this->htmlFilters[] = array(
'regex' => ($file{0} === ';') ? $file : $this->createRegex($file),
'callback' => $callback,
);
return $this;
}
/**
* Convert a string with a wildcard (*) to a regex.
*
* @param string $filterExpr
* Ex: "/foo/*.bar"
* @return string
* Ex: ";^/foo/[^/]*\.bar$;"
*/
protected function createRegex($filterExpr) {
$regex = preg_quote($filterExpr, ';');
$regex = str_replace('\\*', '[^/]*', $regex);
$regex = ";^$regex$;";
return $regex;
}
/**
* @return string
*/
public function getName() {
return $this->name;
}
/**
* @param string $name
*/
public function setName($name) {
$this->name = $name;
}
}