public function current() { if (!$this->valid()) { return null; } return $this->factory->get('Query\\Row', array($this->objectManager, $this->rows[$this->position])); }
/** * Internally create a node type object * * @param NodeTypeDefinitionInterface $ntd * @param bool $allowUpdate whether updating the definition is to be allowed or not * * @return NodeType the new node type * * @throws \PHPCR\NodeType\NodeTypeExistsException */ protected function createNodeType(NodeTypeDefinitionInterface $ntd, $allowUpdate) { if ($this->hasNodeType($ntd->getName()) && !$allowUpdate) { throw new NodeTypeExistsException('NodeType already existing: ' . $ntd->getName()); } return $this->factory->get('NodeType\\NodeType', array($this, $ntd)); }
/** * Reads the node type definition from an xml element * * @param DOMElement $node The dom element to read information from */ protected function fromXml(DOMElement $node) { $this->name = $node->getAttribute('name'); $this->isAbstract = Helper::getBoolAttribute($node, 'isAbstract'); $this->isMixin = Helper::getBoolAttribute($node, 'isMixin'); $this->isQueryable = Helper::getBoolAttribute($node, 'isQueryable'); $this->hasOrderableChildNodes = Helper::getBoolAttribute($node, 'hasOrderableChildNodes'); $this->primaryItemName = $node->getAttribute('primaryItemName'); if (empty($this->primaryItemName)) { $this->primaryItemName = null; } $this->declaredSuperTypeNames = array(); $xp = new DOMXPath($node->ownerDocument); $supertypes = $xp->query('supertypes/supertype', $node); foreach ($supertypes as $supertype) { $this->declaredSuperTypeNames[] = $supertype->nodeValue; } $this->declaredPropertyDefinitions = new ArrayObject(); $properties = $xp->query('propertyDefinition', $node); foreach ($properties as $property) { $this->declaredPropertyDefinitions[] = $this->factory->get('NodeType\\PropertyDefinition', array($property, $this->nodeTypeManager)); } $this->declaredNodeDefinitions = new ArrayObject(); $declaredNodeDefinitions = $xp->query('childNodeDefinition', $node); foreach ($declaredNodeDefinitions as $nodeDefinition) { $this->declaredNodeDefinitions[] = $this->factory->get('NodeType\\NodeDefinition', array($nodeDefinition, $this->nodeTypeManager)); } }
/** * {@inheritDoc} * * @api */ public function getVersionManager() { if (!$this->session->getTransport() instanceof VersioningInterface) { throw new UnsupportedRepositoryOperationException('Transport does not support versioning'); } return $this->factory->get('Version\\VersionManager', array($this->session->getObjectManager())); }
/** * Parse the events in an <entry> section * * @param DOMElement $entry * @param string $currentUserId The current user ID as extracted from * the <entry> part * * @return Event[] */ protected function extractEvents(DOMElement $entry, $currentUserId) { $events = array(); $domEvents = $entry->getElementsByTagName('event'); foreach ($domEvents as $domEvent) { $event = $this->factory->get('Jackalope\\Observation\\Event', array($this->nodeTypeManager)); $event->setType($this->extractEventType($domEvent)); $date = $this->getDomElement($domEvent, 'eventdate', 'The event date was not found while building the event journal:\\n' . $this->getEventDom($domEvent)); $event->setUserId($currentUserId); // The timestamps in Java contain milliseconds, it's not the case in PHP // so we strip millis from the response $event->setDate(substr($date->nodeValue, 0, -3)); $id = $this->getDomElement($domEvent, 'eventidentifier'); if ($id) { $event->setIdentifier($id->nodeValue); } $href = $this->getDomElement($domEvent, 'href'); if ($href) { $path = str_replace($this->workspaceRootUri, '', $href->nodeValue); if (substr($path, -1) === '/') { // Jackrabbit might return paths with trailing slashes. Eliminate them if present. $path = substr($path, 0, -1); } $event->setPath($path); } $primaryNodeType = $this->getDomElement($domEvent, 'eventprimarynodetype'); if ($primaryNodeType) { $event->setPrimaryNodeTypeName($primaryNodeType->nodeValue); } $mixinNodeTypes = $domEvent->getElementsByTagName('eventmixinnodetype'); foreach ($mixinNodeTypes as $mixinNodeType) { $event->addMixinNodeTypeName($mixinNodeType->nodeValue); } $userData = $this->getDomElement($domEvent, 'eventuserdata'); if ($userData) { $event->setUserData($userData->nodeValue); } $eventInfos = $this->getDomElement($domEvent, 'eventinfo'); if ($eventInfos) { foreach ($eventInfos->childNodes as $info) { if ($info->nodeType == XML_ELEMENT_NODE) { $event->addInfo($info->tagName, $info->nodeValue); } } } // abort if we got more events than expected (usually on paging) if ($event->getDate() > $this->creationMillis) { $this->nextMillis = false; return $events; } if ($this->filter->match($event)) { $events[] = $event; } } return $events; }
/** * {@inheritDoc} * * @api */ public function execute() { if (is_null($this->objectManager)) { // if the ObjectManager was not injected in the header. this is only supposed to happen in the DBAL client. throw new RepositoryException('Jackalope implementation error: This query was built for parsing only. (There is no ObjectManager to run the query against.)'); } $transport = $this->objectManager->getTransport(); $rawData = $transport->query($this); $queryResult = $this->factory->get('Query\\QueryResult', array($rawData, $this->objectManager)); return $queryResult; }
/** * {@inheritDoc} * * @api */ public function getNodes($prefetch = false) { if ($prefetch !== true) { return $this->factory->get('Query\\NodeIterator', array($this->objectmanager, $this->rows)); } $paths = array(); foreach ($this->getRows() as $row) { $paths[] = $row->getPath(); } return $this->objectmanager->getNodesByPath($paths); }
/** Creates a session * * Builds the corresponding workspace instance * * @param FactoryInterface $factory the object factory * @param Repository $repository * @param string $workspaceName the workspace name that is used * @param SimpleCredentials $credentials the credentials that where * used to log in, in order to implement Session::getUserID() * if they are null, getUserID returns null * @param TransportInterface $transport the transport implementation */ public function __construct(FactoryInterface $factory, Repository $repository, $workspaceName, SimpleCredentials $credentials = null, TransportInterface $transport) { $this->factory = $factory; $this->repository = $repository; $this->objectManager = $this->factory->get('ObjectManager', array($transport, $this)); $this->workspace = $this->factory->get('Workspace', array($this, $this->objectManager, $workspaceName)); $this->credentials = $credentials; $this->namespaceRegistry = $this->workspace->getNamespaceRegistry(); self::registerSession($this); $transport->setNodeTypeManager($this->workspace->getNodeTypeManager()); }
/** * {@inheritDoc} * * @api */ public function login(CredentialsInterface $credentials = null, $workspaceName = null) { if (!($workspaceName = $this->transport->login($credentials, $workspaceName))) { throw new RepositoryException('transport failed to login without telling why'); } /** @var $session Session */ $session = $this->factory->get('Session', array($this, $workspaceName, $credentials, $this->transport)); $session->setSessionOption(Session::OPTION_AUTO_LASTMODIFIED, $this->options[Session::OPTION_AUTO_LASTMODIFIED]); if ($this->options['transactions']) { $utx = $this->factory->get('Transaction\\UserTransaction', array($this->transport, $session, $session->getObjectManager())); $session->getWorkspace()->setTransactionManager($utx); } return $session; }
/** * Reads the node type definition from an array * * @param array $data an array with key-value information */ protected function fromArray(array $data) { $this->name = $data['name']; $this->isAbstract = $data['isAbstract']; $this->isMixin = $data['isMixin']; $this->isQueryable = $data['isQueryable']; $this->hasOrderableChildNodes = $data['hasOrderableChildNodes']; $this->primaryItemName = $data['primaryItemName'] ?: null; $this->declaredSuperTypeNames = isset($data['declaredSuperTypeNames']) && count($data['declaredSuperTypeNames']) ? $data['declaredSuperTypeNames'] : array(); $this->declaredPropertyDefinitions = new ArrayObject(); foreach ($data['declaredPropertyDefinitions'] as $propertyDef) { $this->declaredPropertyDefinitions[] = $this->factory->get('NodeType\\PropertyDefinition', array($propertyDef, $this->nodeTypeManager)); } $this->declaredNodeDefinitions = new ArrayObject(); foreach ($data['declaredNodeDefinitions'] as $nodeDef) { $this->declaredNodeDefinitions[] = $this->factory->get('NodeType\\NodeDefinition', array($nodeDef, $this->nodeTypeManager)); } }
/** * Get the node identified by an absolute path. * * To prevent unnecessary work to be done a cache is filled to only fetch * nodes once. To reset a node with the data from the backend, use * Node::refresh() * * Uses the factory to create a Node object. * * @param string $absPath The absolute path of the node to fetch. * @param string $class The class of node to get. TODO: Is it sane to fetch * data separately for Version and normal Node? * @param object $object A (prefetched) object (de-serialized json) from the backend * only to be used if we get child nodes in one backend call * * @return NodeInterface * * @throws ItemNotFoundException If nothing is found at that * absolute path * @throws RepositoryException If the path is not absolute or not * well-formed * * @see Session::getNode() */ public function getNodeByPath($absPath, $class = 'Node', $object = null) { $absPath = PathHelper::normalizePath($absPath); if (!empty($this->objectsByPath[$class][$absPath])) { // Return it from memory if we already have it return $this->objectsByPath[$class][$absPath]; } // do this even if we have item in cache, will throw error if path is deleted - sanity check $fetchPath = $this->getFetchPath($absPath, $class); if (!$object) { // this is the first request, get data from transport $object = $this->transport->getNode($fetchPath); } // recursively create nodes for pre-fetched children if fetchDepth was > 1 foreach ($object as $name => $properties) { if (is_object($properties)) { $objVars = get_object_vars($properties); $countObjVars = count($objVars); // if there's more than one objectvar or just one and this isn't jcr:uuid, // then we assume this child was pre-fetched from the backend completely if ($countObjVars > 1 || $countObjVars == 1 && !isset($objVars['jcr:uuid'])) { try { $parentPath = '/' === $absPath ? '/' : $absPath . '/'; $this->getNodeByPath($parentPath . $name, $class, $properties); } catch (ItemNotFoundException $ignore) { // we get here if the item was deleted or moved locally. just ignore } } } } /** @var $node NodeInterface */ $node = $this->factory->get($class, array($object, $absPath, $this->session, $this)); if ($uuid = $node->getIdentifier()) { // map even nodes that are not mix:referenceable, as long as they have a uuid $this->objectsByUuid[$uuid] = $absPath; } $this->objectsByPath[$class][$absPath] = $node; return $this->objectsByPath[$class][$absPath]; }
/** * {@inheritDoc} */ public function query(Query $query) { $this->assertLoggedIn(); if (!$query instanceof QueryObjectModelInterface) { $parser = new Sql2ToQomQueryConverter($this->factory->get('Query\\QOM\\QueryObjectModelFactory')); try { $qom = $parser->parse($query->getStatement()); $qom->setLimit($query->getLimit()); $qom->setOffset($query->getOffset()); } catch (\Exception $e) { throw new InvalidQueryException('Invalid query: ' . $query->getStatement(), null, $e); } } else { $qom = $query; } $qomWalker = new QOMWalker($this->nodeTypeManager, $this->api, $this->getNamespaces()); list($selectors, $selectorAliases, $query) = $qomWalker->walkQOMQuery($qom); $primarySource = reset($selectors); $primaryType = $primarySource->getSelectorName() ?: $primarySource->getNodeTypeName(); $data = $this->api->forms()->everything->ref($this->ref)->query($query)->submit(); // TODO implement $results = array(); return $results; }
/** * {@inheritDoc} * * @api */ public function createEventFilter() { return $this->factory->get('Jackalope\\Observation\\EventFilter', array($this->session)); }
/** * {@inheritDoc} */ public function query(Query $query) { $this->assertLoggedIn(); if (!$query instanceof QueryObjectModelInterface) { $parser = new Sql2ToQomQueryConverter($this->factory->get('Query\\QOM\\QueryObjectModelFactory')); try { $qom = $parser->parse($query->getStatement()); $qom->setLimit($query->getLimit()); $qom->setOffset($query->getOffset()); } catch (\Exception $e) { throw new InvalidQueryException('Invalid query: ' . $query->getStatement(), null, $e); } } else { $qom = $query; } $qomWalker = new QOMWalker($this->nodeTypeManager, $this->getConnection(), $this->getNamespaces()); list($selectors, $selectorAliases, $sql) = $qomWalker->walkQOMQuery($qom); $primarySource = reset($selectors); $primaryType = $primarySource->getSelectorName() ?: $primarySource->getNodeTypeName(); $data = $this->getConnection()->fetchAll($sql, array($this->workspaceName)); $results = $properties = $standardColumns = array(); foreach ($data as $row) { $result = array(); /** @var SelectorInterface $selector */ foreach ($selectors as $selector) { $selectorName = $selector->getSelectorName() ?: $selector->getNodeTypeName(); $columnPrefix = isset($selectorAliases[$selectorName]) ? $selectorAliases[$selectorName] . '_' : $selectorAliases[''] . '_'; if ($primaryType === $selector->getNodeTypeName()) { $result[] = array('dcr:name' => 'jcr:path', 'dcr:value' => $row[$columnPrefix . 'path'], 'dcr:selectorName' => $selectorName); } $result[] = array('dcr:name' => 'jcr:path', 'dcr:value' => $row[$columnPrefix . 'path'], 'dcr:selectorName' => $selectorName); $result[] = array('dcr:name' => 'jcr:score', 'dcr:value' => 0, 'dcr:selectorName' => $selectorName); if (0 === count($qom->getColumns())) { $selectorPrefix = null !== $selector->getSelectorName() ? $selectorName . '.' : ''; $result[] = array('dcr:name' => $selectorPrefix . 'jcr:primaryType', 'dcr:value' => $primaryType, 'dcr:selectorName' => $selectorName); } if (isset($row[$columnPrefix . 'props'])) { $propertyNames = array(); $columns = $qom->getColumns(); // Always populate jcr:created and jcr:createdBy if a wildcard selector is used. // This emulates the behavior of Jackrabbit if (0 === count($columns)) { $propertyNames = array('jcr:created', 'jcr:createdBy'); } foreach ($columns as $column) { if (!$column->getSelectorName() || $column->getSelectorName() == $selectorName) { $propertyNames[] = $column->getPropertyName(); } } $properties[$selectorName] = (array) $this->xmlToColumns($row[$columnPrefix . 'props'], $propertyNames); } else { $properties[$selectorName] = array(); } // TODO: add other default columns that Jackrabbit provides to provide a more consistent behavior if (isset($properties[$selectorName]['jcr:createdBy'])) { $standardColumns[$selectorName]['jcr:createdBy'] = $properties[$selectorName]['jcr:createdBy']; } if (isset($properties[$selectorName]['jcr:created'])) { $standardColumns[$selectorName]['jcr:created'] = $properties[$selectorName]['jcr:created']; } } $reservedNames = array('jcr:path', 'jcr:score'); foreach ($qom->getColumns() as $column) { $selectorName = $column->getSelectorName(); $columnName = $column->getPropertyName(); $columnPrefix = isset($selectorAliases[$selectorName]) ? $selectorAliases[$selectorName] . '_' : $selectorAliases[''] . '_'; if (in_array($column->getColumnName(), $reservedNames)) { throw new InvalidQueryException(sprintf('Cannot reserved name "%s". Reserved names are "%s"', $column->getColumnName(), implode('", "', $reservedNames))); } $dcrValue = 'jcr:uuid' === $columnName ? $row[$columnPrefix . 'identifier'] : (isset($properties[$selectorName][$columnName]) ? $properties[$selectorName][$columnName] : ''); if (isset($standardColumns[$selectorName][$columnName])) { unset($standardColumns[$selectorName][$columnName]); } $result[] = array('dcr:name' => $column->getColumnName() === $columnName && isset($properties[$selectorName][$columnName]) ? $selectorName . '.' . $columnName : $column->getColumnName(), 'dcr:value' => $dcrValue, 'dcr:selectorName' => $selectorName ?: $primaryType); } foreach ($standardColumns as $selectorName => $columns) { foreach ($columns as $columnName => $value) { $result[] = array('dcr:name' => $primaryType . '.' . $columnName, 'dcr:value' => $value, 'dcr:selectorName' => $selectorName); } } $results[] = $result; } return $results; }
/** * {@inheritDoc} * * @api */ public function createQuery(SourceInterface $source, ConstraintInterface $constraint = null, array $orderings = array(), array $columns = array()) { return $this->factory->get('Query\\QOM\\QueryObjectModel', array($this->objectManager, $source, $constraint, $orderings, $columns)); }
/** * {@inheritDoc} */ public function createWorkspace($name, $srcWorkspace = null) { if (null != $srcWorkspace) { // https://issues.apache.org/jira/browse/JCR-3144 throw new UnsupportedRepositoryOperationException('Can not create a workspace from a source workspace as we neither implemented clone nor have native support for this'); } $curl = $this->getCurl(); $uri = $this->server . $name; $request = $this->factory->get('Transport\\Jackrabbit\\Request', array($this, $curl, Request::MKWORKSPACE, $uri)); $request->setCredentials($this->credentials); foreach ($this->defaultHeaders as $header) { $request->addHeader($header); } if (!$this->sendExpect) { $request->addHeader("Expect:"); } $request->execute(); }
/** * {@inheritDoc} * * @api */ public function getQOMFactory() { return $this->factory->get('Query\\QOM\\QueryObjectModelFactory', array($this->objectManager)); }