| Server IP : 54.36.91.62 / Your IP : 216.73.217.112 Web Server : Apache System : Linux webm013.cluster127.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64 User : coopiak ( 151928) PHP Version : 8.3.23 Disable Function : _dyuweyrj4,_dyuweyrj4r,dl MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /home/c/o/o/coopiak/amisdesseniors-fr/plugins/system/jcepro/editor/plugins/microdata/ |
Upload File : |
<?php
/**
* @package JCE
* @subpackage Editor
*
* @copyright Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Filesystem\File;
use Joomla\CMS\Http\HttpFactory;
// 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($config = array())
{
parent::__construct($config);
$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' => __DIR__
)
);
// Add tabs
$tabs->addTab('microdata', 1);
// add link stylesheet
$document->addStyleSheet(
array(
'plugins/microdata/css/microdata',
),
'pro'
);
// add link scripts last
$document->addScript(array(
'plugins/microdata/js/microdata',
),
'pro');
}
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 = HttpFactory::getHttp();
try {
$response = $http->get($url);
} catch (\RuntimeException $e) {
$response = null;
}
if ($response === null || $response->code !== 200) {
return array('error' => Text::_('Unable to load schema - Invalid response from ' . $url));
}
/*if ($data = gzdecode($response->body)) {
return $data;
}*/
return $response->body;
}
public function getSchema()
{
// 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 (File::exists($cache)) {
$data = file_get_contents($cache);
self::$_schema = json_decode($data);
}
if (empty(self::$_schema) || !$ttl || (File::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;
File::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;
}
}