/** * Returns false if the node fails to match the parameters * * @throws NodeException * @param $node * @param $filterParams * @param $metaParams * @return bool */ protected function filterNode($node, $filterParams, $metaParams) { if (!empty($filterParams)) { if (is_null($this->now)) { $this->now = $this->DateFactory->newStorageDate(); } foreach ($filterParams as $key => $value) { if (strpos($key, '#') === 0) { continue; } switch ($key) { case 'Title.firstChar': $firstChar = strtolower(substr($node['Title'], 0, 1)); if ($value == '#') { $ord = ord($firstChar); if ($ord >= 97 && $ord <= 122) { return false; } } else { if (strcmp($firstChar, $value) !== 0) { return false; } } break; case 'Title.eq': if (strcmp($value, $node['Title']) !== 0) { return false; } break; case 'Title.ieq': if (strcasecmp($value, $node['Title']) !== 0) { return false; } break; case 'Title.like': if (is_null($value)) { break; } if (stripos($node['Title'], $value) === FALSE) { return false; } break; case 'TreeID.childOf': if (stripos($node['TreeID'], $value) !== 0) { return false; } break; case 'TreeID.eq': if (strcmp($value, $node['TreeID']) !== 0) { return false; } break; case 'TreeID.depth': if (strlen($node['TreeID']) / 4 != $value) { return false; } break; case 'ActiveDate.after': if ($node['ActiveDate']->toUnix() < $value->toUnix()) { return false; } break; case 'ActiveDate.before': if ($node['ActiveDate']->toUnix() >= $value->toUnix()) { return false; } break; case 'ActiveDate.start': if ($node['ActiveDate']->toUnix() <= $value->toUnix()) { return false; } break; case 'ActiveDate.end': if ($node['ActiveDate']->toUnix() >= $value->toUnix()) { return false; } break; case 'CreationDate.after': if ($node['CreationDate']->toUnix() < $value->toUnix()) { return false; } break; case 'CreationDate.before': if ($node['CreationDate']->toUnix() >= $value->toUnix()) { return false; } break; case 'CreationDate.start': if ($node['CreationDate']->toUnix() <= $value->toUnix()) { return false; } break; case 'CreationDate.end': if ($node['CreationDate']->toUnix() >= $value->toUnix()) { return false; } break; case 'Status.eq': switch (strtolower($value)) { case 'published': if (strtolower($node['Status']) != 'published') { return false; } break; case 'draft': if (strtolower($node['Status']) != 'draft') { return false; } break; case 'deleted': if (strtolower($node['Status']) != 'deleted') { return false; } break; default: if (strtolower($node['Status']) == 'deleted') { return false; } break; } break; case 'Status.isActive': if (StringUtils::strToBool($value) == true && (strcmp('published', $node['Status']) !== 0 || $node['ActiveDate']->toUnix() >= $this->now->toUnix())) { return false; } break; case 'Status.all': if (StringUtils::strToBool($value) == false && strcmp('deleted', $node['Status']) === 0) { return false; } break; // case 'IncludesMeta': // $found = false; // foreach($value as $partial) { // $meta = MetaUtils::filterMeta($node['Metas'],$partial->getMetaName()); // if($partial->match($meta)) // $found = true; // } // if(!$found) // return false; // break; // case 'IncludesMeta': // $found = false; // foreach($value as $partial) { // $meta = MetaUtils::filterMeta($node['Metas'],$partial->getMetaName()); // if($partial->match($meta)) // $found = true; // } // if(!$found) // return false; // break; case 'Meta.exist': foreach ($value as $partial) { $meta = $node->getMeta($partial->getMetaName()); if (empty($meta) || !$partial->match($meta)) { return false; } } break; // case 'IncludesOutTags': // $found = false; // foreach($value as $partial) { // foreach($node['OutTags'] as $tag) // { // if($this->TagsHelper->matchPartial($partial, $tag)) { // $found = true; // break 2; // } // } // } // if(!$found) // return false; // // break; // case 'IncludesOutTags': // $found = false; // foreach($value as $partial) { // foreach($node['OutTags'] as $tag) // { // if($this->TagsHelper->matchPartial($partial, $tag)) { // $found = true; // break 2; // } // } // } // if(!$found) // return false; // // break; case 'OutTags.exist': $found = 0; foreach ($value as $partial) { foreach ($node['OutTags'] as $tag) { if ($this->TagsHelper->matchPartial($partial, $tag)) { ++$found; break; } } } if ($found != count($value)) { return false; } break; // case 'IncludesInTags': // $found = false; // foreach($value as $partial) { // foreach($node['InTags'] as $tag) // { // if($this->TagsHelper->matchPartial($partial, $tag)) { // $found = true; // break 2; // } // } // } // if(!$found) // return false; // // break; // case 'IncludesInTags': // $found = false; // foreach($value as $partial) { // foreach($node['InTags'] as $tag) // { // if($this->TagsHelper->matchPartial($partial, $tag)) { // $found = true; // break 2; // } // } // } // if(!$found) // return false; // // break; case 'InTags.exist': $found = 0; foreach ($value as $partial) { foreach ($node['InTags'] as $tag) { if ($this->TagsHelper->matchPartial($partial, $tag)) { ++$found; break; } } } if ($found != count($value)) { return false; } break; } } } if (!empty($metaParams)) { $schema = $node['NodeRef']->getElement()->getSchema(); foreach ($metaParams as $mArgs) { list($full, $name, $operator, $compareValue) = $mArgs; $def = $schema->getMetaDef($name); $datatype = $def->Datatype; if (is_object($node)) { $realValue = $node->getMetaValue($name); } else { $meta = MetaUtils::filterMeta($node['Metas'], $name); $realValue = $meta->getMetaValue(); } if ($datatype == 'flag') { throw new NodeException('Unable to run meta clause on flag datatype'); } switch ($operator) { case 'eq': if (in_array($datatype, array('text', 'varchar'))) { if (strcmp($compareValue, $realValue) !== 0) { return false; } else { if ($compareValue !== $realValue) { return false; } } } break; case 'ieq': if (strcasecmp($compareValue, $realValue) !== 0) { return false; } break; case 'like': if (is_null($compareValue)) { break; } if (stripos($compareValue, $realValue) === FALSE) { return false; } break; case 'before': $d = $this->DateFactory->newLocalDate($value); if ($realValue->toUnix() <= $d->toUnix()) { return false; } break; case 'after': $d = $this->DateFactory->newLocalDate($compareValue); if ($realValue->toUnix() > $d->toUnix()) { return false; } break; case 'start': $d = $this->DateFactory->newLocalDate($compareValue); $d->setTime(0, 0, 0); if ($realValue->toUnix() >= $d->toUnix()) { return false; } break; case 'end': $d = $this->DateFactory->newLocalDate($compareValue); $d->setTime(23, 59, 59); if ($realValue->toUnix() <= $d->toUnix()) { return false; } break; case 'notEq': if (in_array($datatype, array('text', 'varchar'))) { if (strcmp($compareValue, $realValue) === 0) { return false; } else { if ($compareValue === $realValue) { return false; } } } break; case 'lessThan': if ($compareValue >= $realValue) { return false; } break; case 'lessThanEq': if ($compareValue > $realValue) { return false; } break; case 'greaterThan': if ($compareValue <= $realValue) { return false; } break; case 'greaterThanEq': if ($compareValue < $realValue) { return false; } break; /* * case insensitive comparison for #meta.in filtering. * works exactly like the SQL SomeValue IN ('item1', 'item2') */ /* * case insensitive comparison for #meta.in filtering. * works exactly like the SQL SomeValue IN ('item1', 'item2') */ case 'in': $inValues = explode(',', $compareValue); $foundValue = false; if (in_array($datatype, array('text', 'varchar'))) { foreach ($inValues as $val) { if (strcasecmp($val, $realValue) === 0) { $foundValue = true; break; } } } else { foreach ($inValues as $val) { if ($val === $realValue) { $foundValue = true; break; } } } if (!$foundValue) { return false; } break; } } } return true; }
public function saveMeta(DatabaseInterface $db, NodeRef $originNodeRef, $recordid, $metaPartials = 'fields', array $metaTags, $restrictedPartials = '') { if (empty($recordid)) { throw new Exception('Cannot save meta without recordid'); } $originalRestrictedPartials = $restrictedPartials; $restrictedPartials = PartialUtils::unserializeMetaPartials($restrictedPartials); if ($restrictedPartials == 'all' || ($x = array_search('all', $restrictedPartials)) !== false) { return; } MetaUtils::validateMeta($metaTags); // $originNodeRef = $node->getNodeRef(); $tableid = $this->NodeDBMeta->getPrimaryKey($originNodeRef); $now = $this->DateFactory->newStorageDate(); $tagsToDelete = array(); $updatedMeta = array(); $originalMeta = array(); // if($sectionType != null) // { // $schema = $originNodeRef->getElement()->getSchema()->getSectionDef($sectionType); // } else // { $schema = $originNodeRef->getElement()->getSchema(); // } // remove duplicates from meta foreach ($metaTags as $o => &$mtag) { // if($sectionid != 0) // $mtag->setMetaSectionID($sectionid); $metaDef = $schema->getMetaDef($mtag->getMetaName()); $mtag->setMetaStorageDatatype($metaDef->Datatype); $mtag->setMetaValidationDatatype($metaDef->Validation->getDatatype()); foreach ($metaTags as $i => $ddtag) { //if($o != $i && $tag->getMetaName() === $dtag->getMetaName() && $tag->getMetaSectionID() == $dtag->getMetaSectionID()) if ($o != $i && $mtag->getMetaName() === $ddtag->getMetaName()) { // error_log("REMOVING DUPE ".$dtag->toString()); unset($metaTags[$o]); } } foreach ($restrictedPartials as $dPartial) { if (strcmp($dPartial->getMetaName(), $mtag['MetaName']) === 0) { unset($metaTags[$o]); } } } $currentMetaTags = $this->findMeta($db, $originNodeRef, $recordid, $metaPartials, true, $originalRestrictedPartials); // $this->Logger->debug('current meta for ['.$recordid.'] on section ['.$sectionid.']'); // $this->Logger->debug($currentMetaTags); MetaUtils::validateMeta($currentMetaTags); foreach ($currentMetaTags as $k => $tag) { //if($tag->getMetaID() == false) throw new Exception('Cannot save meta without MetaIDs for current meta'); $foundThisTag = false; foreach ($metaTags as $dtag) { //if($tag->getMetaName() === $dtag->getMetaName() && $tag->getMetaSectionID() == $dtag->getMetaSectionID()) if ($tag->getMetaName() === $dtag->getMetaName()) { // error_log("MATCHED ".$dtag->toString() ." TO ".$tag->toString()); // error_log(print_r($dtag, true)); // error_log(print_r($tag, true)); // delete string meta that have no value if (($dtag->getMetaStorageDatatype() == 'text' || $dtag->getMetaStorageDatatype() == 'varchar' || $dtag->getMetaStorageDatatype() == 'blob') && strlen(trim($dtag->getMetaValue())) == 0 || $dtag->getMetaStorageDatatype() == 'flag' && $dtag->getMetaValue() == false || ($dtag->getMetaValidationDatatype() == 'int' || $dtag->getMetaValidationDatatype() == 'float') && $dtag->getMetaValue() === null || in_array($dtag, $updatedMeta)) { // error_log('DELETE: '.$tag); $tagsToDelete[] = $tag; } else { // error_log('UPDATE: '.$tag); $updatedMeta[$tag->getMetaStorageDatatype()][] = $dtag; $originalMeta[$tag->getMetaStorageDatatype()][] = $tag; } $foundThisTag = true; break; } } if (!$foundThisTag) { $tagsToDelete[] = $tag; } } $changedOne = false; $tagIDsToDelete = array(); foreach ($tagsToDelete as $tag) { // log tag deletion // $this->transactionsService->logMetaDelete($element, $recordid, $tag); $table = $this->NodeDBMeta->getMetaTable($originNodeRef, $tag->getMetaStorageDatatype()); $affectedRows = $db->deleteRecord($table, "{$tableid} = {$db->quote($recordid)} AND Name = {$db->quote($tag->getMetaName())}"); if ($affectedRows > 0) { $this->NodeEvents->fireMetaEvents('meta', 'remove', $originNodeRef, $tag); $changedOne = true; } // $tagIDsToDelete[][] = $tag->getMetaID(); } // if(!empty($tagIDsToDelete)){ // foreach($tagIDsToDelete as $datatype => $ids){ // // ; // $deletions = $db->write("DELETE FROM {$db->quoteIdentifier($table)} WHERE MetaID IN (".$db->joinQuote((array)$ids).")", DatabaseInterface::AFFECTED_ROWS); // // } // } foreach ($metaTags as $tag) { $datatype = $tag->getMetaStorageDatatype(); $table = $db->quoteIdentifier($this->NodeDBMeta->getMetaTable($originNodeRef, $datatype)); if (($datatype == 'text' || $datatype == 'varchar' || $datatype == 'blob') && strlen(trim($tag->getMetaValue())) == 0) { continue; } if ($datatype == 'flag' && $tag->getMetaValue() == false) { continue; } if (($tag->getMetaValidationDatatype() == 'int' || $tag->getMetaValidationDatatype() == 'float') && $tag->getMetaValue() === null) { continue; } $datatypeCol = $this->NodeDBMeta->getMetaDatatypeColumn($datatype); if (isset($updatedMeta[$datatype]) && in_array($tag, $updatedMeta[$datatype])) { $tagid = array_search($tag, $updatedMeta[$datatype]); $originalTag = $originalMeta[$datatype][$tagid]; // if this is an integer storage field and the originalvalue is 0 and the new value equates to 0, do no update if (in_array(strtolower($datatypeCol), array('tiny', 'int', 'long', 'float')) && floatVal($originalTag->getMetaValue()) == 0 && floatVal($tag->getMetaValue()) == 0) { continue; } if ($datatype != 'flag' && strcmp('' . $originalTag->getMetaValue(), '' . $tag->getMetaValue()) !== 0) { // update the meta tag $affectedRows = $db->updateRecord($table, array("{$datatypeCol}Value" => $tag->getMetaValue()), "{$tableid} = {$db->quote($recordid)} AND Name = {$db->quote($tag->getMetaName())}"); if ($affectedRows > 0) { $this->NodeEvents->fireMetaEvents('meta', 'update', $originNodeRef, $tag, $originalTag); // if($tag->getMetaValidationDatatype() == 'boolean') // if($tag->getMetaValue() == false) // $this->NodeEvents->fireMetaEvents('meta', 'remove', $originNodeRef, $tag, $originalTag); // else // $this->NodeEvents->fireMetaEvents('meta', 'add', $originNodeRef, $tag, $originalTag); $changedOne = true; } } } else { // insert the meta tag // $newinsert = array( // $tableid => $recordid, // 'Name' => $tag->getMetaName(), // "{$datatype}Value" => $tag->getMetaValue(), // ); try { if ($datatype == 'flag') { $affectedRows = $db->write("INSERT IGNORE INTO {$table} ({$tableid}, Name) Values ({$db->quote($recordid)}, {$db->quote($tag->getMetaName())})", DatabaseInterface::AFFECTED_ROWS); } else { $affectedRows = $db->write("INSERT INTO {$table} ({$tableid}, Name, {$datatypeCol}Value) Values ({$db->quote($recordid)}, {$db->quote($tag->getMetaName())}, {$db->quote($tag->getMetaValue())})", DatabaseInterface::AFFECTED_ROWS); } // $bulkTagInserts[$datatype][] = $newinsert; // $db->insertRecord($table, $newinsert); if ($affectedRows > 0) { $this->NodeEvents->fireMetaEvents('meta', 'add', $originNodeRef, $tag); $changedOne = true; } } catch (SQLDuplicateKeyException $dke) { $where = "{$tableid} = {$db->quote($recordid)} AND Name = {$db->quote($tag->getMetaName())}"; $originalValue = $db->readField("SELECT {$datatypeCol}Value FROM {$table} WHERE {$where} LOCK IN SHARE MODE"); // update the meta tag $affectedRows = $db->updateRecord($table, array("{$datatypeCol}Value" => $tag->getMetaValue()), $where); if ($affectedRows > 0) { $this->NodeEvents->fireMetaEvents('meta', 'update', $originNodeRef, $tag, new Meta($tag->getMetaName(), $originalValue)); $changedOne = true; } } // $this->NodeEvents->fireMetaEvents('meta', 'add', $originNodeRef, $tag); } } // if(!empty($bulkTagInserts)) // foreach($bulkTagInserts as $datatype => $bulkInserts) // $db->bulkInsertRecords($db->quoteIdentifier($this->NodeDBMeta->getMetaTable($originNodeRef, $datatype)), $bulkInserts); return $changedOne; }