Resources are objects which can be stored in a resource repository. Resources
have a path, under which they are stored in the repository.
Depending on the implementation, resources may offer additional functionality:
* Resources that are similar to files in that they have a body and a size
should implement {@link BodyResource}.
Resources can be attached to a repository by calling {@link attachTo()}. They
can be detached again by calling {@link detach()}. Use {@link isAttached()}
to find out whether a resource is attached and {@link getRepository()} to
obtain the attached repository.
You can create a reference to a resource by calling {@link createReference()}.
References can have different paths than the resource they are referencing.
Otherwise, they are identical to the referenced resource. Use
{@link isReference()} to check whether a resource is a reference. You can
call {@link getRepositoryPath()} to retrieve the path of the referenced
resource.
If you implement a custom resource, let your test extend
{@link AbstractResourceTest} to make sure your resource satisfies the
constraints of the interface. Extend {@link GenericResource} if you want to
avoid reimplementing basic functionality.
/** * {@inheritdoc} */ public function append(PuliResource $resource) { if (!isset($this->versions[$resource->getPath()])) { $this->versions[$resource->getPath()] = array(); } $this->versions[$resource->getPath()][] = $resource; }
private function doSerializeResource(PuliResource $resource, $depth = 0) { $data = array(); $repositoryAlias = $this->registry->getRepositoryAlias($resource->getRepository()); $data['repository_alias'] = $repositoryAlias; $data['repository_type'] = $this->registry->getRepositoryType($resource->getRepository()); $data['payload_alias'] = $this->payloadAliasRegistry->getPayloadAlias($resource); $data['payload_type'] = null; if ($resource instanceof CmfResource) { $data['payload_type'] = $resource->getPayloadType(); } $data['path'] = $resource->getPath(); $data['label'] = $data['node_name'] = PathHelper::getNodeName($data['path']); $data['repository_path'] = $resource->getRepositoryPath(); $enhancers = $this->enhancerRegistry->getEnhancers($repositoryAlias); $children = array(); foreach ($resource->listChildren() as $name => $childResource) { $children[$name] = array(); if ($depth < 2) { $children[$name] = $this->doSerializeResource($childResource, $depth + 1); } } $data['children'] = $children; if ($resource instanceof BodyResource) { $data['body'] = $resource->getBody(); } foreach ($enhancers as $enhancer) { $data = $enhancer->enhance($data, $resource); } return $data; }
/** * {@inheritdoc} */ public function supports(PuliResource $resource) { if (false === $resource instanceof CmfResource) { return false; } return $this->metadataFactory->hasMetadataFor(ClassUtils::getRealClass($resource->getPayloadType())); }
/** * Return the descriptors value for the given descriptor. * * @param string $descriptor * * @return mixed */ public function get($descriptor) { if (!isset($this->descriptors[$descriptor])) { throw new \InvalidArgumentException(sprintf('Descriptor "%s" not supported for resource "%s" of class "%s". Supported descriptors: "%s"', $descriptor, $this->resource->getPath(), get_class($this->resource), implode('", "', array_keys($this->descriptors)))); } return $this->descriptors[$descriptor]; }
/** * {@inheritdoc} */ public function append(PuliResource $resource) { if (null === $this->json) { $this->load(); } if (!isset($this->json[$resource->getPath()])) { $this->json[$resource->getPath()] = array(); } $this->json[$resource->getPath()][] = serialize($resource); $this->flush(); }
/** * Return the alias for the given PHPCR resource. * * @param PuliResource $resource * * @return string */ public function getPayloadAlias(PuliResource $resource) { $repositoryType = $this->repositoryRegistry->getRepositoryType($resource->getRepository()); $type = null; if ($resource instanceof CmfResource) { $type = $resource->getPayloadType(); } if (null === $type) { return; } if (!isset($this->aliasesByRepository[$repositoryType])) { return; } if (!isset($this->aliasesByRepository[$repositoryType][$type])) { return; } return $this->aliasesByRepository[$repositoryType][$type]; }
/** * {@inheritdoc} */ public function supports(PuliResource $resource) { if (false === $resource instanceof CmfResource) { return false; } try { $this->registry->getByClass($resource->getPayloadType()); } catch (\InvalidArgumentException $e) { return false; } return true; }
/** * {@inheritdoc} */ public function enhance(array $data, PuliResource $resource) { $object = $resource->getPayload(); // sonata has dependency on ClassUtils so this is fine. $class = ClassUtils::getClass($object); if (false === $this->pool->hasAdminByClass($class)) { return $data; } $admin = $this->pool->getAdminByClass($class); $links = array(); $routeCollection = $admin->getRoutes(); foreach ($routeCollection->getElements() as $code => $route) { $routeName = $route->getDefault('_sonata_name'); $url = $this->urlGenerator->generate($routeName, array($admin->getIdParameter() => $admin->getUrlsafeIdentifier($object)), true); $routeRole = substr($code, strlen($admin->getCode()) + 1); $links[$routeRole] = $url; } $data['label'] = $admin->toString($object); $data['sonata_label'] = $admin->getLabel(); $data['sonata_links'] = $links; return $data; }
/** * Formats the name of the resource. * * Resources with children are colored. * * @param PuliResource $resource The resource. * * @return string|null The formatted name. */ private function formatName(PuliResource $resource) { $name = $resource->getName(); if ($resource->hasChildren()) { return '<c1>' . $name . '</c1>'; } return $name; }
/** * Returns an iterator for the children of a resource. * * @param PuliResource $resource The resource. * * @return RegexFilterIterator The iterator. */ private function getChildIterator(PuliResource $resource) { $staticPrefix = rtrim($resource->getPath(), '/') . '/'; $regExp = '~^' . preg_quote($staticPrefix, '~') . '[^/]+$~'; return new RegexFilterIterator($regExp, $staticPrefix, new ArrayIterator($this->resources), RegexFilterIterator::FILTER_KEY); }
/** * {@inheritdoc} */ public function append(PuliResource $resource) { $versions = $this->store->get($resource->getPath(), array()); $versions[] = $resource; $this->store->set($resource->getPath(), $versions); }
/** * Returns the path where a resource is going to be installed. * * This is a path relative to the document root of the target server. * * @param PuliResource $resource The resource. * * @return string The server path. */ public function getServerPathForResource(PuliResource $resource) { $relPath = Path::makeRelative($resource->getRepositoryPath(), $this->basePath); return '/' . trim($this->mapping->getServerPath() . '/' . $relPath, '/'); }
/** * {@inheritdoc} */ protected function storeVersion(PuliResource $resource) { $path = $resource->getPath(); // Newly inserted parent directories and the resource need to be // sorted before we can correctly search references below krsort($this->json); // If a mapping exists for a sub-path of this resource // (e.g. $path = /a, mapped sub-path = /a/b) // we need to record the order, since by default sub-paths are // preferred over super paths $references = $this->searchReferences($path, self::NO_SEARCH_FILESYSTEM | self::NO_CHECK_FILE_EXISTS | self::INCLUDE_ANCESTORS | self::INCLUDE_NESTED); // Filter virtual resources $references = array_filter($references, function ($currentReferences) { return array(null) !== $currentReferences; }); // The $references contain: // - any sub references (e.g. /a/b/c, /a/b/d) // - the reference itself at $pos (e.g. /a/b) // - non-null parent references (e.g. /a) // (in that order, since long paths are sorted before short paths) $pos = array_search($path, array_keys($references), true); // We need to do three things: // 1. If any parent mapping has an order defined, inherit that order if ($pos + 1 < count($references)) { // Inherit the parent order if necessary if (!isset($this->json['_order'][$path])) { $parentReferences = array_slice($references, $pos + 1); $this->initWithParentOrder($path, $parentReferences); } // A parent order was inherited. Insert the path itself. if (isset($this->json['_order'][$path])) { $this->prependOrderEntry($path, $path); } } // 2. If there are child mappings, insert the current path into their order if ($pos > 0) { $subReferences = array_slice($references, 0, $pos); foreach ($subReferences as $subPath => $_) { if (isset($this->json['_order'][$subPath])) { continue; } if (isset($this->json['_order'][$path])) { $this->json['_order'][$subPath] = $this->json['_order'][$path]; } else { $this->initWithDefaultOrder($subPath, $path, $references); } } // After initializing all order entries, insert the new one foreach ($subReferences as $subPath => $_) { $this->prependOrderEntry($subPath, $path); } } }
private function addResource($path, PuliResource $resource, $checkParentsForSymlinks = true) { $pathInBaseDir = $this->baseDir . $path; $hasChildren = $resource->hasChildren(); $hasBody = $resource instanceof BodyResource; if ($hasChildren && $hasBody) { throw new UnsupportedResourceException(sprintf('Instances of BodyResource do not support child resources in ' . 'FilesystemRepository. Tried to add a BodyResource with ' . 'children at %s.', $path)); } $resource = clone $resource; $resource->attachTo($this, $path); if ($this->symlink && $checkParentsForSymlinks) { $this->replaceParentSymlinksByCopies($path); } if ($resource instanceof FilesystemResource) { if ($this->symlink) { $this->symlinkMirror($resource->getFilesystemPath(), $pathInBaseDir); } elseif ($hasBody) { $this->filesystem->copy($resource->getFilesystemPath(), $pathInBaseDir); } else { $this->filesystem->mirror($resource->getFilesystemPath(), $pathInBaseDir); } $this->storeVersion($resource); return; } if ($resource instanceof LinkResource) { if (!$this->symlink) { throw new UnsupportedResourceException(sprintf('LinkResource requires support of symbolic links in FilesystemRepository. ' . 'Tried to add a LinkResource at %s.', $path)); } $this->filesystem->symlink($this->baseDir . $resource->getTargetPath(), $pathInBaseDir); $this->storeVersion($resource); return; } if ($hasBody) { file_put_contents($pathInBaseDir, $resource->getBody()); $this->storeVersion($resource); return; } if (is_file($pathInBaseDir)) { $this->filesystem->remove($pathInBaseDir); } if (!file_exists($pathInBaseDir)) { mkdir($pathInBaseDir, 0777, true); } foreach ($resource->listChildren() as $child) { $this->addResource($path . '/' . $child->getName(), $child, false); } $this->storeVersion($resource); }
/** * {@inheritdoc} */ public function enhance(array $data, PuliResource $resource) { $payload = $resource->getPayload(); $data['payload'] = $payload; return $data; }
/** * {@inheritdoc} */ public function supports(PuliResource $resource) { if (false === $resource instanceof CmfResource) { return false; } $payload = $resource->getPayload(); // sonata has dependency on ClassUtils so this is fine. $class = ClassUtils::getClass($payload); return $this->pool->hasAdminByClass($class); }
/** * Recursively prints the tree for the given resource. * * @param IO $io The I/O. * @param PuliResource $resource The printed resource. * @param int $total Collects the total number of printed resources. * @param string $prefix The prefix for all printed resources. */ private function printTree(IO $io, PuliResource $resource, &$total, $prefix = '') { // The root node has an empty name $children = $resource->listChildren(); $lastIndex = count($children) - 1; $index = 0; foreach ($children as $child) { $isLastChild = $index === $lastIndex; $childPrefix = $isLastChild ? self::LAST_CHILD_PREFIX : self::CHILD_PREFIX; $nestingPrefix = $isLastChild ? self::NESTING_CLOSED_PREFIX : self::NESTING_OPEN_PREFIX; $name = $child->getName() ?: '/'; if ($child->hasChildren()) { $name = '<c1>' . $name . '</c1>'; } $io->writeLine($prefix . $childPrefix . $name); $this->printTree($io, $child, $total, $prefix . $nestingPrefix); ++$index; ++$total; } }
/** * It should return the resource that it describes. */ public function testGetResource() { $resource = $this->description->getResource(); $this->assertSame($this->resource->reveal(), $resource); }