*/ 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; } /** * @param array $xml */ public function __construct($allCaseTypes = NULL, $xml = array()) { $this->allCaseTypes = $allCaseTypes; $this->xml = $xml; } /** * @param string $caseType * @return SimpleXMLElement|FALSE */ 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]; } /** * @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(); $dom->load($fileName); $dom->xinclude(); $fileXml = simplexml_import_dom($dom); } return $fileXml; } /** * @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 symbolic names of case-types */ public function getAllCaseTypes() { if ($this->allCaseTypes === NULL) { $this->allCaseTypes = CRM_Case_PseudoConstant::caseType("name"); } return $this->allCaseTypes; } /** * @return array 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 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; } }