public function match(Record $record) { $operator = $this->term['operator']; $property = Util::generateValidIdentifier($this->term['property']); $recordValue = strtolower($record->getProperty($property)); $conditionValue = strtolower($this->term['value']); switch ($operator) { case '=': return $recordValue == $conditionValue; break; case '>': return $recordValue > $conditionValue; break; case '<': return $recordValue < $conditionValue; break; case '>=': return $recordValue >= $conditionValue; break; case '<=': return $recordValue <= $conditionValue; break; case '!=': return $recordValue != $conditionValue; break; case '*=': $p = strpos($recordValue, $conditionValue); if ($p !== false) { return true; } break; } return false; }
public function setProperty($property, $value) { $property = Util::generateValidIdentifier($property); if ($this->dataTypeDefinition->hasProperty($property, $this->view)) { $this->properties[$property] = (string) $value; } else { throw new CMDLParserException('Unknown property ' . $property, CMDLParserException::CMDL_UNKNOWN_PROPERTY); } return $this; }
public function testListExtraction() { $result = Util::extractLists('(1:online,2:offline)'); $this->assertCount(1, $result); $this->assertCount(2, $result[0]); $result = Util::extractLists('param1 "param 2" param3 (a,b,c)'); $this->assertCount(1, $result); $this->assertArrayHasKey('a', $result[0]); $this->assertEquals('a', $result[0]['a']); $result = Util::extractLists('(a:dog,horse,c:cow) (green, blue, red ,purple)'); $this->assertCount(2, $result); $this->assertArrayHasKey('a', $result[0]); $this->assertArrayHasKey('horse', $result[0]); $this->assertArrayHasKey('c', $result[0]); $this->assertContains('green', $result[1]); $this->assertContains('blue', $result[1]); $this->assertContains('red', $result[1]); $this->assertContains('purple', $result[1]); $result = Util::extractLists('(a:"Lassy",\'Black Beauty \',c: Milka Cow )'); $this->assertCount(1, $result); $this->assertContains('Lassy', $result[0]); $this->assertContains('Black Beauty ', $result[0]); $this->assertContains('Milka Cow', $result[0]); }
public static function normalizeFilterQuery(Application $app, $query, ContentTypeDefinition $contentTypeDefinition) { $query = str_replace('><', '*=', $query); try { $condition = self::parseCondition($query); if (is_array($condition) && count($condition) == 3) { $property = Util::generateValidIdentifier($condition[0]); if (!$contentTypeDefinition->hasProperty($property)) { $app['context']->addAlertMessage('Cannot filter by property ' . $property . '.'); $query = ''; } } else { $query = 'name *= ' . $query; } $filter = new PropertyFilter($query); } catch (\Exception $e) { $app['context']->addAlertMessage('Could not parse query.'); $app['context']->setCurrentSearchTerm(''); //$query = ''; $filter = ''; } //$app['context']->setCurrentSearchTerm($query); return $filter; }
protected function getConfigTypeTableName($ensureConfigTypeTableIsPresent = true) { $repository = $this->getRepository(); $repositoryName = $repository->getName(); $tableName = $repositoryName . '$$config'; if ($tableName != Util::generateValidIdentifier($repositoryName) . '$$config') { throw new AnyContentClientException('Invalid repository name ' . $repositoryName); } if ($ensureConfigTypeTableIsPresent == true) { $this->ensureConfigTypeTableIsPresent(); } return $tableName; }
/** * remove protected properties and execute @name annotation * * @param Record $record */ protected function finalizeRecord(Record $record, DataDimensions $dataDimensions) { // Apply @name annotation if ($record->getDataTypeDefinition()->hasNamingPattern()) { $record->setName(Util::applyNamingPattern($record->getProperties(), $record->getDataTypeDefinition()->getNamingPattern())); } // remove protected properties $properties = $record->getProperties(); foreach ($record->getDataTypeDefinition()->getProtectedProperties($dataDimensions->getViewName()) as $property) { unset($properties[$property]); } $record->setProperties($properties); return $record; }
public function createRepository($repositoryName) { if ($repositoryName != Util::generateValidIdentifier($repositoryName)) { throw new RepositoryException('Invalid repository name.'); } $filename = $this->getCMDLDirectory(); @mkdir($filename . '/' . $repositoryName); $this->repositories = null; return true; }
public function saveConfig($configTypeDefinition, $properties, $workspace = 'default', $language = 'default') { $repositoryName = $this->repository->getName(); $configTypeName = $configTypeDefinition->getName(); $tableName = $repositoryName . '$$config'; if ($tableName != Util::generateValidIdentifier($repositoryName) . '$$config') { throw new RepositoryException('Invalid repository and/or config type name(s).'); } $possibleProperties = $configTypeDefinition->getProperties(); $notallowed = array_diff(array_keys($properties), $possibleProperties); if (count($notallowed) != 0) { throw new RepositoryException('Trying to store undefined properties: ' . join(',', $notallowed) . '.', RepositoryException::REPOSITORY_INVALID_PROPERTIES); } $mandatoryProperties = $configTypeDefinition->getMandatoryProperties('default'); $missing = array(); foreach ($mandatoryProperties as $property) { if (array_key_exists($property, $properties)) { if ($properties[$property] == '') { $missing[] = $property; } } else { $missing[] = $property; } } if (count($missing) != 0) { throw new RepositoryException('Trying to store config, but missing mandatory properties: ' . join(',', $missing) . '.', RepositoryException::REPOSITORY_MISSING_MANDATORY_PROPERTIES); } $dbh = $this->repository->getDatabaseConnection(); $timestamp = time(); $timeshiftTimestamp = $this->repository->getTimeshiftTimestamp(); // get current revision $revision = 0; try { $record = $this->getConfig($configTypeName, $workspace, $language); $revision = $record['record']['info']['revision']; } catch (RepositoryException $e) { // never mind we don't need an existing record } // invalidate current revision $sql = 'UPDATE ' . $tableName . ' SET validuntil_timestamp = ? WHERE id = ? AND workspace = ? AND language = ? AND validfrom_timestamp <=? AND validuntil_timestamp >?'; $params = array(); $params[] = $timeshiftTimestamp; $params[] = $configTypeName; $params[] = $workspace; $params[] = $language; $params[] = $timeshiftTimestamp; $params[] = $timeshiftTimestamp; $stmt = $dbh->prepare($sql); $stmt->execute($params); $values = array(); $values['id'] = $configTypeName; $values['hash'] = md5(serialize($properties)); $values['workspace'] = $workspace; $values['language'] = $language; $values['revision'] = $revision + 1; $values['properties'] = json_encode($properties); $values['lastchange_timestamp'] = $timestamp; $values['lastchange_apiuser'] = $this->repository->getAPIUser(); $values['lastchange_clientip'] = $this->repository->getClientIp(); $values['lastchange_username'] = $this->repository->getCurrentUserName(); $values['lastchange_firstname'] = $this->repository->getCurrentUserFirstname(); $values['lastchange_lastname'] = $this->repository->getCurrentUserLastname(); $values['validfrom_timestamp'] = $timeshiftTimestamp; $values['validuntil_timestamp'] = $this->repository->getMaxTimestamp(); $sql = 'INSERT INTO ' . $tableName; $sql .= ' (' . join(',', array_keys($values)) . ')'; $sql .= ' VALUES ( ?'; $sql .= str_repeat(' , ?', count($values) - 1); $sql .= ')'; $stmt = $dbh->prepare($sql); $stmt->execute(array_values($values)); return true; }
public static function adminAddConfigType(Application $app, Request $request, $repositoryAccessHash) { $url = $app['url_generator']->generate('admin'); /** @var RepositoryManager $repositoryManager */ $repositoryManager = $app['repos']; /** @var Repository $repository */ $repository = $repositoryManager->getRepositoryByRepositoryAccessHash($repositoryAccessHash); if ($repository) { $configTypeName = substr(trim($request->request->get('create_config_type')), 0, 32); $configTypeName = Util::generateValidIdentifier($configTypeName); if ($configTypeName != '') { if (!$repository->hasConfigType($configTypeName)) { $connection = $repository->getWriteConnection(); if ($connection->saveConfigTypeCMDL($configTypeName, '### definition of config type ' . $configTypeName . ' ###' . PHP_EOL)) { $app['context']->addSuccessMessage('Config Type ' . $configTypeName . ' created.'); $app['menus']->clearCache(); return new RedirectResponse($url); } } else { $app['context']->addAlertMessage('Config Type ' . $configTypeName . ' already exists.'); } } } $app['context']->addErrorMessage('Error generating new config type.'); return new RedirectResponse($url); }
public static function getMany(Application $app, Request $request, $repositoryName, $contentTypeName, $workspace = 'default', $clippingName = 'default', $language = 'default') { $timeshift = 0; $orderBy = 'id ASC'; $limit = null; $page = 1; $subset = null; $filter = null; /** @var $repository Repository */ $repository = $app['repos']->get($repositoryName); if ($repository) { $manager = $repository->getContentManager($contentTypeName); if ($manager) { if ($request->query->has('timeshift')) { $timeshift = (int) $request->get('timeshift'); } if ($request->query->has('language')) { $language = $request->get('language'); } if ($request->query->has('order')) { if ($request->get('order') == 'property') { $properties = explode(',', $request->get('properties')); $orderBy = ''; foreach ($properties as $property) { if ($manager->hasProperty(Util::generateValidIdentifier($property), $clippingName)) { if (substr(trim($property), -1) == '-') { $orderBy .= 'property_' . Util::generateValidIdentifier($property) . ' DESC, '; } else { $orderBy .= 'property_' . Util::generateValidIdentifier($property) . ' ASC, '; } } else { return self::badRequest($app, self::UNKNOWN_PROPERTY, $repositoryName, $contentTypeName, $clippingName, $property); } } $orderBy .= ' id ASC'; } else { switch ($request->get('order')) { case 'id': $orderBy = 'id ASC'; break; case 'id-': $orderBy = 'id DESC'; break; case 'name': $orderBy = 'property_name ASC, id ASC'; break; case 'name-': $orderBy = 'property_name DESC, id ASC'; break; case 'pos': $orderBy = 'position ASC, id ASC'; break; case 'pos-': $orderBy = 'position DESC, id ASC'; break; case 'change': // reversed order for token "change", since usually you want to see the latest changes first $orderBy = 'lastchange_timestamp DESC, id ASC'; break; case 'change-': $orderBy = 'lastchange_timestamp ASC, id DESC'; break; case 'creation': $orderBy = 'creation_timestamp ASC, id ASC'; break; case 'creation-': $orderBy = 'creation_timestamp DESC, id DESC'; break; case 'status': $orderBy = 'property_status ASC, id ASC'; break; case 'status-': $orderBy = 'property_status DESC, id ASC'; break; case 'subtype': $orderBy = 'property_subtype ASC, id ASC'; break; case 'subtype-': $orderBy = 'property_subtype DESC, id ASC'; break; } } } if ($request->query->has('limit')) { $limit = (int) $request->get('limit'); if ($request->query->has('page')) { $page = (int) $request->get('page'); } } if ($request->query->has('subset')) { $subset = $request->get('subset'); } if ($request->query->has('filter')) { if (is_array($request->query->get('filter'))) { $filter = FilterFactory::createFromArray($request->query->get('filter')); } else { $filter = FilterFactory::createFromQuery($request->query->get('filter')); } } $records = $manager->getRecords($clippingName, $workspace, $orderBy, $limit, $page, $subset, $filter, $language, $timeshift); return $app->json($records); } else { return self::notFoundError($app, self::UNKNOWN_CONTENTTYPE, $repositoryName, $contentTypeName); } } return self::notFoundError($app, self::UNKNOWN_REPOSITORY, $repositoryName); }
public function truncateConfigType($repositoryName, $configTypeName) { $tableName = $repositoryName . '$$config'; if ($configTypeName != Util::generateValidIdentifier($configTypeName) || $repositoryName != Util::generateValidIdentifier($repositoryName)) { throw new \Exception('Invalid repository and/or config type name(s).', self::INVALID_NAMES); } $dbh = $this->getConnection(); $sql = 'DELETE FROM ' . $tableName . ' WHERE id = ?'; $stmt = $dbh->prepare($sql); $params = array(); $params[] = $configTypeName; try { $stmt->execute($params); } catch (\PDOException $e) { return false; } return true; }
public function sortRecords($list, $workspace = 'default', $language = 'default') { $repositoryName = $this->repository->getName(); $contentTypeName = $this->contentTypeDefinition->getName(); $tableName = $repositoryName . '$' . $contentTypeName; if ($tableName != Util::generateValidIdentifier($repositoryName) . '$' . Util::generateValidIdentifier($contentTypeName)) { throw new \Exception('Invalid repository and/or content type name(s).', self::INVALID_NAMES); } $dbh = $this->repository->getDatabaseConnection(); $tempTableName = $tableName . '_' . substr(md5(uniqid(microtime(), true)), 0, 8); $timeshiftTimestamp = $this->repository->getTimeshiftTimestamp(); $sql = 'CREATE TEMPORARY TABLE ' . $tempTableName . ' SELECT * FROM ' . $tableName . ' WHERE workspace = ? AND language = ? AND validfrom_timestamp <= ? AND validuntil_timestamp > ? AND deleted=0'; $params = array(); $params[] = $workspace; $params[] = $language; $params[] = $timeshiftTimestamp; $params[] = $timeshiftTimestamp; $stmt = $dbh->prepare($sql); $stmt->execute($params); $sql = 'UPDATE ' . $tempTableName . ' SET parent_id = null, position=null, position_left = null, position_right = null, position_level = null'; $params = array(); $stmt = $dbh->prepare($sql); $stmt->execute($params); $transform = new AdjacentList2NestedSet($list); $transform->traverse(0); $nestedSet = $transform->getNestedSet(); $pos = 0; $ids = array(); foreach ($nestedSet as $id => $item) { $ids[] = $id; $pos++; $sql = 'UPDATE ' . $tempTableName . ' SET parent_id = ?, position=?, position_left = ?, position_right = ?, position_level = ? WHERE id = ?'; $params = array(); $params[] = $item['parent_id']; $params[] = $pos; $params[] = $item['left']; $params[] = $item['right']; $params[] = $item['level']; $stmt = $dbh->prepare($sql); $params[] = $id; $stmt->execute($params); } // end validity of all current records $sql = 'UPDATE ' . $tableName . ' SET validuntil_timestamp = ? WHERE workspace = ? AND language = ? AND validfrom_timestamp <= ? AND validuntil_timestamp > ? AND deleted=0'; $timeshiftTimestamp = $this->repository->getTimeshiftTimestamp(); $params = array(); $params[] = $timeshiftTimestamp; $params[] = $workspace; $params[] = $language; $params[] = $timeshiftTimestamp; $params[] = $timeshiftTimestamp; $stmt = $dbh->prepare($sql); $stmt->execute($params); // set validity of all new records $sql = 'UPDATE ' . $tempTableName . ' SET revision=revision+1, validfrom_timestamp = ?'; $params = array(); $params[] = $timeshiftTimestamp; $stmt = $dbh->prepare($sql); $stmt->execute($params); // Merge back $stmt = $dbh->prepare('INSERT INTO ' . $tableName . ' SELECT * FROM ' . $tempTableName); $stmt->execute(); $stmt = $dbh->prepare('DROP TABLE ' . $tempTableName); $stmt->execute(); //self::_updateContentInfo($content_type, $workspace); return true; }
public function createRepository($repositoryName) { if ($repositoryName != Util::generateValidIdentifier($repositoryName)) { throw new RepositoryException('Invalid repository name.'); } if (!$this->hasRepository($repositoryName)) { /** @var PDO $db */ $dbh = $this->app['db']->getConnection(); $sql = 'INSERT INTO _cmdl_ (repository) VALUES (?)'; $stmt = $dbh->prepare($sql); try { $stmt->execute(array($repositoryName)); } catch (\PDOException $e) { } } $this->repositories = null; return true; }
public static function parseAnnotation(DataTypeDefinition $dataTypeDefinition, FormElementDefinitionCollection $currentFormElementDefinitionCollection, $line) { $p = strpos($line, ' '); if ($p) { $annotationName = trim(substr($line, 1, $p)); $onTheRight = substr($line, $p + 1); $lists = Util::extractLists($onTheRight); $params = Util::extractParams($onTheRight); $numericalLists = Util::extractLists($onTheRight, true); } else { $annotationName = substr($line, 1); $lists = array(); $params = array(); $numericalLists = array(); } switch ($annotationName) { case 'title': $annotation = new DataTypeTitleAnnotation($dataTypeDefinition, $currentFormElementDefinitionCollection, $params, $lists); break; case 'description': $annotation = new DataTypeDescriptionAnnotation($dataTypeDefinition, $currentFormElementDefinitionCollection, $params, $lists); break; case 'name': $annotation = new ContentTypeNameAnnotation($dataTypeDefinition, $currentFormElementDefinitionCollection, $params, $lists); break; case 'languages': $annotation = new DataTypeLanguagesAnnotation($dataTypeDefinition, $currentFormElementDefinitionCollection, $params, $lists); break; case 'status': $annotation = new ContentTypeStatusAnnotation($dataTypeDefinition, $currentFormElementDefinitionCollection, $params, $lists); break; case 'subtypes': $annotation = new ContentTypeSubtypesAnnotation($dataTypeDefinition, $currentFormElementDefinitionCollection, $params, $lists); break; case 'workspaces': $annotation = new DataTypeWorkspacesAnnotation($dataTypeDefinition, $currentFormElementDefinitionCollection, $params, $lists); break; case 'sortable': $annotation = new DataTypeSortableAnnotation($dataTypeDefinition, $currentFormElementDefinitionCollection, $params, $lists); break; case 'time-shiftable': $annotation = new DataTypeTimeShiftableAnnotation($dataTypeDefinition, $currentFormElementDefinitionCollection, $params, $lists); break; case 'default-value': $annotation = new FormElementDefaultValueAnnotation($dataTypeDefinition, $currentFormElementDefinitionCollection, $params, $lists); break; case 'help': $annotation = new FormElementHelpAnnotation($dataTypeDefinition, $currentFormElementDefinitionCollection, $params, $lists); break; case 'hint': $annotation = new FormElementHintAnnotation($dataTypeDefinition, $currentFormElementDefinitionCollection, $params, $lists); break; case 'info': $annotation = new FormElementInfoAnnotation($dataTypeDefinition, $currentFormElementDefinitionCollection, $params, $lists); break; case 'placeholder': $annotation = new FormElementPlaceholderAnnotation($dataTypeDefinition, $currentFormElementDefinitionCollection, $params, $lists); break; case 'hidden-properties': $annotation = new FormElementCollectionHiddenPropertiesAnnotation($dataTypeDefinition, $currentFormElementDefinitionCollection, $params, $lists); break; case 'insert': $annotation = new InsertAnnotation($dataTypeDefinition, $currentFormElementDefinitionCollection, $params, $lists); break; case 'custom': $annotation = new CustomAnnotation($dataTypeDefinition, $currentFormElementDefinitionCollection, $params, $lists, $numericalLists); break; default: throw new CMDLParserException('Unknown annotation ' . $annotationName . '.', CMDLParserException::CMDL_UNKNOWN_ANNOTATION); break; } $dataTypeDefinition = $annotation->apply(); return $dataTypeDefinition; }
public function importXLSX(Repository $repository, $contentTypeName, $filename, $workspace = 'default', $language = 'default', $viewName = 'exchange') { $this->count = 0; $this->records = null; $this->stash = array(); $this->error = false; $repository->selectContentType($contentTypeName); // Select view and fallback if necessary $contentTypeDefinition = $repository->getContentTypeDefinition(); $viewDefinition = $contentTypeDefinition->getExchangeViewDefinition($viewName); $viewName = $viewDefinition->getName(); $repository->selectWorkspace($workspace); $repository->selectLanguage($language); $repository->selectView($viewName); $objPHPExcel = \PHPExcel_IOFactory::load($filename); if ($objPHPExcel) { if ($this->isTruncateRecords()) { $this->deleteEffectiveRecords($repository, $workspace, $viewName, $language); } $objWorksheet = $objPHPExcel->getActiveSheet(); $highestRow = $objWorksheet->getHighestRow(); // e.g. 10 $highestColumn = $objWorksheet->getHighestColumn(); // e.g 'F' $highestColumnIndex = \PHPExcel_Cell::columnIndexFromString($highestColumn); // e.g. 5 $idColumnIndex = null; $propertiesColumnIndices = array(); for ($i = 0; $i <= $highestColumnIndex; $i++) { $value = trim($objWorksheet->getCellByColumnAndRow($i, 1)->getValue()); if ($value != '') { if (substr($value, 0, 1) == '.') { if ($value == '.id') { $idColumnIndex = $i; } } else { $value = Util::generateValidIdentifier($value); if ($contentTypeDefinition->hasProperty($value, $viewName)) { $this->writeln('Detected valid property ' . $value); $propertiesColumnIndices[$value] = $i; } } } } $this->writeln(''); if (count($propertiesColumnIndices) != 0) { for ($row = 2; $row <= $highestRow; ++$row) { $id = null; if ($idColumnIndex !== null) { if (!$this->isGenerateNewIDs()) { $id = $objWorksheet->getCellByColumnAndRow($idColumnIndex, $row)->getValue(); } } $properties = array(); foreach ($propertiesColumnIndices as $property => $col) { $value = $objWorksheet->getCellByColumnAndRow($col, $row)->getValue(); $properties[$property] = $value; } $record = new Record($contentTypeDefinition, 'Imported Record', $viewName, $workspace, $language); $record->setProperties($properties); $record->setID($id); $msg = $this->stashRecord($repository, $record, $workspace, $viewName, $language); $this->writeln($msg); } $this->writeln(''); $this->writeln('Found ' . $this->count . ' records to import'); $this->writeln(''); if ($this->count != 0) { $this->writeln('Starting bulk import'); $this->writeln(''); $this->saveRecords($repository); $this->writeln(''); $this->writeln(''); } } else { $this->writeln('Excel does not contain matching property columns.'); } } else { $this->writeln('Error parsing Excel file.'); $this->error = true; } return !$this->error; }