*/ class ResourceService extends ConfigurableService { public const SERVICE_ID = 'tao/ResourceService'; public const LABEL_URI = 'http://www.w3.org/2000/01/rdf-schema#label'; public const OPTION_CLASS_NESTING_LEVEL = 'class-nesting-level'; private const DEFAULT_CLASS_NESTING_LEVEL = 999; /** * The different lookup formats */ private static $formats = ['list', 'tree']; /** * The lookup instances by format */ private $lookups; /** * Get the list of classes from the given root class * * @param core_kernel_classes_Class $rootClass the root class * @return array the classes hierarchy */ public function getAllClasses(core_kernel_classes_Class $rootClass): array { return [ 'uri' => $rootClass->getUri(), 'label' => $rootClass->getLabel(), 'children' => $this->getSubClasses($rootClass->getSubClasses(false)) ]; } /** * Get the class subclasses * * @param core_kernel_classes_Class[] $subClasses * @param int $nestingLevel * * @return array the classes hierarchy */ private function getSubClasses(array $subClasses, int $nestingLevel = 0): array { if ($nestingLevel >= $this->getNestingLevelLimit()) { return []; } $result = []; foreach ($subClasses as $subClass) { $children = $subClass->getSubClasses(false); $entry = [ 'uri' => $subClass->getUri(), 'label' => $subClass->getLabel() ]; if (count($children) > 0) { $entry['children'] = $this->getSubClasses($children, $nestingLevel + 1); } $result[] = $entry; } return $result; } private function getNestingLevelLimit(): int { return $this->getOption(self::OPTION_CLASS_NESTING_LEVEL) ?? self::DEFAULT_CLASS_NESTING_LEVEL; } /** * Retrieve the resources for the given parameters * * @param core_kernel_classes_Class $rootClass * @param string $format the lookup format * @param array $selectedUris * @param string|array $search to filter by label if a string or provides the search filters * @param int $offset for paging * @param int $limit for paging * * @return core_kernel_classes_Class[] the resources * @throws InvalidServiceManagerException */ public function getResources( core_kernel_classes_Class $rootClass, $format = 'list', $selectedUris = [], $search = '', $offset = 0, $limit = 30 ): array { $propertyFilters = $this->getPropertyFilters($search); $result = []; $resourceLookup = $this->getResourceLookup($format); if (!is_null($resourceLookup)) { $result = $resourceLookup->getResources($rootClass, $selectedUris, $propertyFilters, $offset, $limit); } return $result; } /** * Retrieve the classes for the given parameters * * @param core_kernel_classes_Class $rootClass * @param string $format the lookup format * @param array $selectedUris * @param string|array $search to filter by label if a string or provides the search filters * @param int $offset for paging * @param int $limit for paging * * @return core_kernel_classes_Class[] the classes * @throws InvalidServiceManagerException */ public function getClasses( core_kernel_classes_Class $rootClass, $format = 'list', $selectedUris = [], $search = '', $offset = 0, $limit = 30 ): array { $propertyFilters = $this->getPropertyFilters($search); $result = []; $resourceLookup = $this->getResourceLookup($format); if (!is_null($resourceLookup)) { $result = $resourceLookup->getClasses($rootClass, $selectedUris, $propertyFilters, $offset, $limit); } return $result; } /** * Get the permissions for a list of resources. * * @param User $user the user to check the permissions * @param array $resources the resources to get the permissions * * @return array the available rights and the permissions per resource */ public function getResourcesPermissions(User $user, $resources): array { $permissions = []; if (!is_null($user)) { try { $permissionManager = $this->getServiceManager()->get(PermissionInterface::SERVICE_ID); $supportedRights = $permissionManager->getSupportedRights(); $permissions['supportedRights'] = $supportedRights; if (count($supportedRights) > 0) { $uris = $this->getUris($resources); $permissions['data'] = $permissionManager->getPermissions($user, $uris); } } catch (Exception $e) { common_Logger::w('Unable to retrieve permssions ' . $e->getMessage()); } } return $permissions; } /** * Get the filters based on the search param * * @param string|array $search to filter by label if a string or provides the search filters * @return array the list of property filters */ private function getPropertyFilters($search = ''): array { $propertyFilters = []; if (is_string($search) && strlen(trim($search)) > 0) { $propertyFilters[self::LABEL_URI] = $search; } if (is_array($search)) { foreach ($search as $uri => $value) { if ( is_string($uri) && (is_string($value) && strlen(trim($value)) > 0) || (is_array($value) && count($value) > 0) ) { $propertyFilters[$uri] = $value; } } } return $propertyFilters; } /** * Get the resource lookup for the given format * * @param $format * * @return ResourceLookup|null * * @throws InvalidServiceManagerException */ private function getResourceLookup($format): ?ResourceLookup { if (in_array($format, self::$formats, true)) { if (!isset($this->lookups)) { $this->lookups = [ 'list' => $this->getServiceManager()->get(ListResourceLookup::SERVICE_ID), 'tree' => $this->getServiceManager()->get(TreeResourceLookup::SERVICE_ID) ]; } return $this->lookups[$format]; } return null; } /** * Walk through the resources (recursively) to get theirs URIs * * @param array|core_kernel_classes_Resource $nodes the tree or a sub tree, a resource or a resource list * @return string[] the list of URIs */ private function getUris($nodes): array { $uris = []; if ($nodes instanceof core_kernel_classes_Resource) { $uris[] = $nodes->getUri(); } if (is_array($nodes)) { //legacy format if (isset($nodes['attributes']['data-uri'])) { $uris[] = $nodes['attributes']['data-uri']; } if (isset($nodes['uri'])) { $uris[] = $nodes['uri']; } $treeKeys = array_keys($nodes); if (isset($treeKeys[0]) && is_int($treeKeys[0])) { foreach ($nodes as $node) { $uris = array_merge($uris, $this->getUris($node)); } } if (isset($nodes['children'])) { $uris = array_merge($uris, $this->getUris($nodes['children'])); } } return $uris; } }