Merge pull request #3696 from davecivicrm/CRM-15002
[civicrm-core.git] / CRM / Case / XMLRepository.php
index fec0ff2f32fe00a5c91192ab6dd8e3e1de694070..5193f468c6ea024a317c58006e90ceec38333478 100644 (file)
@@ -32,6 +32,8 @@
  * $Id$
  *
  * 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;
@@ -53,7 +55,7 @@ class CRM_Case_XMLRepository {
 
   /**
    * @param bool $fresh
-   * @return CRM_Case_XMLProcessor
+   * @return CRM_Case_XMLRepository
    */
   public static function singleton($fresh = FALSE) {
     if (!self::$singleton || $fresh) {
@@ -65,7 +67,8 @@ class CRM_Case_XMLRepository {
   /**
    * @param array<String,SimpleXMLElement> $xml
    */
-  public function __construct($xml = array()) {
+  public function __construct($allCaseTypes = NULL, $xml = array()) {
+    $this->allCaseTypes = $allCaseTypes;
     $this->xml = $xml;
   }
 
@@ -74,15 +77,58 @@ class CRM_Case_XMLRepository {
    * @return SimpleXMLElement|FALSE
    */
   public function retrieve($caseType) {
-    $caseType = CRM_Case_XMLProcessor::mungeCaseType($caseType);
+    // check if xml definition is defined in db
+    $definition = CRM_Core_DAO::getFieldValue('CRM_Case_DAO_CaseType', $caseType, 'definition', 'name');
+
+    if (!empty($definition)) {
+      return simplexml_load_string($definition);
+    }
+
+    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)) {
-      // first check custom templates directory
-      $fileName = NULL;
+      // Search for a file based directly on the $caseType name
+      $fileName = $this->findXmlFile($caseType);
+
+      // For backward compatibility, also search for double-mungd 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)) {
+        return FALSE;
+      }
+
+      // read xml file
+      $dom = new DomDocument();
+      $dom->load($fileName);
+      $dom->xinclude();
+      $this->xml[$caseType] = simplexml_import_dom($dom);
+    }
+    return $this->xml[$caseType];
+  }
+
+  /**
+   * @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
-      ) {
+      if (isset($config->customTemplateDir) && $config->customTemplateDir) {
         // check if the file exists in the custom templates directory
         $fileName = implode(DIRECTORY_SEPARATOR,
           array(
@@ -95,10 +141,10 @@ class CRM_Case_XMLRepository {
           )
         );
       }
+    }
 
-      if (!$fileName ||
-        !file_exists($fileName)
-      ) {
+    if (!$fileName || !file_exists($fileName)) {
+      if (!file_exists($fileName)) {
         // check if file exists locally
         $fileName = implode(DIRECTORY_SEPARATOR,
           array(
@@ -108,38 +154,21 @@ class CRM_Case_XMLRepository {
             "$caseType.xml",
           )
         );
-
-        if (!file_exists($fileName)) {
-          // check if file exists locally
-          $fileName = implode(DIRECTORY_SEPARATOR,
-            array(
-              dirname(__FILE__),
-              'xml',
-              'configuration.sample',
-              "$caseType.xml",
-            )
-          );
-        }
-
-        if (!file_exists($fileName)) {
-          $caseTypesViaHook = $this->getCaseTypesViaHook();
-          if (isset($caseTypesViaHook[$caseType], $caseTypesViaHook[$caseType]['file'])) {
-            $fileName = $caseTypesViaHook[$caseType]['file'];
-          }
-        }
-
-        if (!file_exists($fileName)) {
-          return FALSE;
-        }
       }
 
-      // read xml file
-      $dom = new DomDocument();
-      $dom->load($fileName);
-      $dom->xinclude();
-      $this->xml[$caseType] = simplexml_import_dom($dom);
+      if (!file_exists($fileName)) {
+        // check if file exists locally
+        $fileName = implode(DIRECTORY_SEPARATOR,
+          array(
+            dirname(__FILE__),
+            'xml',
+            'configuration.sample',
+            "$caseType.xml",
+          )
+        );
+      }
     }
-    return $this->xml[$caseType];
+    return file_exists($fileName) ? $fileName : NULL;
   }
 
   /**
@@ -153,4 +182,87 @@ class CRM_Case_XMLRepository {
     }
     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
+   */
+  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
+   */
+  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;
+  }
+
 }