protected function _getNodeRefs()
 {
     $noderefs = $this->Request->getParameter('NodeRefs');
     if (!empty($noderefs) && strlen($noderefs) > 0) {
         $noderefs = StringUtils::smartSplit($noderefs, ',');
         $noderefObjs = array();
         foreach ($noderefs as $noderef) {
             $nr = $this->NodeRefService->parseFromString($noderef);
             if ($nr != null) {
                 $noderefObjs[] = $nr;
             }
         }
         return $noderefObjs;
     } else {
         return array();
     }
 }
 public function execute()
 {
     $this->_beginBulkaction();
     $noderefs = $this->_getNodeRefs();
     $tags = $this->Request->getParameter('Tags');
     $tagStrings = array();
     if (!empty($tags)) {
         $tagStrings = StringUtils::smartSplit($tags);
     }
     foreach ($noderefs as $noderef) {
         try {
             foreach ($tagStrings as $tagString) {
                 $this->RegulatedNodeService->addOutTag($noderef, new Tag($tagString));
             }
             $this->_updateBulkaction($noderef->getElement()->Slug, $noderef->Slug);
         } catch (Exception $e) {
             $this->_failureBulkaction($e->getMessage(), $noderef->getElement()->Slug, $noderef->Slug);
         }
     }
     return $this->_endBulkaction();
 }
 public function __construct($tagOrElement, $slug = '', $role = '', $value = '')
 {
     if ($tagOrElement instanceof TagPartial || $tagOrElement instanceof Tag) {
         $this->fields = $tagOrElement->toArray();
         return;
     }
     $this->fields = array_merge($this->fields, array('TagElement' => '', 'TagAspect' => '', 'TagSlug' => '', 'TagRole' => '', 'TagValue' => ''));
     if (is_array($tagOrElement)) {
         $this->fields = array_merge($this->fields, $tagOrElement);
     } else {
         if (is_string($tagOrElement)) {
             // assume first param is element
             if (!empty($slug) || !empty($role) || !empty($value)) {
                 if (substr($tagOrElement, 0, 1) == '@') {
                     $this->fields['TagAspect'] = substr($tagOrElement, 1);
                 } else {
                     $this->fields['TagElement'] = $tagOrElement;
                 }
                 $this->fields['TagSlug'] = $slug;
                 $this->fields['TagRole'] = $role;
                 $this->fields['TagValue'] = $value;
                 // assume first param is tag string
             } else {
                 $expressions = StringUtils::smartSplit($tagOrElement, ".", '"', '\\"', 2);
                 if (preg_match("/^(((?P<ai>@)?(?P<el>[a-z0-9-]+))?(:(?P<s>[a-z0-9\\/\\-]+)?)?)?(#(?P<r>[a-z0-9-]+)?)?(=(?P<v>.+?))?\$/", array_shift($expressions), $m)) {
                     if (!empty($m['ai'])) {
                         $this->fields['TagAspect'] = !empty($m['el']) ? $m['el'] : '';
                     } else {
                         $this->fields['TagElement'] = !empty($m['el']) ? $m['el'] : '';
                     }
                     $this->fields['TagSlug'] = !empty($m['s']) ? $m['s'] : '';
                     $this->fields['TagRole'] = !empty($m['r']) ? $m['r'] : '';
                     $this->fields['TagValue'] = !empty($m['v']) ? $m['v'] : '';
                     if (!empty($expressions)) {
                         //                            if(count($expressions) > 1)
                         $this->fields['ChildPartials'] = current($expressions);
                         //                            else
                         //                                $this->fields['ChildPartial'] = $expressions[0];
                     }
                 }
             }
         } else {
             throw new Exception('Invalid parameter to TagPartial: ' . ClassUtils::getQualifiedType($tagOrElement));
         }
     }
     if (empty($this->fields['TagElement']) && empty($this->fields['TagAspect']) && empty($this->fields['TagRole'])) {
         throw new TagException('Invalid partial: No element, aspect, or role was specified [' . print_r($tagOrElement, true) . ']');
     }
     if (!empty($this->fields['TagAspect'])) {
         //            $this->fields['TagAspect'] = strtolower($this->fields['TagAspect']);
         if (!preg_match("/[a-z0-9-]+/", $this->fields['TagAspect'])) {
             throw new TagException('Invalid partial: Aspect "' . $this->fields['TagAspect'] . '" must contain only characters or dash');
         }
     }
     if (!empty($this->fields['TagSlug'])) {
         $this->fields['TagSlug'] = strtolower($this->fields['TagSlug']);
         if (!SlugUtils::isSlug($this->fields['TagSlug'], true)) {
             throw new TagException('Invalid tag: "' . $this->fields['TagSlug'] . '" must be valid slug');
         }
     }
     if (!empty($this->fields['TagRole']) && !SlugUtils::isSlug($this->fields['TagRole'])) {
         $this->fields['TagRole'] = SlugUtils::createSlug($this->fields['TagRole']);
     }
     if (!empty($this->fields['TagValue']) && !SlugUtils::isSlug($this->fields['TagValue'])) {
         $this->fields['TagValue'] = SlugUtils::createSlug($this->fields['TagValue']);
     }
     // lowercase all parts
     foreach (array('TagElement', 'TagAspect', 'TagSlug', 'TagRole', 'TagValue') as $name) {
         $this->fields[$name] = strtolower($this->fields[$name]);
     }
 }
 protected function findTags($direction, $db, NodeRef $originNodeRef, $ids, $partials = 'fields', $forceReadWrite = false, $checkJumpPermissions = false, $restrictedPartials, $resolveLinkedRecords = true, $existingRows = null)
 {
     if (!is_null($db) && !$db instanceof DatabaseInterface) {
         throw new NodeException('Argument 2 passed to NodeTagsDAO::findTags() must implement interface DatabaseInterface');
     }
     $results = array();
     if (empty($partials)) {
         return $results;
     }
     $returnOne = false;
     if (!is_array($ids)) {
         $returnOne = $ids;
         $ids = array($originNodeRef->getRefURL() => $ids);
     }
     $fixedId = false;
     if (!is_null($existingRows)) {
         $fixedId = 1;
         $returnOne = 1;
     }
     $tagFields = $this->tagFields;
     $this->Logger->debug('findTags [' . $direction . '] with partials [' . $partials . '] restrict [' . $restrictedPartials . ']');
     if ($direction == 'out') {
         $table = $this->NodeDBMeta->getOutTagsTable($originNodeRef);
         $partials = PartialUtils::unserializeOutPartials($partials);
         $restrictedPartials = PartialUtils::unserializeOutPartials($restrictedPartials);
     } else {
         $table = $this->NodeDBMeta->getInTagsTable($originNodeRef);
         $partials = PartialUtils::unserializeInPartials($partials);
         $restrictedPartials = PartialUtils::unserializeInPartials($restrictedPartials);
         //            $tagFields[] = 'TagOutID';
     }
     //        $this->Logger->debug($partials);
     $tableid = $this->NodeDBMeta->getPrimaryKey($originNodeRef);
     $now = $this->DateFactory->newLocalDate();
     $rows = array();
     $fieldlikePartials = array();
     $childexprPartials = array();
     $addlParams = array();
     $jumpParams = array();
     $fieldlikeRoles = array();
     $nonfieldlikeRoles = array();
     $outRoles = array();
     $all = false;
     $allfieldlike = false;
     $tagDefs = array();
     if ($partials == 'all' || ($x = array_search('all', $partials)) !== false) {
         $all = true;
         $partials = array();
     } else {
         if (($x = array_search('fields', $partials)) !== false) {
             $allfieldlike = true;
             unset($partials[$x]);
         }
     }
     if ($restrictedPartials == 'all' || ($x = array_search('all', $restrictedPartials)) !== false) {
         return array();
     }
     $tagDefs = $originNodeRef->getElement()->getSchema()->getTagDefs();
     foreach ($originNodeRef->getElement()->getSchema()->getTagDefs() as $role => $tagDef) {
         if ($tagDef->isFieldlike() && strtolower($tagDef->Direction) == $direction) {
             $fieldlikeRoles[] = $role;
         }
         if ($tagDef->Direction == 'out') {
             $outRoles[] = $role;
         }
     }
     foreach ($partials as $x => $outPartial) {
         if ($outPartial['TagRole'] == false) {
             throw new TagException('Tag partials must specify a role when retrieving tags');
         }
         if (in_array($outPartial['TagRole'], $fieldlikeRoles)) {
             $fieldlikePartials[] = $outPartial;
             unset($partials[$x]);
         }
         if ($resolveLinkedRecords && $outPartial->hasChildPartials()) {
             $childexprPartials[$outPartial['TagRole']][] = $outPartial;
         }
     }
     // tags passed to us, no need to query database
     if (is_null($existingRows)) {
         if ($allfieldlike == true || !empty($fieldlikePartials)) {
             $cachedIds = array();
             // read from cache
             list($cachedIds, $rows) = $this->NodeCache->getTags($direction, $ids, $forceReadWrite);
             $remainingIds = array_diff($ids, $cachedIds);
             if (!empty($remainingIds)) {
                 $dbToCacheRows = array();
                 if (!empty($fieldlikeRoles)) {
                     $q = new Query();
                     $q->SELECT($tableid . ' as ID');
                     $q->SELECT($tagFields);
                     // Commented out on 2/1/2010 by Craig .. Mysql seems to be using the right indexes without this.
                     // $q->FROM($db->quoteIdentifier($table).' FORCE INDEX(RoleOnly)');
                     $q->FROM($db->quoteIdentifier($table));
                     $q->WHERE("{$tableid} IN ({$db->joinQuote((array) $remainingIds)})");
                     $q->WHERE("Role IN ({$db->joinQuote((array) $fieldlikeRoles)})");
                     $dbRows = $this->getConnectionForWrite($originNodeRef)->readAll($q);
                     foreach ($dbRows as $row) {
                         $dbToCacheRows[$row['ID']][] = $row;
                         $rows[] = $row;
                     }
                 }
                 $this->NodeCache->putTags($direction, $remainingIds, $dbToCacheRows, $forceReadWrite);
             }
         }
         if ($all) {
             $q = new Query();
             //                if($forceReadWrite)
             //                    $q->forUpdate();
             $q->SELECT($tableid . ' as ID');
             $q->SELECT($tagFields);
             $q->FROM($db->quoteIdentifier($table));
             $q->WHERE("{$tableid} IN ({$db->joinQuote((array) $ids)})");
             //                $q->WHERE("SectionID = 0");
             $rows = $db->readAll($q);
         } else {
             $runPartials = array();
             // perform a SQL statement per partial
             foreach ($partials as $outPartial) {
                 if (in_array($outPartial->toString(), $runPartials)) {
                     continue;
                 }
                 if ($outPartial['TagRole'] == false) {
                     throw new TagException('Tag partials must specify a role when retrieving tags');
                 }
                 if ($direction == 'out' && !in_array($outPartial['TagRole'], $outRoles)) {
                     continue;
                 }
                 $unions = array();
                 foreach ((array) $ids as $id) {
                     $q = new Query();
                     $q->SELECT($tableid . ' as ID');
                     $q->SELECT($tagFields);
                     $q->FROM($db->quoteIdentifier($table));
                     //                        $q->WHERE("$tableid IN ({$db->joinQuote((array)$ids)})");
                     $q->WHERE("{$tableid} = {$db->quote($id)}");
                     //                    $q->WHERE("SectionID = 0");
                     if ($direction == 'out') {
                         $q->WHERE($this->getOutTagPartialClause($outPartial, $db, $db->quoteIdentifier($table)));
                     } else {
                         $q->WHERE($this->getInTagPartialClause($outPartial, $originNodeRef->getElement(), $db, $db->quoteIdentifier($table)));
                     }
                     if (!$forceReadWrite && $this->nodeDatabaseTagMergeLimit > 0) {
                         $q->LIMIT($this->nodeDatabaseTagMergeLimit);
                     }
                     $unions[] = '(' . (string) $q . ')';
                 }
                 $sql = implode('
                      UNION ALL
                     ', $unions);
                 $rows = array_merge($rows, $db->readAll($sql));
                 $nonfieldlikeRoles[] = $outPartial['TagRole'];
                 $runPartials[] = $outPartial->toString();
             }
         }
     } else {
         $rows = $existingRows;
     }
     // if no rows, return empty array
     if (empty($rows)) {
         return $rows;
     }
     $sortKeys = array();
     foreach ($rows as $k => $row) {
         $sortKeys[$k] = $row['TagSortOrder'];
     }
     array_multisort($sortKeys, SORT_ASC, $rows);
     // gather linked NodeRefs
     $tagNodeRefs = array();
     //        $strTagNodeRefs = array();
     //        $this->Logger->debug('FIELD LIKE PARTIALS');
     //        $this->Logger->debug($fieldlikePartials);
     //        $this->Logger->debug('NON FIELD LIKE PARTIALS');
     //        $this->Logger->debug($partials);
     $existingTagsPerNode = array();
     $newrows = array();
     $deletedTags = array();
     // filter out bogus rows
     foreach ($rows as $k => $row) {
         //            $rowElement = $this->ElementService->getByID($row['TagElementID']);
         if (!empty($row['TagElement'])) {
             $rowElement = $this->ElementService->getBySlug($row['TagElement']);
         } else {
             $rowElement = $this->ElementService->getByID($row['TagElementID']);
         }
         // element doesn't exist anymore
         if (empty($rowElement)) {
             continue;
         }
         //            error_log($nodeRef);
         if (!array_key_exists($row['TagRole'], $tagDefs)) {
             if ($direction == 'in' && $rowElement->getSchema()->hasTagDef($row['TagRole'])) {
                 $row['TagDef'] = $rowElement->getSchema()->getTagDef($row['TagRole']);
             } else {
                 continue;
             }
             // tag definition does not exist
         } else {
             $row['TagDef'] = $tagDefs[$row['TagRole']];
         }
         $row['TagElement'] = $rowElement->getSlug();
         $row['TagRoleDisplay'] = $row['TagDef']['Title'];
         $row['TagDirection'] = $direction;
         //$row['TagLinkRefURL'] = $nodeRef->getRefURL();
         //            $row['TagSite'] = $nodeRef->getSite()->getSlug();
         if (!empty($restrictedPartials)) {
             foreach ($restrictedPartials as $partial) {
                 if ($this->TagsHelper->matchPartial($partial, $row)) {
                     continue 2;
                 }
             }
         }
         if ($all == false && $allfieldlike == false && !empty($fieldlikePartials) && in_array($row['TagRole'], $fieldlikeRoles)) {
             //                error_log('matching fieldlike');
             //                error_log(print_r($fieldlikePartials, true));
             $found = false;
             foreach ($fieldlikePartials as $partial) {
                 //                    error_log('test '.$partial->toString());
                 if ($this->TagsHelper->matchPartial($partial, $row)) {
                     //                        error_log('match');
                     $found = true;
                     break;
                 }
             }
             if (!$found) {
                 continue;
             }
         }
         if ($all == false && !empty($partials) && in_array($row['TagRole'], $nonfieldlikeRoles)) {
             //                error_log('matching fieldlike');
             $found = false;
             foreach ($partials as $partial) {
                 //                    error_log('test '.$partial->toString());
                 if ($this->TagsHelper->matchPartial($partial, $row)) {
                     //                        error_log('match');
                     $found = true;
                     break;
                 }
             }
             if (!$found) {
                 continue;
             }
         }
         $nodeRef = new NodeRef($rowElement, $row['TagSlug']);
         $row['TagLinkNodeRef'] = $nodeRef;
         $row['NoValidation'] = true;
         $tag = new Tag($row);
         if (isset($existingTagsPerNode[$row['ID']]) && array_key_exists($tag->toString(), $existingTagsPerNode[$row['ID']])) {
             $tagIDToDelete = $existingTagsPerNode[$row['ID']][$tag->toString()];
             if ($tagIDToDelete != $tag->TagID) {
                 if ($tag->TagID > $tagIDToDelete) {
                     $tagIDToDelete = $tag->TagID;
                     // If the current tag is being deleted, mark it as deleted so that we can skip the rest of
                     // the processing once it's deleted from the db.
                     $tag->Deleted = true;
                 } else {
                     // We're deleting a tag that was already added to the results array. Therefore just keep track of
                     // it so that we can remove it from the results array later.
                     if ($fixedId) {
                         $deletedTags[$fixedId][] = $tagIDToDelete;
                     } else {
                         $deletedTags[$row['ID']][] = $tagIDToDelete;
                     }
                 }
                 // read repair
                 $this->Logger->debug("Delete {$tag->getTagDirection()} tag: {$tag->toString()}");
                 $affectedRows = $this->getConnectionForWrite($originNodeRef)->write("DELETE FROM {$db->quoteIdentifier($table)} WHERE TagID = {$db->quote($tagIDToDelete)}");
                 if ($affectedRows > 0) {
                     $this->NodeEvents->fireTagEvents($direction . 'tags', 'remove', $originNodeRef, $nodeRef, $tag);
                 }
                 // If the current tag is the one that got deleted, we're done processing this tag and can move to
                 // the next. This tag will not get added to the results.
                 if ($tag->Deleted) {
                     continue;
                 }
             }
         }
         $existingTagsPerNode[$row['ID']][$tag->toString()] = $tag->TagID;
         if ($resolveLinkedRecords) {
             $tagNodeRefs[] = $nodeRef;
             //                $strTagNodeRefs[$k] = (string)$nodeRef;
             // if need to merge more tags in
             if (array_key_exists($row['TagRole'], $childexprPartials)) {
                 // TODO: check partial matches
                 $rowRefKey = $rowElement->getSlug();
                 $outPartials = $childexprPartials[$row['TagRole']];
                 foreach ($outPartials as $outPartial) {
                     $expressions = StringUtils::smartSplit($outPartial->getChildPartials(), ".", '"', '\\"', 2);
                     $firstExpression = array_shift($expressions);
                     if (strtolower($firstExpression) == 'meta') {
                         $addlParams[$rowRefKey]['Meta.select'][] = 'all';
                     } elseif (strtolower($firstExpression) == 'fields') {
                         $addlParams[$rowRefKey]['Meta.select'][] = 'all';
                         $addlParams[$rowRefKey]['OutTags.select'][] = 'fields';
                         $addlParams[$rowRefKey]['InTags.select'][] = 'fields';
                     } else {
                         unset($schemaDef);
                         $isTag = true;
                         try {
                             $jPartial = new TagPartial($firstExpression);
                             $role = $jPartial->getTagRole();
                             if ($nodeRef->getElement()->getSchema()->hasTagDef($role)) {
                                 $schemaDef = $nodeRef->getElement()->getSchema()->getTagDef($role);
                             } else {
                                 if ($nodeRef->getElement()->getSchema()->hasMetaDef($role)) {
                                     $jPartial = new MetaPartial($firstExpression);
                                     $schemaDef = $nodeRef->getElement()->getSchema()->getMetaDef($role);
                                     $isTag = false;
                                 }
                             }
                         } catch (Exception $e) {
                             $jPartial = new MetaPartial($firstExpression);
                             $role = $jPartial->getMetaName();
                             if ($nodeRef->getElement()->getSchema()->hasMetaDef($role)) {
                                 $schemaDef = $nodeRef->getElement()->getSchema()->getMetaDef($role);
                             }
                             $isTag = false;
                         }
                         if (empty($schemaDef)) {
                             continue;
                         }
                         //throw new NodeException('Cannot retrieve additional nodes for role ['.$role.'], no schema def found on element ['.$rowElement->getSlug().']');
                         if ($isTag) {
                             $newPartials = $schemaDef->getDirection() == 'out' ? 'OutTags.select' : 'InTags.select';
                             $jPartial = $jPartial->getTagRole();
                         } else {
                             $newPartials = 'Meta.select';
                             $jPartial = $jPartial->getMetaName();
                         }
                         $new = $firstExpression;
                         if (!empty($expressions[0])) {
                             $new .= '.' . $expressions[0];
                         }
                         $addlParams[$rowRefKey][$newPartials][] = $new;
                         $jumpParams[$row['TagRole']][$newPartials][] = $jPartial;
                     }
                 }
             }
             $newrows[] = $tag;
         } else {
             if ($fixedId) {
                 $results[$fixedId][] = $row;
             } else {
                 $results[$row['ID']][] = $tag;
             }
         }
     }
     if ($resolveLinkedRecords) {
         //            error_log('PRE NODE RETRIEVE');
         // find the corresponding records
         $nodeRows = array();
         $connectionCouplets = $this->getResolvedConnectionCouplets($tagNodeRefs, $forceReadWrite);
         foreach ($connectionCouplets as $connectionCouplet) {
             $db = $connectionCouplet->getConnection();
             $tableToSlugs = $connectionCouplet->getAttribute('tablesToSlugs');
             foreach ($tableToSlugs as $table => $tableInfo) {
                 extract($tableInfo);
                 $rowRefKey = $element->getSlug();
                 $partialJump = false;
                 $newNodePartials = null;
                 if (array_key_exists($rowRefKey, $addlParams)) {
                     $partialJump = true;
                     $addl = $addlParams[$rowRefKey];
                     $newNodePartials = new NodePartials();
                     if (array_key_exists('OutTags.select', $addl)) {
                         $newNodePartials->setOutPartials(implode(',', array_unique($addl['OutTags.select'])));
                     }
                     if (array_key_exists('InTags.select', $addl)) {
                         $newNodePartials->setInPartials(implode(',', array_unique($addl['InTags.select'])));
                     }
                     if (array_key_exists('Meta.select', $addl)) {
                         $newNodePartials->setMetaPartials(implode(',', array_unique($addl['Meta.select'])));
                     }
                 }
                 if ($checkJumpPermissions && !$this->NodePermissions->check('get', $tableNodeRef, $newNodePartials, true)) {
                     continue;
                 }
                 $foundRows = $this->multiGetFromDB($db, $tableid, $table, $tableNodeRef, $slugs, false, $forceReadWrite, false);
                 if ($partialJump && !empty($foundRows)) {
                     $this->Logger->debug('Partials jump on ' . $tableNodeRef->getElement()->getName());
                     $aoutTags = array();
                     $ainTags = array();
                     $ameta = array();
                     $this->Benchmark->start('partial-jump');
                     $idField = 'ID';
                     $pids = ArrayUtils::arrayMultiColumn($foundRows, $idField);
                     if ($newNodePartials->hasOutPartials()) {
                         $aoutTags = $this->findOutTags($db, $tableNodeRef, $pids, $newNodePartials->getOutPartials(), false, false, $checkJumpPermissions);
                     }
                     if ($newNodePartials->hasInPartials()) {
                         $ainTags = $this->findInTags($db, $tableNodeRef, $pids, $newNodePartials->getInPartials(), false, false, $checkJumpPermissions);
                     }
                     if ($newNodePartials->hasMetaPartials()) {
                         $ameta = $this->NodeMetaDAO->findMeta($db, $tableNodeRef, $pids, $newNodePartials->getMetaPartials(), false);
                     }
                     foreach ($foundRows as $nodeRefString => &$nrow) {
                         $nrow->setNodePartials($newNodePartials);
                         $nrow->setMetas(isset($ameta[$nrow[$idField]]) ? $ameta[$nrow[$idField]] : array());
                         $nrow->setOutTags(isset($aoutTags[$nrow[$idField]]) ? $aoutTags[$nrow[$idField]] : array());
                         $nrow->setInTags(isset($ainTags[$nrow[$idField]]) ? $ainTags[$nrow[$idField]] : array());
                     }
                     $this->Benchmark->end('partial-jump');
                 }
                 $nodeRows = array_merge($nodeRows, $foundRows);
             }
         }
         foreach ($newrows as $row) {
             //                $id = $row['ID'];
             //                unset($row['ID']);
             //                error_log(print_r($row, true));
             if ($resolveLinkedRecords) {
                 $nodeRef = $row['TagLinkNodeRef'];
                 if (!array_key_exists((string) $nodeRef, $nodeRows)) {
                     continue;
                 }
                 $tagNode = $nodeRows[(string) $nodeRef];
                 // if need to filter out jump partials
                 if (array_key_exists($row['TagRole'], $jumpParams)) {
                     $outPartials = $jumpParams[$row['TagRole']];
                     foreach ($outPartials as $key => $kPartials) {
                         if ($key == 'Meta.select') {
                             foreach ($tagNode->getMetas() as $meta) {
                                 if (!in_array($meta->MetaName, $kPartials)) {
                                     $tagNode->removeMeta($meta->MetaName);
                                 }
                             }
                         } else {
                             if ($key == 'InTags.select') {
                                 foreach ($tagNode->getInTags() as $tag) {
                                     if (!in_array($tag->TagRole, $kPartials)) {
                                         $tagNode->removeInTags($tag->TagRole);
                                     }
                                 }
                             } else {
                                 if ($key == 'OutTags.select') {
                                     foreach ($tagNode->getOutTags() as $tag) {
                                         if (!in_array($tag->TagRole, $kPartials)) {
                                             $tagNode->removeOutTags($tag->TagRole);
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
                 // ignore deleted records
                 //if($tagNode['Status'] == 'deleted')
                 //    continue;
                 $row['TagLinkNode'] = $tagNode;
                 $row['TagLinkTitle'] = $tagNode['Title'];
                 $row['TagLinkID'] = $tagNode['ID'];
                 $row['TagLinkStatus'] = $tagNode['Status'];
                 $row['TagLinkActiveDate'] = $tagNode['ActiveDate'];
                 $row['TagLinkSortOrder'] = $tagNode['SortOrder'];
                 // only populate TagLinkURL if the record is active
                 if ($tagNode['Status'] == 'published' && $tagNode['ActiveDateUnix'] < $now->toUnix()) {
                     $row['TagLinkIsActive'] = true;
                     $row['TagLinkURL'] = $nodeRef->getRecordLink();
                     $row['TagLinkURI'] = $nodeRef->getRecordLinkURI();
                 } else {
                     $row['TagLinkURL'] = '';
                 }
                 $row['TagLinkURI'] = '';
             }
             if ($fixedId) {
                 $results[$fixedId][] = $row;
             } else {
                 $results[$row['ID']][] = $row;
             }
         }
     }
     // If tags were deleted during the 'read repair' they need to be removed from the results array
     // Go through the nodes that have had tags deleted. If those nodes exist in the results array, go
     // through the tags being returned. If the tag exists in the 'deleted' array for the node, remove it from
     // the result set.
     if (!empty($deletedTags)) {
         foreach ($deletedTags as $rowId => $rowDeletedTags) {
             if (isset($results[$rowId]) && !empty($results[$rowId])) {
                 foreach ($results[$rowId] as $resultKey => $rowResults) {
                     if (in_array($rowResults->TagID, $rowDeletedTags)) {
                         unset($results[$rowId][$resultKey]);
                     }
                 }
             }
         }
     }
     if ($returnOne) {
         return isset($results[$returnOne]) ? $results[$returnOne] : array();
     }
     return $results;
 }
 /**
  * @param null $elementSlug
  * @return array
  * @throws Exception
  */
 public function getUniqueThumbnailSizes($elementSlug = null)
 {
     $sizes = $this->thumbnailCmsSize;
     if (is_string($this->thumbnailSizes)) {
         $sizes .= ',' . $this->thumbnailSizes;
     } else {
         if (is_array($this->thumbnailSizes)) {
             if (array_key_exists($elementSlug, $this->thumbnailSizes)) {
                 $sizes .= ',' . $this->thumbnailSizes[$elementSlug];
             }
         } else {
             throw new Exception("Invalid thumbnail sizes [{$elementSlug}]");
         }
     }
     return array_unique(StringUtils::smartSplit($sizes, ','));
 }
 public static function decreasePartials($partials, $decrease)
 {
     if (empty($partials)) {
         return $partials;
     }
     if (($k = array_search($decrease, $explodedPartials = StringUtils::smartSplit($partials, ',', '"', '\\"'))) !== FALSE) {
         unset($explodedPartials[$k]);
         return implode(',', $explodedPartials);
     }
     return $partials;
 }
 protected function fireBindEvents($action, Node &$node, Errors &$errors, array $fields, array $rawFields)
 {
     if (isset($fields['OutTags_partials'])) {
         foreach (StringUtils::smartSplit($fields['OutTags_partials'], ',', '"', '\\"') as $partial) {
             $node->getNodePartials()->increaseOutPartials($partial);
         }
     }
     if (isset($fields['InTags_partials'])) {
         foreach (StringUtils::smartSplit($fields['InTags_partials'], ',', '"', '\\"') as $partial) {
             $node->getNodePartials()->increaseInPartials($partial);
         }
     }
     foreach ((array) $node->getNodeRef()->getElement()->getAspects() as $aspect) {
         $this->Events->trigger('Node.@' . $aspect->Slug . '.bind', $action, $node, $errors, $fields, $rawFields);
         $schema = $aspect->getSchema();
         foreach ($schema->getMetaDefs() as $metaDef) {
             $bound = $this->Events->trigger('Node.@' . $aspect->Slug . '.meta.#' . $metaDef->Id . '.bind', $action, $node, $errors, $fields, $rawFields);
             if (!$bound) {
                 $this->bindMeta($node, $errors, $fields, $rawFields, $metaDef->Id);
             }
         }
         foreach ($schema->getTagDefs() as $tagDef) {
             if ($tagDef->Direction == 'in') {
                 $bound = $this->Events->trigger('Node.@' . $aspect->Slug . '.intags.#' . $tagDef->Id . '.bind', $action, $node, $errors, $fields, $rawFields);
                 if (!$bound && $tagDef->isFieldlike()) {
                     $this->bindInTags($node, $errors, $fields, $rawFields, $tagDef->Id);
                 }
             } else {
                 $bound = $this->Events->trigger('Node.@' . $aspect->Slug . '.outtags.#' . $tagDef->Id . '.bind', $action, $node, $errors, $fields, $rawFields);
                 if (!$bound && $tagDef->isFieldlike()) {
                     $this->bindOutTags($node, $errors, $fields, $rawFields, $tagDef->Id);
                 }
             }
         }
     }
     $errors->throwOnError();
 }
 /**
  * Imports and runs sql contained in the specified file.
  * The file must contain only valid sql.
  *
  * @param string $filename The filename to load
  *
  * @return void
  */
 public function import($filename)
 {
     // TODO: Wrap this in a transaction!
     if (!file_exists($filename)) {
         throw new Exception("File not found: {$filename}");
     }
     $sql_queries = file_get_contents($filename);
     $sql_queries = $this->_removeRemarks($sql_queries);
     $sql_queries = StringUtils::smartSplit($sql_queries, ";", "'", "\\'");
     foreach ($sql_queries as $sql) {
         $sql = trim($sql);
         // Trim newlines so we don't have blank queries
         if (empty($sql)) {
             continue;
         }
         $this->write($sql);
     }
 }
 public static function flattenObjectsUsingKeys($obj, array $keys)
 {
     $array = self::flattenObjects($obj);
     $newArray = array();
     foreach ($keys as $key) {
         if (array_key_exists($key, $array)) {
             $newArray[$key] = $array[$key];
         } else {
             if (strpos($key, '.') !== FALSE) {
                 $parts = StringUtils::smartSplit($key, '.', '"', '\\');
                 if (!empty($parts)) {
                     $newArray = array_merge_recursive($newArray, self::breakDownArray($array, $parts));
                 }
             }
         }
     }
     return $newArray;
 }
 protected function _getPendingThumbnails($elementSlug, $thumbnails)
 {
     $sizes = $this->imagesThumbnailCmsSize;
     if (is_string($this->thumbnailSizes)) {
         $sizes .= ',' . $this->thumbnailSizes;
     } else {
         if (is_array($this->thumbnailSizes)) {
             if (array_key_exists($elementSlug, $this->thumbnailSizes)) {
                 $sizes .= ',' . $this->thumbnailSizes[$elementSlug];
             }
         } else {
             throw new Exception("Invalid thumbnail sizes [{$elementSlug}]");
         }
     }
     $sizes = array_unique(StringUtils::smartSplit($sizes, ','));
     $have = array();
     foreach ($thumbnails as $thumb) {
         $have[] = $thumb->value;
     }
     return array_values(array_diff($sizes, $have));
 }
 /**
  * Store the temporary-zipped-media nodes as proper media nodes.
  *
  * @throws MediaServiceException
  * @param $params
  * @return
  */
 protected function _storeTemporary($params)
 {
     if (empty($params['NodeRef'])) {
         throw new MediaServiceException('NodeRef must be specified');
     }
     list($element, $slug) = explode(':', $params['NodeRef']);
     $tmpParams = array('ElementSlug' => $element, 'NodeSlug' => $slug);
     // get node with all tags
     $node = $this->getNode($tmpParams, 'all');
     // will spit error if not found
     $nodeTitle = $node->Title;
     $nodeSlug = $node->Slug;
     // if a custom title is specified, override existing title & slug
     if (!empty($params['Title']) && $params['Title'] !== $node->Title) {
         $nodeTitle = $params['Title'];
         $nodeSlug = SlugUtils::createSlug($nodeTitle);
     }
     $nodeRef = new NodeRef($this->ElementService->getBySlug($params['ElementSlug']), $nodeSlug);
     $nodeRef = $this->NodeService->generateUniqueNodeRef($nodeRef, $nodeTitle);
     $params['Slug'] = $nodeRef->getSlug();
     $rawParams = $this->Request->getRawParameters();
     // Clean the param keys removing uid
     foreach ($params as $key => $value) {
         if (preg_match('/^#/', $key)) {
             $nkey = preg_replace('/-uid\\d+$/', '', $key);
             if (strcmp($nkey, $key) == 0) {
                 continue;
             }
             $params[$nkey] = $params[$key];
             $rawParams[$nkey] = $rawParams[$key];
             unset($params[$key]);
             unset($rawParams[$key]);
         }
     }
     foreach (array('In', 'Out') as $dir) {
         // Clean the _partials
         if (!empty($params[$dir . 'Tags_partials'])) {
             $newPartials = array();
             $partials = StringUtils::smartSplit($params[$dir . 'Tags_partials'], ',', '"', '\\"');
             foreach ($partials as $p) {
                 $newPartials[] = preg_replace('/-uid\\d+$/', '', $p);
             }
             $params[$dir . 'Tags_partials'] = implode(',', $newPartials);
             $rawParams[$dir . 'Tags_partials'] = implode(',', $newPartials);
         }
         // Clean the tags
         if (isset($params[$dir . 'Tags']) && is_array($params[$dir . 'Tags'])) {
             foreach ($params[$dir . 'Tags'] as $key => $value) {
                 $nkey = preg_replace('/-uid\\d+$/', '', $key);
                 if (strcmp($nkey, $key) == 0) {
                     continue;
                 }
                 $params[$dir . 'Tags'][$nkey] = $params[$dir . 'Tags'][$key];
                 $rawParams[$dir . 'Tags'][$nkey] = $rawParams[$dir . 'Tags'][$key];
                 unset($params[$dir . 'Tags'][$key]);
                 unset($rawParams[$dir . 'Tags'][$key]);
             }
         }
     }
     // create node
     $newNode = $nodeRef->generateNode();
     $this->NodeMapper->defaultsOnNode($newNode);
     //bind posted params to form backing object
     $this->NodeBinder->bindPersistentFields($newNode, $this->getErrors(), $params, $rawParams);
     $this->NodeBinder->fireAddBindEvents($newNode, $this->getErrors(), $params, $rawParams);
     $this->getErrors()->throwOnError();
     $newNode->Title = $nodeTitle;
     // copy other permanent fields
     $newNode->ActiveDate = $node->ActiveDate;
     $newNode->Status = $node->Status;
     // clone all the file out tags
     $outTags = $node->getOutTags();
     $newOutTags = array();
     foreach ($outTags as $tag) {
         if ($tag->getTagElement() == 'file') {
             $tnode = $this->RegulatedNodeService->getByNodeRef($tag->getTagLinkNode()->getNodeRef(), new NodePartials('#parent-element'));
             $fileNode = $this->cloneFileNode($tnode, $newNode->getElement());
             $newTag = new Tag($fileNode->getNodeRef(), '', $tag->getTagRole(), $tag->getTagValue(), $tag->getTagValueDisplay());
             $newOutTags[] = $newTag;
         } else {
             $newOutTags[] = $tag;
         }
     }
     $newNode->addOutTags($newOutTags);
     // copy all in tags
     $newNode->addInTags($node->getInTags());
     // and add the new node
     $newNode = $this->RegulatedNodeService->add($newNode);
     // then remove the temporary node
     $this->RegulatedNodeService->delete($node->getNodeRef());
     // commit so the node is ready for the worker
     $this->TransactionManager->commit()->begin();
     //-----------
     // Rebuild thumbnails asynchronously
     $workerParams = array('nodeRef' => '' . $newNode->getNodeRef(), 'forceRebuildExisting' => false);
     $this->GearmanService->doBackgroundJob('ImagesWorker', 'rebuildThumbnails', $workerParams, 'high');
     return $this->RegulatedNodeService->getByNodeRef($newNode->getNodeRef(), new NodePartials('all', '#original.#url,#original.#width,#original.#height,#original.#size,#thumbnails=150.#url,#thumbnails=150.#size,#thumbnails=150.#height,#thumbnails=150.#width'));
 }