View source
<?php
namespace Drupal\schema_metatag;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Cache\CacheBackendInterface;
class SchemaMetatagClient implements SchemaMetatagClientInterface {
protected $moduleHandler;
protected $cacheBackend;
protected static $scheme = 'http';
protected static $prefix = 'http://schema.org/';
public function __construct(ModuleHandlerInterface $moduleHandler, CacheBackendInterface $cache_backend) {
$this->moduleHandler = $moduleHandler;
$this->cacheBackend = $cache_backend;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('module_handler'), $container
->get('schema_metatag.cache'));
}
public function getLocalFile() {
$path = DRUPAL_ROOT . '/' . $this->moduleHandler
->getModule('schema_metatag')
->getPath();
$uri = $path . '/data/schemaorg-all-http.jsonld';
try {
if ($response = file_get_contents($uri)) {
$data = json_decode($response, TRUE);
if (is_array($data) && array_key_exists('@graph', $data)) {
return $data['@graph'];
}
}
} catch (RequestException $e) {
watchdog_exception('schema_metatag', $e);
}
return FALSE;
}
public function objectInfo($clear = FALSE) {
$cid = "schema_metatag.objects";
if (!$clear && ($cache = $this->cacheBackend
->get($cid))) {
$items = $cache->data;
}
else {
$data = $this
->getLocalFile();
$items = [];
foreach ($data as $item) {
if ($this
->isIncludedClass($item)) {
$subobject_of = [];
$object = is_array($item['rdfs:label']) ? $item['rdfs:label']['@value'] : $item['rdfs:label'];
$description = $item['rdfs:comment'];
if (array_key_exists('rdfs:subClassOf', $item)) {
foreach ($item['rdfs:subClassOf'] as $value) {
if (!is_array($value)) {
$value = [
$value,
];
}
foreach ($value as $value_item) {
$subobject_of[] = str_replace(static::$prefix, '', $value_item);
}
}
}
$description = strip_tags($description);
$items[$object] = [
'object' => $object,
'description' => $description,
'parents' => $subobject_of,
];
}
}
$this->cacheBackend
->set($cid, $items, CacheBackendInterface::CACHE_PERMANENT);
}
return $items;
}
public function propertyInfo($clear = FALSE) {
$cid = "schema_metatag.properties";
if (!$clear && ($cache = $this->cacheBackend
->get($cid))) {
$items = $cache->data;
}
else {
$data = $this
->getLocalFile();
$items = [];
foreach ($data as $item) {
if ($this
->isIncludedProperty($item)) {
$expected_types = $belongs_to = [];
$property = $item['rdfs:label'];
$description = $item['rdfs:comment'];
foreach ($item[static::$prefix . 'rangeIncludes'] as $value) {
foreach ((array) $value as $value_item) {
$expected_types[] = str_replace(static::$prefix, '', $value_item);
}
}
if (!empty($expected_types)) {
foreach ($item[static::$prefix . 'domainIncludes'] as $value) {
foreach ((array) $value as $value_item) {
$class = str_replace(static::$prefix, '', $value_item);
$belongs_to[] = $class;
}
}
foreach ($belongs_to as $parent) {
$items[$parent][$property] = [
'property' => $property,
'description' => strip_tags($description),
'expected_types' => array_unique($expected_types),
];
}
}
}
$this->cacheBackend
->set($cid, $items, CacheBackendInterface::CACHE_PERMANENT);
}
}
return $items;
}
public function getObjectTree($clear = FALSE, $clear_objects = FALSE) {
$cid = "schema_metatag.tree";
if (!$clear && !$clear_objects && ($cache = $this->cacheBackend
->get($cid))) {
$tree = $cache->data;
}
else {
$objects = $this
->objectInfo($clear_objects);
$tree = [];
$flat = [];
foreach ($objects as $child => $item) {
if (empty($item['parents'])) {
$tree[$child] =& $flat[$child];
}
else {
foreach ($item['parents'] as $parent) {
if (!isset($flat[$child])) {
$flat[$child] = [];
}
$flat[$parent][$child] =& $flat[$child];
}
}
}
$this
->sortAssocArray($tree);
$this->cacheBackend
->set($cid, $tree, CacheBackendInterface::CACHE_PERMANENT);
}
return $tree;
}
public function getTree($parent_name = NULL, $depth = -1, $clear = FALSE, $clear_tree = FALSE, $clear_objects = FALSE) {
$cid = "schema_metatag.{$parent_name}.{$depth}";
if (!$clear && !$clear_tree && !$clear_objects && ($cache = $this->cacheBackend
->get($cid))) {
$tree = $cache->data;
}
else {
$base_tree = $this
->getObjectTree($clear_tree, $clear_objects);
$tree = $this
->getUncachedTree($base_tree, $parent_name, $depth);
$this->cacheBackend
->set($cid, $tree, CacheBackendInterface::CACHE_PERMANENT);
}
return $tree;
}
public function getUncachedTree($base_tree, $parent_name = NULL, $depth = -1) {
$tree = [];
if (!empty($parent_name)) {
$iterator = new \RecursiveArrayIterator($base_tree);
$iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $key => $value) {
if ($key == $parent_name) {
$tree = [
$parent_name => $iterator
->getInnerIterator()
->offsetGet($key),
];
break;
}
}
}
else {
$tree = $base_tree;
}
if ($depth !== -1) {
$iterator = new \RecursiveArrayIterator($tree);
$iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
$iterator
->setMaxDepth($depth);
foreach ($iterator as $key => $value) {
if ($iterator
->getDepth() == $depth) {
$child_depth = $iterator
->getDepth();
for ($current_depth = $child_depth; $current_depth >= 0; $current_depth--) {
$child_iterator = $iterator
->getSubIterator($current_depth);
$parent_iterator = $iterator
->getSubIterator($current_depth + 1);
if ($child_depth === $current_depth) {
$replacement = [];
}
else {
$replacement = $parent_iterator
->getArrayCopy();
}
$child_iterator
->offsetSet($child_iterator
->key(), $replacement);
}
}
}
$tree = $iterator
->getArrayCopy();
}
return $tree;
}
public function getParents($child_name) {
$parents = [];
$tree = $this
->getTree();
$iterator = new \RecursiveArrayIterator($tree);
$iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
$depth = 0;
$prev_depth = 0;
$prev_key = '';
foreach ($iterator as $key => $value) {
$depth = $iterator
->getDepth();
if ($depth > $prev_depth) {
$parents[] = $prev_key;
}
elseif ($depth < $prev_depth) {
for ($i = $depth; $i < $prev_depth; $i++) {
array_pop($parents);
}
}
if ($key == $child_name) {
return $parents;
}
$prev_depth = $depth;
$prev_key = $key;
}
}
public function getOptionList($parent_name = NULL, $depth = -1) {
$tree = $this
->getTree($parent_name, $depth);
$separator = '-';
$label_list = [];
$previous_keys = [];
$key_list = [];
$iterator = new \RecursiveArrayIterator($tree);
$iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $key => $item) {
if (!in_array($key, $previous_keys)) {
$depth = $iterator
->getDepth() + 1;
$label_list[] = str_repeat($separator, $depth) . ' ' . $key;
$key_list[] = $key;
$previous_keys[] = $key;
}
}
$option_list = array_combine($key_list, $label_list);
return $option_list;
}
public function clearData() {
$this->cacheBackend
->invalidateAll();
}
public function sortAssocArray(array &$array) {
ksort($array);
foreach ($array as &$a) {
if (is_array($a)) {
self::sortAssocArray($a);
}
}
}
public function isIncludedClass(array $item) {
if (!isset($item['@type']) || !isset($item['rdfs:label'])) {
return FALSE;
}
if ($item['@type'] != 'rdfs:Class') {
return FALSE;
}
if (!empty($item[static::$prefix . 'supersededBy'])) {
return FALSE;
}
return TRUE;
}
public function isIncludedProperty(array $item) {
if (!isset($item['@type'])) {
return FALSE;
}
if ($item['@type'] != 'rdf:Property') {
return FALSE;
}
if (!empty($item[static::$prefix . 'supersededBy'])) {
return FALSE;
}
return TRUE;
}
}