drupal-civicrm/sites/all/modules/civicrm/CRM/Case/XMLRepository.php
2018-01-14 13:10:16 +00:00

316 lines
9.1 KiB
PHP

<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*
* The XMLRepository is responsible for loading XML for case-types.
* It includes any bulk operations that apply across the list of all XML
* documents of all case-types.
*/
class CRM_Case_XMLRepository {
private static $singleton;
/**
* @var array<String,SimpleXMLElement>
*/
protected $xml = array();
/**
* @var array|NULL
*/
protected $hookCache = NULL;
/**
* @var array|NULL symbolic names of case-types
*/
protected $allCaseTypes = NULL;
/**
* @param bool $fresh
* @return CRM_Case_XMLRepository
*/
public static function singleton($fresh = FALSE) {
if (!self::$singleton || $fresh) {
self::$singleton = new static();
}
return self::$singleton;
}
public function flush() {
$this->xml = array();
$this->hookCache = NULL;
$this->allCaseTypes = NULL;
CRM_Core_DAO::$_dbColumnValueCache = array();
}
/**
* Class constructor.
*
* @param array $allCaseTypes
* @param array $xml
*/
public function __construct($allCaseTypes = NULL, $xml = array()) {
$this->allCaseTypes = $allCaseTypes;
$this->xml = $xml;
}
/**
* Retrieve case.
*
* @param string $caseType
*
* @return FALSE|\SimpleXMLElement
* @throws \CRM_Core_Exception
*/
public function retrieve($caseType) {
// check if xml definition is defined in db
$definition = CRM_Core_DAO::getFieldValue('CRM_Case_DAO_CaseType', $caseType, 'definition', 'name');
if (!empty($definition)) {
list ($xml, $error) = CRM_Utils_XML::parseString($definition);
if (!$xml) {
throw new CRM_Core_Exception("Failed to parse CaseType XML: $error");
}
return $xml;
}
// TODO In 4.6 or 5.0, remove support for weird machine-names
//if (!CRM_Case_BAO_CaseType::isValidName($caseType)) {
// // perhaps caller provider a the label instead of the name?
// throw new CRM_Core_Exception("Cannot load caseType with malformed name [$caseType]");
//}
if (!CRM_Utils_Array::value($caseType, $this->xml)) {
$fileXml = $this->retrieveFile($caseType);
if ($fileXml) {
$this->xml[$caseType] = $fileXml;
}
else {
return FALSE;
}
}
return $this->xml[$caseType];
}
/**
* Retrieve file.
*
* @param string $caseType
* @return SimpleXMLElement|FALSE
*/
public function retrieveFile($caseType) {
$fileName = NULL;
$fileXml = NULL;
if (CRM_Case_BAO_CaseType::isValidName($caseType)) {
// Search for a file based directly on the $caseType name
$fileName = $this->findXmlFile($caseType);
}
// For backward compatibility, also search for double-munged file names
// TODO In 4.6 or 5.0, remove support for loading double-munged file names
if (!$fileName || !file_exists($fileName)) {
$fileName = $this->findXmlFile(CRM_Case_XMLProcessor::mungeCaseType($caseType));
}
if ($fileName && file_exists($fileName)) {
// read xml file
$dom = new DomDocument();
$xmlString = file_get_contents($fileName);
$dom->loadXML($xmlString);
$dom->documentURI = $fileName;
$dom->xinclude();
$fileXml = simplexml_import_dom($dom);
}
return $fileXml;
}
/**
* Find xml file.
*
* @param string $caseType
* @return null|string
* file path
*/
public function findXmlFile($caseType) {
// first check custom templates directory
$fileName = NULL;
if (!$fileName || !file_exists($fileName)) {
$caseTypesViaHook = $this->getCaseTypesViaHook();
if (isset($caseTypesViaHook[$caseType], $caseTypesViaHook[$caseType]['file'])) {
$fileName = $caseTypesViaHook[$caseType]['file'];
}
}
if (!$fileName || !file_exists($fileName)) {
$config = CRM_Core_Config::singleton();
if (isset($config->customTemplateDir) && $config->customTemplateDir) {
// check if the file exists in the custom templates directory
$fileName = implode(DIRECTORY_SEPARATOR,
array(
$config->customTemplateDir,
'CRM',
'Case',
'xml',
'configuration',
"$caseType.xml",
)
);
}
}
if (!$fileName || !file_exists($fileName)) {
if (!file_exists($fileName)) {
// check if file exists locally
$fileName = implode(DIRECTORY_SEPARATOR,
array(
dirname(__FILE__),
'xml',
'configuration',
"$caseType.xml",
)
);
}
if (!file_exists($fileName)) {
// check if file exists locally
$fileName = implode(DIRECTORY_SEPARATOR,
array(
dirname(__FILE__),
'xml',
'configuration.sample',
"$caseType.xml",
)
);
}
}
return file_exists($fileName) ? $fileName : NULL;
}
/**
* @return array
* @see CRM_Utils_Hook::caseTypes
*/
public function getCaseTypesViaHook() {
if ($this->hookCache === NULL) {
$this->hookCache = array();
CRM_Utils_Hook::caseTypes($this->hookCache);
}
return $this->hookCache;
}
/**
* @return array<string> symbolic names of case-types
*/
public function getAllCaseTypes() {
if ($this->allCaseTypes === NULL) {
$this->allCaseTypes = CRM_Case_PseudoConstant::caseType("name");
}
return $this->allCaseTypes;
}
/**
* @return array<string> symbolic-names of activity-types
*/
public function getAllDeclaredActivityTypes() {
$result = array();
$p = new CRM_Case_XMLProcessor_Process();
foreach ($this->getAllCaseTypes() as $caseTypeName) {
$caseTypeXML = $this->retrieve($caseTypeName);
$result = array_merge($result, $p->getDeclaredActivityTypes($caseTypeXML));
}
$result = array_unique($result);
sort($result);
return $result;
}
/**
* @return array<string> symbolic-names of relationship-types
*/
public function getAllDeclaredRelationshipTypes() {
$result = array();
$p = new CRM_Case_XMLProcessor_Process();
foreach ($this->getAllCaseTypes() as $caseTypeName) {
$caseTypeXML = $this->retrieve($caseTypeName);
$result = array_merge($result, $p->getDeclaredRelationshipTypes($caseTypeXML));
}
$result = array_unique($result);
sort($result);
return $result;
}
/**
* Determine the number of times a particular activity-type is
* referenced in CiviCase XML.
*
* @param string $activityType
* Symbolic-name of an activity type.
* @return int
*/
public function getActivityReferenceCount($activityType) {
$p = new CRM_Case_XMLProcessor_Process();
$count = 0;
foreach ($this->getAllCaseTypes() as $caseTypeName) {
$caseTypeXML = $this->retrieve($caseTypeName);
if (in_array($activityType, $p->getDeclaredActivityTypes($caseTypeXML))) {
$count++;
}
}
return $count;
}
/**
* Determine the number of times a particular activity-type is
* referenced in CiviCase XML.
*
* @param string $relationshipTypeName
* Symbolic-name of a relationship-type.
* @return int
*/
public function getRelationshipReferenceCount($relationshipTypeName) {
$p = new CRM_Case_XMLProcessor_Process();
$count = 0;
foreach ($this->getAllCaseTypes() as $caseTypeName) {
$caseTypeXML = $this->retrieve($caseTypeName);
if (in_array($relationshipTypeName, $p->getDeclaredRelationshipTypes($caseTypeXML))) {
$count++;
}
}
return $count;
}
}