Beispiel #1
0
 /**
  * Relate records.
  *
  * @param array|Garp_Util_Configuration $options Lots o' options:
  * 'modelA'    string|Garp_Model_Db    The first model or classname thereof
  * 'modelB'    string|Garp_Model_Db    The second model or classname thereof
  * 'keyA'      mixed                   Primary key(s) of the first model
  * 'keyB'      mixed                   Primary key(s) of the second model
  * 'rule'      string                  The rule that stores this relationship in one
  *                                     of the reference maps
  * 'extraFields' Array                 Extra fields that can be saved with a HABTM record
  * @return bool Success
  */
 public static function relate($options)
 {
     self::_normalizeOptionsForRelate($options);
     $modelA = $options['modelA'];
     $modelB = $options['modelB'];
     /**
      * If bindingModel is set, we can safely skip all those difficult checks below.
      */
     if (is_object($options['bindingModel'])) {
         return self::_relateHasAndBelongsToMany($options);
     }
     try {
         /**
          * If this succeeds, it's a regular relationship where the foreign key
          * resides inside modelA. Continue as usual.
          */
         $reference = $modelA->getReference(get_class($modelB), $options['rule']);
     } catch (Exception $e) {
         if (!self::isInvalidReferenceException($e)) {
             throw $e;
         }
         try {
             /**
              * If this succeeds, the foreign key resides in the modelA.
              * Flip modelA and modelB and keyA and keyB in order to normalize
              * the given configuration.
              * Call self::relate() recursively with these new options.
              */
             $reference = $modelB->getReference(get_class($modelA), $options['rule']);
             $keyA = $options['keyA'];
             $keyB = $options['keyB'];
             $options['modelA'] = $modelB;
             $options['modelB'] = $modelA;
             $options['keyA'] = $keyB;
             $options['keyB'] = $keyA;
             return Garp_Content_Relation_Manager::relate($options);
         } catch (Exception $e) {
             if (!self::isInvalidReferenceException($e)) {
                 throw $e;
             }
             /**
              * Goody, we're dealing with a hasAndBelongsToMany relationship here.
              * Try to construct the intersection model and save the relation
              * that way.
              */
             return self::_relateHasAndBelongsToMany($options);
         }
     }
     $rowA = call_user_func_array(array($options['modelA'], 'find'), (array) $options['keyA']);
     if (!count($rowA)) {
         $errorMsg = sprintf(self::EXCEPTION_ROW_NOT_FOUND_BY_PRIMARY_KEY, $modelA->getName(), implode(',', (array) $options['keyA']));
         throw new Garp_Content_Relation_Exception($errorMsg);
     }
     $rowA = $rowA->current();
     self::_addForeignKeysToRow($rowA, $reference, $options['keyB']);
     return $rowA->save();
 }
Beispiel #2
0
 /**
  * Relate Chapters.
  * Called after insert and after update.
  * @param Array $chapters
  * @param Garp_Model_Db $model The subject model
  * @param Int $articleId The id of the involved article
  * @return Void
  */
 public function relateChapters(array $chapters, Garp_Model_Db $model, $articleId)
 {
     // Start by unrelating all chapters
     Garp_Content_Relation_Manager::unrelate(array('modelA' => $model, 'modelB' => 'Model_Chapter', 'keyA' => $articleId));
     // Reverse order since the Weighable behavior sorts chapter by weight DESC,
     // giving each new chapter the highest weight.
     $chapters = array_reverse($chapters);
     foreach ($chapters as $chapterData) {
         $chapterData = $this->_getValidChapterData($chapterData);
         /**
          * Insert a new chapter.
          * The chapter will take care of storing and relating the
          * content nodes.
          */
         $chapterModel = new Model_Chapter();
         $chapterId = $chapterModel->insert(array('type' => $chapterData['type'], 'content' => $chapterData['content']));
         Garp_Content_Relation_Manager::relate(array('modelA' => $model, 'modelB' => 'Model_Chapter', 'keyA' => $articleId, 'keyB' => $chapterId));
     }
 }
Beispiel #3
0
 /**
  * Relate entities to each other, optionally removing previous existing relations.
  *
  * @param array $options
  * @return bool
  */
 public function relate(array $options)
 {
     $this->_checkAcl('relate');
     extract($options);
     if (!isset($primaryKey) || !isset($model) || !isset($foreignKeys)) {
         throw new Garp_Content_Exception('Not enough options. "primaryKey", "model" and "foreignKeys" are required.');
     }
     $model = Garp_Content_Api::modelAliasToClass($model);
     $primaryKey = (array) $primaryKey;
     $foreignKeys = (array) $foreignKeys;
     $rule = isset($rule) ? $rule : null;
     $rule2 = isset($rule2) ? $rule2 : null;
     $bindingModel = isset($bindingModel) ? 'Model_' . $bindingModel : null;
     $bidirectional = isset($bidirectional) ? $bidirectional : null;
     if (array_key_exists('unrelateExisting', $options) && $options['unrelateExisting']) {
         Garp_Content_Relation_Manager::unrelate(array('modelA' => $this->_model, 'modelB' => $model, 'keyA' => $primaryKey, 'rule' => $rule, 'ruleB' => $rule2, 'bindingModel' => $bindingModel, 'bidirectional' => $bidirectional));
     }
     $success = $attempts = 0;
     foreach ($foreignKeys as $i => $relationData) {
         if (!array_key_exists('key', $relationData)) {
             throw new Garp_Content_Exception('Foreign key is a required key.');
         }
         $foreignKey = $relationData['key'];
         $extraFields = array_key_exists('relationMetadata', $relationData) ? $relationData['relationMetadata'] : array();
         if (Garp_Content_Relation_Manager::relate(array('modelA' => $this->_model, 'modelB' => $model, 'keyA' => $primaryKey, 'keyB' => $foreignKey, 'extraFields' => $extraFields, 'rule' => $rule, 'ruleB' => $rule2, 'bindingModel' => $bindingModel, 'bidirectional' => $bidirectional))) {
             $success++;
         }
         $attempts++;
     }
     return $success == $attempts;
 }
Beispiel #4
0
 /**
  * Relate ContentNodes to a chapter.
  * @param Array $contentNodeList
  * @param Int $chapterId
  * @return Void
  */
 public function relateContentNodes($contentNodeList, $chapterId)
 {
     // Reverse node list because the Weighable behavior sorts different from the way
     // the CMS sends us the nodes.
     $contentNodeList = array_reverse($contentNodeList);
     foreach ($contentNodeList as $contentNode) {
         $node = $this->_getValidContentNodeData($contentNode);
         // Save ContentNode
         $node['chapter_id'] = $chapterId;
         $contentNodeId = $this->_insertContentNode($node);
         // @todo Move everything below here to Model_ContentNode::afterInsert()
         // Determine content type
         $contentTypeModelName = 'Model_' . $node['model'];
         $contentTypeModel = new $contentTypeModelName();
         // Check for existing id
         $data = $node['data'];
         if (empty($data['id'])) {
             // If no id is present, create a new subtype record
             $contentTypeId = $contentTypeModel->insert($data);
         } else {
             // Update the chapter subtype's content
             $contentTypeModel->update($data, 'id = ' . $contentTypeModel->getAdapter()->quote($data['id']));
             $contentTypeId = $data['id'];
         }
         // Relate the ContentNode to the subtype record
         Garp_Content_Relation_Manager::relate(array('modelA' => 'Model_ContentNode', 'modelB' => $contentTypeModel, 'keyA' => $contentNodeId, 'keyB' => $contentTypeId));
     }
 }