File Manager

Current Directory: /home/astoriaah/www/components/com_jce/editor/tiny_mce/plugins/microdata
Viewing File: /home/astoriaah/www/components/com_jce/editor/tiny_mce/plugins/microdata/microdata.php
<?php /** * @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved * @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * JCE is free software. This version may have been modified pursuant * to the GNU General Public License, and as distributed it includes or * is derivative of works licensed under the GNU General Public License or * other free or open source software licenses */ defined('JPATH_PLATFORM') or die; // Load class dependencies // Link Plugin Controller class WFMicrodataPlugin extends WFEditorPlugin { protected static $_url = 'https://schema.org/version/latest/schemaorg-current-https.jsonld'; //protected static $_url = 'https://schema.org/docs/schema_org_rdfa.html'; protected static $_schema = null; /** * Constructor activating the default information of the class. */ public function __construct() { parent::__construct(); $request = WFRequest::getInstance(); $request->setRequest(array($this, 'getSchema')); $request->setRequest(array($this, 'getTypeList')); $request->setRequest(array($this, 'getPropertyList')); } public function display() { parent::display(); $document = WFDocument::getInstance(); $settings = $this->getSettings(); $document->addScriptDeclaration('MicrodataDialog.settings=' . json_encode($settings) . ';'); $tabs = WFTabs::getInstance(array( 'base_path' => WF_EDITOR_PLUGIN, )); // Add tabs $tabs->addTab('microdata', 1); // add link stylesheet $document->addStyleSheet(array('microdata'), 'plugins'); // add link scripts last $document->addScript(array('microdata'), 'plugins'); } public function getSettings($settings = array()) { return parent::getSettings($settings); } public function getPropertyList($type) { $schema = $this->getSchema('types'); if (isset($schema->types->$type)) { return $schema->types->$type; } return false; } /** * array_merge_recursive does indeed merge arrays, but it converts values with duplicate * keys to arrays rather than overwriting the value in the first array with the duplicate * value in the second array, as array_merge does. I.e., with array_merge_recursive, * this happens (documented behavior):. * * array_merge_recursive(array('key' => 'org value'), array('key' => 'new value')); * => array('key' => array('org value', 'new value')); * * array_merge_recursive_distinct does not change the datatypes of the values in the arrays. * Matching keys' values in the second array overwrite those in the first array, as is the * case with array_merge, i.e.: * * array_merge_recursive_distinct(array('key' => 'org value'), array('key' => 'new value')); * => array('key' => array('new value')); * * Parameters are passed by reference, though only for performance reasons. They're not * altered by this function. * * @param array $array1 * @param array $array2 * * @return array * * @author Daniel <daniel (at) danielsmedegaardbuus (dot) dk> * @author Gabriel Sobrinho <gabriel (dot) sobrinho (at) gmail (dot) com> */ private static function array_merge_recursive_distinct(array &$array1, array &$array2) { $merged = $array1; foreach ($array2 as $key => &$value) { if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) { $merged[$key] = self::array_merge_recursive_distinct($merged[$key], $value); } else { $merged[$key] = $value; } } return $merged; } private static function findClassPositionByType($needle, $array) { foreach ($array as $pos => $item) { if ($needle == $item['resource']) { return $pos; } } return false; } private static function extractKey($value) { if (is_array($value) && array_key_exists('@value', $value)) { $value = $value['@value']; } // key is in url format, eg: 'https://schema.org/value' if (strpos($value, '://') !== false) { $key = parse_url($value, PHP_URL_PATH); if (!$key) { return $value; } return trim($key, "/"); } // key is in format 'schema:value' if (substr($value, 0, 7) === 'schema:') { return substr($value, 7); } return $value; } private static function buildListFromJson($nodes) { $data = array(); $nodes = isset($nodes['@graph']) ? $nodes['@graph'] : array(); foreach ($nodes as $node) { $id = self::extractKey($node['@id']); if ($node['@type'] != 'rdfs:Class') { continue; } if (isset($node['rdfs:subClassOf'])) { continue; } $comment = ''; if (isset($node['rdfs:comment'])) { $comment = self::extractKey($node['rdfs:comment']); } $values = array( 'resource' => $id, 'comment' => $comment, 'domainIncludes' => array(), 'rangeIncludes' => array(), ); $data[] = $values; } $count = count($nodes); do { foreach ($nodes as $node) { if ($node['@type'] != 'rdfs:Class') { $count--; continue; } if (!isset($node['rdfs:subClassOf'])) { $count--; continue; } $id = self::extractKey($node['@id']); if (self::findClassPositionByType($id, $data)) { $count--; continue; } $comment = ''; if (isset($node['rdfs:comment'])) { $comment = self::extractKey($node['rdfs:comment']); } $values = array( 'resource' => $id, 'comment' => $comment, 'subClassOf' => array(), 'domainIncludes' => array(), 'rangeIncludes' => array(), ); $items = (array) $node['rdfs:subClassOf']; foreach ($items as $item) { if (is_string($item)) { $values['subClassOf'][] = self::extractKey($item); } else { $values['subClassOf'][] = self::extractKey($item['@id']); } } $pos = false; foreach ($values['subClassOf'] as $cls) { $pos = self::findClassPositionByType($cls, $data); if ($pos !== false) { array_splice($data, $pos + 1, 0, array($values)); } } if ($pos) { $count--; } } } while ($count > 0); foreach ($nodes as $node) { if ($node['@type'] != 'rdf:Property') { continue; } $id = self::extractKey($node['@id']); $comment = ''; if (isset($node['rdfs:comment'])) { $comment = self::extractKey($node['rdfs:comment']); } $entry = array( 'label' => $id, 'comment' => $comment, ); foreach (['domainIncludes', 'rangeIncludes'] as $prop) { $key = 'schema:' . $prop; if (!isset($node[$key])) { continue; } $val = $node[$key]; if (!is_array($val)) { $subclass = self::extractKey($val['@id']); array_walk($data, function (&$item) use ($subclass, $prop, $entry) { if ($item['resource'] == $subclass) { $item[$prop] = array_merge($item[$prop], array($entry)); } }); } else { foreach ($val as $subclass) { if (!is_string($subclass)) { $subclass = $subclass['@id']; } $subclass = self::extractKey($subclass); array_walk($data, function (&$item) use ($subclass, $prop, $entry) { if ($item['resource'] == $subclass) { $item[$prop] = array_merge($item[$prop], array($entry)); } }); } } } } return $data; } private static function buildListFromDom($html) { $dom = new \DOMDocument(); $dom->loadHTML($html); $data = array(); // dom is empty, return cache if (empty($dom)) { return $data; } $nodes = $dom->getElementsByTagName('div'); // no div nodes, return cache if ($nodes->length === 0) { return $data; } foreach ($nodes as $node) { $value = self::extractKey($node->getAttribute('resource')); if ($node->getAttribute('typeof') === 'rdfs:Class') { $subclass = array(); $comment = ''; foreach ($node->getElementsByTagName('a') as $item) { if ($item->getAttribute('property') === 'rdfs:subClassOf') { $subclass[] = self::extractKey($item->nodeValue); } } foreach ($node->getElementsByTagName('span') as $item) { $prop = $item->getAttribute('property'); if ($prop === 'rdfs:comment') { $comment = self::extractKey($item->nodeValue); } } $arr = array($value => array('resource' => $value, 'comment' => $comment, 'subClassOf' => $subclass, 'domainIncludes' => array(), 'rangeIncludes' => array())); $data = self::array_merge_recursive_distinct($data, $arr); } if ($node->getAttribute('typeof') === 'rdf:Property') { $comment = ''; foreach ($node->getElementsByTagName('span') as $item) { $prop = self::extractKey($item->getAttribute('property')); if ($prop === 'rdfs:comment') { $comment = self::extractKey($item->nodeValue); } } foreach ($node->getElementsByTagName('a') as $item) { $prop = self::extractKey($item->getAttribute('property')); if ($prop === 'domainIncludes' || $prop === 'rangeIncludes') { $subclass = self::extractKey($item->nodeValue); if ($value) { $entry = array('label' => $value, 'comment' => $comment); $arr = array($subclass => array($prop => array($entry))); $data = array_merge_recursive($data, $arr); } } } } } return $data; } private function getData($url) { $http = JHttpFactory::getHttp(); try { $response = $http->get($url); } catch (\RuntimeException $e) { $response = null; } if ($response === null || $response->code !== 200) { return array('error' => JText::_('Unable to load schema - Invalid response from ' . $url)); } /*if ($data = gzdecode($response->body)) { return $data; }*/ return $response->body; } public function getSchema() { jimport('joomla.filesystem.file'); // get the url from parameters or default $url = $this->getParam('schema_url', self::$_url); if (empty(self::$_schema)) { // create cache file path $cache = JPATH_SITE . '/cache/com_jce/' . md5($url) . '.json'; // get refresh time $ttl = (int) $this->getParam('cache_ttl', 7); // load data from cache file if (JFile::exists($cache)) { $data = file_get_contents($cache); self::$_schema = json_decode($data); } if (empty(self::$_schema) || !$ttl || (JFile::exists($cache) && filemtime($cache) >= strtotime($ttl . ' days ago'))) { if (pathinfo($url, PATHINFO_EXTENSION) === 'jsonld') { $jsonld = $this->getData($url); if (!is_string($jsonld)) { return self::$_schema; } $json = json_decode($jsonld, true); if (empty($json)) { return self::$_schema; } $data = self::buildListFromJson($json); } else { $html = $this->getData($url); // result should be string, otherwise an error if (!is_string($html)) { return $html; } // error getting data, return cache if (empty($html)) { return self::$_schema; } $data = self::buildListFromDom($html); } // no new list created, return cache if (empty($data)) { return empty(self::$_schema) ? 'Unable to build schema list' : self::$_schema; } // set schema and write to cache self::$_schema = $data; JFile::write($cache, json_encode($data)); } } return self::$_schema; } public function getTypeList() { $schema = $this->getSchema(); $options = array(); foreach ($schema as $key => $value) { $options[] = array('key' => $key, 'value' => $value->resource); } return $options; } }