first commit
This commit is contained in:
26
plugins/system/schemaorg/forms/schemaorg.xml
Executable file
26
plugins/system/schemaorg/forms/schemaorg.xml
Executable file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form>
|
||||
<fields name="schema">
|
||||
<fieldset
|
||||
name="schema"
|
||||
label="PLG_SYSTEM_SCHEMAORG_FIELD_SCHEMA_LABEL"
|
||||
>
|
||||
<field
|
||||
name="schemainfo"
|
||||
type="note"
|
||||
class="alert alert-info d-block w-100"
|
||||
description="PLG_SYSTEM_SCHEMAORG_FIELD_SCHEMA_DESCRIPTION"
|
||||
/>
|
||||
<field
|
||||
name="schemaType"
|
||||
type="list"
|
||||
label="PLG_SYSTEM_SCHEMAORG_FIELD_SCHEMA_TYPE_LABEL"
|
||||
default="None"
|
||||
validate="options"
|
||||
>
|
||||
<option value="None">JNONE</option>
|
||||
</field>
|
||||
|
||||
</fieldset>
|
||||
</fields>
|
||||
</form>
|
||||
77
plugins/system/schemaorg/schemaorg.xml
Executable file
77
plugins/system/schemaorg/schemaorg.xml
Executable file
@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="system" method="upgrade">
|
||||
<name>plg_system_schemaorg</name>
|
||||
<author>Joomla! Project</author>
|
||||
<creationDate>2023-07</creationDate>
|
||||
<copyright>(C) 2023 Open Source Matters, Inc.</copyright>
|
||||
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
|
||||
<authorEmail>admin@joomla.org</authorEmail>
|
||||
<authorUrl>www.joomla.org</authorUrl>
|
||||
<version>5.0.0</version>
|
||||
<description>PLG_SYSTEM_SCHEMAORG_XML_DESCRIPTION</description>
|
||||
<namespace path="src">Joomla\Plugin\System\Schemaorg</namespace>
|
||||
<files>
|
||||
<folder plugin="schemaorg">services</folder>
|
||||
<folder>src</folder>
|
||||
</files>
|
||||
<languages>
|
||||
<language tag="en-GB">language/en-GB/plg_system_schemaorg.ini</language>
|
||||
<language tag="en-GB">language/en-GB/plg_system_schemaorg.sys.ini</language>
|
||||
</languages>
|
||||
<config>
|
||||
<fields name="params">
|
||||
<fieldset name="basic">
|
||||
<field
|
||||
name="baseType"
|
||||
type="list"
|
||||
label="PLG_SYSTEM_SCHEMAORG_BASETYPE_LABEL"
|
||||
description="PLG_SYSTEM_SCHEMAORG_BASETYPE_DESCRIPTION"
|
||||
default="organization"
|
||||
validate="options"
|
||||
required="true"
|
||||
>
|
||||
<option value="organization">PLG_SYSTEM_SCHEMAORG_BASETYPE_OPTION_ORGANIZATION</option>
|
||||
<option value="person">PLG_SYSTEM_SCHEMAORG_BASETYPE_OPTION_PERSON</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="user"
|
||||
type="user"
|
||||
label="PLG_SYSTEM_SCHEMAORG_USER_LABEL"
|
||||
showon="baseType:person"
|
||||
default="0"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="name"
|
||||
type="text"
|
||||
label="PLG_SYSTEM_SCHEMAORG_NAME_LABEL"
|
||||
showon="baseType:organization[OR]user:0"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="image"
|
||||
type="media"
|
||||
label="PLG_SYSTEM_SCHEMAORG_IMAGE_LABEL"
|
||||
/>
|
||||
<field
|
||||
name="socialmedia"
|
||||
type="subform"
|
||||
label="PLG_SYSTEM_SCHEMAORG_SOCIALMEDIA_LABEL"
|
||||
multiple="true"
|
||||
>
|
||||
<form>
|
||||
<field
|
||||
name="url"
|
||||
type="url"
|
||||
label="PLG_SYSTEM_SCHEMAORG_SOCIALMEDIA_URL_LABEL"
|
||||
required="true"
|
||||
hint="https://"
|
||||
validate="url"
|
||||
/>
|
||||
</form>
|
||||
</field>
|
||||
</fieldset>
|
||||
</fields>
|
||||
</config>
|
||||
</extension>
|
||||
53
plugins/system/schemaorg/services/provider.php
Normal file
53
plugins/system/schemaorg/services/provider.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Plugin
|
||||
* @subpackage System.schemaorg
|
||||
*
|
||||
* @copyright (C) 2023 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Extension\PluginInterface;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\CMS\User\UserFactoryInterface;
|
||||
use Joomla\Database\DatabaseInterface;
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use Joomla\Event\DispatcherInterface;
|
||||
use Joomla\Plugin\System\Schemaorg\Extension\Schemaorg;
|
||||
|
||||
return new class () implements ServiceProviderInterface {
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function register(Container $container)
|
||||
{
|
||||
$container->set(
|
||||
PluginInterface::class,
|
||||
function (Container $container) {
|
||||
$dispatcher = $container->get(DispatcherInterface::class);
|
||||
|
||||
$plugin = new Schemaorg(
|
||||
$dispatcher,
|
||||
(array) PluginHelper::getPlugin('system', 'schemaorg')
|
||||
);
|
||||
|
||||
$plugin->setApplication(Factory::getApplication());
|
||||
$plugin->setDatabase(Factory::getContainer()->get(DatabaseInterface::class));
|
||||
$plugin->setUserFactory($container->get(UserFactoryInterface::class));
|
||||
|
||||
return $plugin;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
533
plugins/system/schemaorg/src/Extension/Schemaorg.php
Normal file
533
plugins/system/schemaorg/src/Extension/Schemaorg.php
Normal file
@ -0,0 +1,533 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Plugin
|
||||
* @subpackage System.schemaorg
|
||||
*
|
||||
* @copyright (C) 2023 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Plugin\System\Schemaorg\Extension;
|
||||
|
||||
use Joomla\CMS\Event\Model;
|
||||
use Joomla\CMS\Event\Plugin\System\Schemaorg\BeforeCompileHeadEvent;
|
||||
use Joomla\CMS\Event\Plugin\System\Schemaorg\PrepareDataEvent;
|
||||
use Joomla\CMS\Event\Plugin\System\Schemaorg\PrepareFormEvent;
|
||||
use Joomla\CMS\Event\Plugin\System\Schemaorg\PrepareSaveEvent;
|
||||
use Joomla\CMS\Helper\ModuleHelper;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Plugin\CMSPlugin;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Schemaorg\SchemaorgPrepareDateTrait;
|
||||
use Joomla\CMS\Schemaorg\SchemaorgPrepareImageTrait;
|
||||
use Joomla\CMS\Schemaorg\SchemaorgServiceInterface;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
use Joomla\CMS\User\UserFactoryAwareTrait;
|
||||
use Joomla\Database\DatabaseAwareTrait;
|
||||
use Joomla\Database\ParameterType;
|
||||
use Joomla\Event\SubscriberInterface;
|
||||
use Joomla\Registry\Registry;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Schemaorg System Plugin
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
final class Schemaorg extends CMSPlugin implements SubscriberInterface
|
||||
{
|
||||
use DatabaseAwareTrait;
|
||||
use SchemaorgPrepareImageTrait;
|
||||
use SchemaorgPrepareDateTrait;
|
||||
use UserFactoryAwareTrait;
|
||||
|
||||
/**
|
||||
* Returns an array of events this subscriber will listen to.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'onBeforeCompileHead' => 'onBeforeCompileHead',
|
||||
'onContentPrepareData' => 'onContentPrepareData',
|
||||
'onContentPrepareForm' => 'onContentPrepareForm',
|
||||
'onContentAfterSave' => 'onContentAfterSave',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs on content preparation
|
||||
*
|
||||
* @param Model\PrepareDataEvent $event The event
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
*/
|
||||
public function onContentPrepareData(Model\PrepareDataEvent $event)
|
||||
{
|
||||
$context = $event->getContext();
|
||||
$data = $event->getData();
|
||||
|
||||
$app = $this->getApplication();
|
||||
|
||||
if ($app->isClient('site') || !$this->isSupported($context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data = (object) $data;
|
||||
|
||||
$itemId = $data->id ?? 0;
|
||||
|
||||
// Check if the form already has some data
|
||||
if ($itemId > 0) {
|
||||
$db = $this->getDatabase();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select('*')
|
||||
->from($db->quoteName('#__schemaorg'))
|
||||
->where($db->quoteName('itemId') . '= :itemId')
|
||||
->bind(':itemId', $itemId, ParameterType::INTEGER)
|
||||
->where($db->quoteName('context') . '= :context')
|
||||
->bind(':context', $context, ParameterType::STRING);
|
||||
|
||||
$results = $db->setQuery($query)->loadAssoc();
|
||||
|
||||
if (empty($results)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$schemaType = $results['schemaType'];
|
||||
$data->schema['schemaType'] = $schemaType;
|
||||
|
||||
$schema = new Registry($results['schema']);
|
||||
|
||||
$data->schema[$schemaType] = $schema->toArray();
|
||||
}
|
||||
|
||||
$dispatcher = $this->getDispatcher();
|
||||
$event = new PrepareDataEvent('onSchemaPrepareData', [
|
||||
'subject' => $data,
|
||||
'context' => $context,
|
||||
]);
|
||||
|
||||
PluginHelper::importPlugin('schemaorg', null, true, $dispatcher);
|
||||
$dispatcher->dispatch('onSchemaPrepareData', $event);
|
||||
}
|
||||
|
||||
/**
|
||||
* The form event.
|
||||
*
|
||||
* @param Model\PrepareFormEvent $event The event
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function onContentPrepareForm(Model\PrepareFormEvent $event)
|
||||
{
|
||||
$form = $event->getForm();
|
||||
$context = $form->getName();
|
||||
$app = $this->getApplication();
|
||||
|
||||
if (!$app->isClient('administrator') || !$this->isSupported($context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Load plugin language files.
|
||||
$this->loadLanguage();
|
||||
|
||||
// Load the form fields
|
||||
$form->loadFile(JPATH_PLUGINS . '/' . $this->_type . '/' . $this->_name . '/forms/schemaorg.xml');
|
||||
|
||||
|
||||
// The user should configure the plugin first
|
||||
if (!$this->params->get('baseType')) {
|
||||
$form->removeField('schemaType', 'schema');
|
||||
|
||||
$plugin = PluginHelper::getPlugin('system', 'schemaorg');
|
||||
|
||||
$user = $this->getApplication()->getIdentity();
|
||||
|
||||
$infoText = Text::_('PLG_SYSTEM_SCHEMAORG_FIELD_SCHEMA_DESCRIPTION_NOT_CONFIGURATED');
|
||||
|
||||
// If edit permission are available, offer a link
|
||||
if ($user->authorise('core.edit', 'com_plugins')) {
|
||||
$infoText = Text::sprintf('PLG_SYSTEM_SCHEMAORG_FIELD_SCHEMA_DESCRIPTION_NOT_CONFIGURATED_ADMIN', (int) $plugin->id);
|
||||
}
|
||||
|
||||
$form->setFieldAttribute('schemainfo', 'description', $infoText, 'schema');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$dispatcher = $this->getDispatcher();
|
||||
$event = new PrepareFormEvent('onSchemaPrepareForm', [
|
||||
'subject' => $form,
|
||||
]);
|
||||
|
||||
PluginHelper::importPlugin('schemaorg', null, true, $dispatcher);
|
||||
$dispatcher->dispatch('onSchemaPrepareForm', $event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves form field data in the database
|
||||
*
|
||||
* @param Model\AfterSaveEvent $event
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function onContentAfterSave(Model\AfterSaveEvent $event)
|
||||
{
|
||||
$context = $event->getContext();
|
||||
$table = $event->getItem();
|
||||
$isNew = $event->getIsNew();
|
||||
$data = $event->getData();
|
||||
$app = $this->getApplication();
|
||||
$db = $this->getDatabase();
|
||||
|
||||
if (!$app->isClient('administrator') || !$this->isSupported($context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$itemId = (int) $table->id;
|
||||
|
||||
if (empty($data['schema']) || empty($data['schema']['schemaType']) || $data['schema']['schemaType'] === 'None') {
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
$query->delete($db->quoteName('#__schemaorg'))
|
||||
->where($db->quoteName('itemId') . '= :itemId')
|
||||
->bind(':itemId', $itemId, ParameterType::INTEGER)
|
||||
->where($db->quoteName('context') . '= :context')
|
||||
->bind(':context', $context, ParameterType::STRING);
|
||||
|
||||
$db->setQuery($query)->execute();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
$query->select('*')
|
||||
->from($db->quoteName('#__schemaorg'))
|
||||
->where($db->quoteName('itemId') . '= :itemId')
|
||||
->bind(':itemId', $itemId, ParameterType::INTEGER)
|
||||
->where($db->quoteName('context') . '= :context')
|
||||
->bind(':context', $context, ParameterType::STRING);
|
||||
|
||||
$entry = $db->setQuery($query)->loadObject();
|
||||
|
||||
if (empty($entry->id)) {
|
||||
$entry = new \stdClass();
|
||||
}
|
||||
|
||||
$entry->itemId = (int) $table->getId();
|
||||
$entry->context = $context;
|
||||
|
||||
if (isset($data['schema']['schemaType'])) {
|
||||
$entry->schemaType = $data['schema']['schemaType'];
|
||||
|
||||
if (isset($data['schema'][$entry->schemaType])) {
|
||||
$entry->schema = (new Registry($data['schema'][$entry->schemaType]))->toString();
|
||||
}
|
||||
}
|
||||
|
||||
$dispatcher = $this->getDispatcher();
|
||||
$event = new PrepareSaveEvent('onSchemaPrepareSave', [
|
||||
'subject' => $entry,
|
||||
'context' => $context,
|
||||
'item' => $table,
|
||||
'isNew' => $isNew,
|
||||
'schema' => $data['schema'],
|
||||
]);
|
||||
|
||||
PluginHelper::importPlugin('schemaorg', null, true, $dispatcher);
|
||||
$dispatcher->dispatch('onSchemaPrepareSave', $event);
|
||||
|
||||
if (!isset($entry->schemaType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($entry->id)) {
|
||||
$db->updateObject('#__schemaorg', $entry, 'id');
|
||||
} else {
|
||||
$db->insertObject('#__schemaorg', $entry, 'id');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is triggered before the framework creates the Head section of the Document
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function onBeforeCompileHead(): void
|
||||
{
|
||||
$app = $this->getApplication();
|
||||
$baseType = $this->params->get('baseType', 'organization');
|
||||
|
||||
$itemId = (int) $app->getInput()->getInt('id');
|
||||
$option = $app->getInput()->get('option');
|
||||
$view = $app->getInput()->get('view');
|
||||
$context = $option . '.' . $view;
|
||||
|
||||
// We need the plugin configured at least once to add structured data
|
||||
if (!$app->isClient('site') || !\in_array($baseType, ['organization', 'person']) || !$this->isSupported($context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$domain = Uri::root();
|
||||
|
||||
$isPerson = $baseType === 'person';
|
||||
|
||||
$schema = new Registry();
|
||||
|
||||
$baseSchema = [];
|
||||
|
||||
$baseSchema['@context'] = 'https://schema.org';
|
||||
$baseSchema['@graph'] = [];
|
||||
|
||||
// Add base tag Person/Organization
|
||||
$baseId = $domain . '#/schema/' . ucfirst($baseType) . '/base';
|
||||
|
||||
$siteSchema = [];
|
||||
|
||||
$siteSchema['@type'] = ucfirst($baseType);
|
||||
$siteSchema['@id'] = $baseId;
|
||||
|
||||
$name = $this->params->get('name', $app->get('sitename'));
|
||||
|
||||
if ($isPerson && $this->params->get('user') > 0) {
|
||||
$user = $this->getUserFactory()->loadUserById($this->params->get('user'));
|
||||
|
||||
$name = $user ? $user->name : '';
|
||||
}
|
||||
|
||||
if ($name) {
|
||||
$siteSchema['name'] = $name;
|
||||
}
|
||||
|
||||
$siteSchema['url'] = $domain;
|
||||
|
||||
// Image
|
||||
$image = $this->params->get('image') ? HTMLHelper::_('cleanimageUrl', $this->params->get('image')) : false;
|
||||
|
||||
if ($image !== false) {
|
||||
$siteSchema['logo'] = [
|
||||
'@type' => 'ImageObject',
|
||||
'@id' => $domain . '#/schema/ImageObject/logo',
|
||||
'url' => $image->url,
|
||||
'contentUrl' => $image->url,
|
||||
'width' => $image->attributes['width'] ?? 0,
|
||||
'height' => $image->attributes['height'] ?? 0,
|
||||
];
|
||||
|
||||
$siteSchema['image'] = ['@id' => $siteSchema['logo']['@id']];
|
||||
}
|
||||
|
||||
// Social media accounts
|
||||
$socialMedia = (array) $this->params->get('socialmedia', []);
|
||||
|
||||
if (!empty($socialMedia)) {
|
||||
$siteSchema['sameAs'] = [];
|
||||
}
|
||||
|
||||
foreach ($socialMedia as $social) {
|
||||
$siteSchema['sameAs'][] = $social->url;
|
||||
}
|
||||
|
||||
$baseSchema['@graph'][] = $siteSchema;
|
||||
|
||||
// Add WebSite
|
||||
$webSiteId = $domain . '#/schema/WebSite/base';
|
||||
|
||||
$webSiteSchema = [];
|
||||
|
||||
$webSiteSchema['@type'] = 'WebSite';
|
||||
$webSiteSchema['@id'] = $webSiteId;
|
||||
$webSiteSchema['url'] = $domain;
|
||||
$webSiteSchema['name'] = $app->get('sitename');
|
||||
$webSiteSchema['publisher'] = ['@id' => $baseId];
|
||||
|
||||
// We support Finder actions
|
||||
$finder = ModuleHelper::getModule('mod_finder');
|
||||
|
||||
if (!empty($finder->id)) {
|
||||
$webSiteSchema['potentialAction'] = [
|
||||
'@type' => 'SearchAction',
|
||||
'target' => Route::_('index.php?option=com_finder&view=search&q={search_term_string}', true, Route::TLS_IGNORE, true),
|
||||
'query-input' => 'required name=search_term_string',
|
||||
];
|
||||
}
|
||||
|
||||
$baseSchema['@graph'][] = $webSiteSchema;
|
||||
|
||||
// Add WebPage
|
||||
$webPageId = $domain . '#/schema/WebPage/base';
|
||||
|
||||
$webPageSchema = [];
|
||||
|
||||
$webPageSchema['@type'] = 'WebPage';
|
||||
$webPageSchema['@id'] = $webPageId;
|
||||
$webPageSchema['url'] = htmlspecialchars(Uri::getInstance()->toString());
|
||||
$webPageSchema['name'] = $app->getDocument()->getTitle();
|
||||
$webPageSchema['description'] = $app->getDocument()->getDescription();
|
||||
$webPageSchema['isPartOf'] = ['@id' => $webSiteId];
|
||||
$webPageSchema['about'] = ['@id' => $baseId];
|
||||
$webPageSchema['inLanguage'] = $app->getLanguage()->getTag();
|
||||
|
||||
// We support Breadcrumb linking
|
||||
$breadcrumbs = ModuleHelper::getModule('mod_breadcrumbs');
|
||||
|
||||
if (!empty($breadcrumbs->id)) {
|
||||
$webPageSchema['breadcrumb'] = ['@id' => $domain . '#/schema/BreadcrumbList/' . (int) $breadcrumbs->id];
|
||||
}
|
||||
|
||||
$baseSchema['@graph'][] = $webPageSchema;
|
||||
|
||||
if ($itemId > 0) {
|
||||
// Load the table data from the database
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select('*')
|
||||
->from($db->quoteName('#__schemaorg'))
|
||||
->where($db->quoteName('itemId') . ' = :itemId')
|
||||
->bind(':itemId', $itemId, ParameterType::INTEGER)
|
||||
->where($db->quoteName('context') . ' = :context')
|
||||
->bind(':context', $context, ParameterType::STRING);
|
||||
|
||||
$result = $db->setQuery($query)->loadObject();
|
||||
|
||||
if ($result) {
|
||||
$localSchema = new Registry($result->schema);
|
||||
|
||||
$localSchema->set('@id', $domain . '#/schema/' . str_replace('.', '/', $context) . '/' . (int) $result->itemId);
|
||||
$localSchema->set('isPartOf', ['@id' => $webPageId]);
|
||||
|
||||
$itemSchema = $localSchema->toArray();
|
||||
|
||||
$baseSchema['@graph'][] = $itemSchema;
|
||||
}
|
||||
}
|
||||
|
||||
$schema->loadArray($baseSchema);
|
||||
|
||||
$dispatcher = $this->getDispatcher();
|
||||
$event = new BeforeCompileHeadEvent('onSchemaBeforeCompileHead', [
|
||||
'subject' => $schema,
|
||||
'context' => $context . '.' . $itemId,
|
||||
]);
|
||||
|
||||
PluginHelper::importPlugin('schemaorg', null, true, $dispatcher);
|
||||
$dispatcher->dispatch('onSchemaBeforeCompileHead', $event);
|
||||
|
||||
$data = $schema->get('@graph');
|
||||
|
||||
foreach ($data as $key => $entry) {
|
||||
$data[$key] = $this->cleanupSchema($entry);
|
||||
}
|
||||
|
||||
$schema->set('@graph', $data);
|
||||
|
||||
$prettyPrint = JDEBUG ? JSON_PRETTY_PRINT : 0;
|
||||
$schemaString = $schema->toString('JSON', ['bitmask' => JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | $prettyPrint]);
|
||||
|
||||
if ($schemaString !== '{}') {
|
||||
$wa = $this->getApplication()->getDocument()->getWebAssetManager();
|
||||
$wa->addInlineScript($schemaString, ['name' => 'inline.schemaorg'], ['type' => 'application/ld+json']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean the schema and remove empty fields
|
||||
*
|
||||
* @param array $schema
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
private function cleanupSchema($schema)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
foreach ($schema as $key => $value) {
|
||||
if (\is_array($value)) {
|
||||
// Subtypes need special handling
|
||||
if (!empty($value['@type'])) {
|
||||
if ($value['@type'] === 'ImageObject') {
|
||||
if (!empty($value['url'])) {
|
||||
$value['url'] = $this->prepareImage($value['url']);
|
||||
}
|
||||
|
||||
if (empty($value['url'])) {
|
||||
$value = [];
|
||||
}
|
||||
} elseif ($value['@type'] === 'Date') {
|
||||
if (!empty($value['value'])) {
|
||||
$value['value'] = $this->prepareDate($value['value']);
|
||||
}
|
||||
|
||||
if (empty($value['value'])) {
|
||||
$value = [];
|
||||
}
|
||||
}
|
||||
|
||||
// Go into the array
|
||||
$value = $this->cleanupSchema($value);
|
||||
|
||||
// We don't save when the array contains only the @type
|
||||
if (empty($value) || \count($value) <= 1) {
|
||||
$value = null;
|
||||
}
|
||||
} elseif ($key == 'genericField') {
|
||||
foreach ($value as $field) {
|
||||
$result[$field['genericTitle']] = $field['genericValue'];
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// No data, no play
|
||||
if (empty($value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$result[$key] = $value;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current plugin should execute schemaorg related activities
|
||||
*
|
||||
* @param string $context
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected function isSupported($context)
|
||||
{
|
||||
// We need at least the extension + view for loading the table fields
|
||||
if (!str_contains($context, '.')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$parts = explode('.', $context, 2);
|
||||
$component = $this->getApplication()->bootComponent($parts[0]);
|
||||
|
||||
return $component instanceof SchemaorgServiceInterface;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user