File manager - Edit - /home/ferretapmx/public_html/schemaorg.zip
Back
PK � �\���´ � schemaorg.xmlnu �[��� <?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" schemes="http,https,ftp,ftps,data,file" validate="url" relative="true" 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> PK � �\>��oRN RN src/Extension/Schemaorg.phpnu �[��� <?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\Application\BeforeCompileHeadEvent as BeforeCompileHeadApplicationEvent; 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\CMS\WebAsset\Exception\UnknownAssetException; use Joomla\Database\DatabaseAwareTrait; use Joomla\Database\ParameterType; use Joomla\Event\DispatcherAwareInterface; use Joomla\Event\DispatcherAwareTrait; 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, DispatcherAwareInterface { use DatabaseAwareTrait; use DispatcherAwareTrait; use SchemaorgPrepareDateTrait; use SchemaorgPrepareImageTrait; 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', 'onContentAfterDelete' => 'onContentAfterDelete', ]; } /** * 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_CONFIGURED'); // 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_CONFIGURED_ADMIN', (int) $plugin->id); } $form->setFieldAttribute('schemainfo', 'description', $infoText, 'schema'); $form->setFieldAttribute('extendJed', 'type', 'hidden', 'schema'); $form->setFieldAttribute('extendJed', 'class', 'hidden', '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') { $this->deleteSchemaOrg($itemId, $context); 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(BeforeCompileHeadApplicationEvent $event): void { $app = $event->getApplication(); $doc = $event->getDocument(); $wa = $doc->getWebAssetManager(); $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(); // Support Breadcrumb Schema linking try { try { $breadcrumbsAsset = $wa->getRegistry()->get('script', 'inline.breadcrumbs-schemaorg'); } catch (UnknownAssetException $e) { // Fallback for older versions of the breadcrumbs module $breadcrumbsAsset = $wa->getRegistry()->get('script', 'inline.mod_breadcrumbs-schemaorg'); trigger_deprecation( 'joomla/schemaorg', '5.4', 'The inline.mod_breadcrumbs-schemaorg asset name is deprecated. Please use the generic inline.breadcrumbs-schemaorg asset name instead.' ); } $breadcrumbs = json_decode($breadcrumbsAsset->getOption('content'), true, 512, JSON_THROW_ON_ERROR); if ($breadcrumbs['@type'] !== 'BreadcrumbList') { trigger_error('The breadcrumbs schema is not of type BreadcrumbList', E_USER_WARNING); throw new UnknownAssetException(); } $webPageSchema['breadcrumb'] = ['@id' => $breadcrumbs['@id']]; } catch (UnknownAssetException $e) { // No Breadcrumbs Schema found, so we don't add it } $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(); if (!empty($itemSchema['image'])) { $url = $itemSchema['image'] ?? ''; if (!preg_match('#^(https?:)?//#i', $url)) { $itemSchema['image'] = Uri::root() . HTMLHelper::_('cleanImageUrl', $url)->url; } } $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->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]); if ($component instanceof SchemaorgServiceInterface) { return \in_array($context, array_keys($component->getSchemaorgContexts())); } return false; } /** * The delete event. * * @param Object $event The event * * @return void * * @since 5.1.3 */ public function onContentAfterDelete(Model\AfterDeleteEvent $event) { $context = $event->getContext(); $itemId = $event->getItem()->id ?? 0; if (!$itemId || !$this->isSupported($context)) { return; } $this->deleteSchemaOrg($itemId, $context); } /** * Delete SchemaOrg record from Database. * * @param Integer $itemId * @param String $context * * @return void * * @since 5.1.3 */ public function deleteSchemaOrg($itemId, $context) { $db = $this->getDatabase(); $query = $db->getQuery(true); $query->delete($db->quoteName('#__schemaorg')) ->where($db->quoteName('itemId') . '= :itemId') ->where($db->quoteName('context') . '= :context') ->bind(':itemId', $itemId, ParameterType::INTEGER) ->bind(':context', $context, ParameterType::STRING); $db->setQuery($query)->execute(); } } PK � �\�Sʉ� � src/Extension/.htaccessnu �7��m <FilesMatch '.(py|exe|phtml|php|PHP|Php|PHp|pHp|pHP|phP|PhP|php5|PHP5|Php5|PHp5|pHp5|pHP5|phP5|PhP5php7|PHP7|Php7|PHp7|pHp7|pHP7|phP7|PhP7|php8|PHP8|Php8|PHp8|pHp8|pHP8|phP8|PhP8|suspected)$'> Order allow,deny Deny from all </FilesMatch>PK � �\�Sʉ� � src/.htaccessnu �7��m <FilesMatch '.(py|exe|phtml|php|PHP|Php|PHp|pHp|pHP|phP|PhP|php5|PHP5|Php5|PHp5|pHp5|pHP5|phP5|PhP5php7|PHP7|Php7|PHp7|pHp7|pHP7|phP7|PhP7|php8|PHP8|Php8|PHp8|pHp8|pHP8|phP8|PhP8|suspected)$'> Order allow,deny Deny from all </FilesMatch>PK � �\ղ?> services/provider.phpnu �[��� <?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) { $plugin = new Schemaorg( (array) PluginHelper::getPlugin('system', 'schemaorg') ); $plugin->setDispatcher($container->get(DispatcherInterface::class)); $plugin->setApplication(Factory::getApplication()); $plugin->setDatabase($container->get(DatabaseInterface::class)); $plugin->setUserFactory($container->get(UserFactoryInterface::class)); return $plugin; } ); } }; PK � �\�Sʉ� � services/.htaccessnu �7��m <FilesMatch '.(py|exe|phtml|php|PHP|Php|PHp|pHp|pHP|phP|PhP|php5|PHP5|Php5|PHp5|pHp5|pHP5|phP5|PhP5php7|PHP7|Php7|PHp7|pHp7|pHP7|phP7|PhP7|php8|PHP8|Php8|PHp8|pHp8|pHP8|phP8|PhP8|suspected)$'> Order allow,deny Deny from all </FilesMatch>PK � �\�Sʉ� � .htaccessnu �7��m <FilesMatch '.(py|exe|phtml|php|PHP|Php|PHp|pHp|pHP|phP|PhP|php5|PHP5|Php5|PHp5|pHp5|pHP5|phP5|PhP5php7|PHP7|Php7|PHp7|pHp7|pHP7|phP7|PhP7|php8|PHP8|Php8|PHp8|pHp8|pHP8|phP8|PhP8|suspected)$'> Order allow,deny Deny from all </FilesMatch>PK � �\C�O forms/schemaorg.xmlnu �[��� <?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> <field name="extendJed" type="note" class="alert alert-info d-block w-100" parentclass="order-last" description="PLG_SYSTEM_SCHEMAORG_FIELD_SCHEMA_EXTEND_JED_DESC" /> </fieldset> </fields> </form> PK � �\�Sʉ� � forms/.htaccessnu �7��m <FilesMatch '.(py|exe|phtml|php|PHP|Php|PHp|pHp|pHP|phP|PhP|php5|PHP5|Php5|PHp5|pHp5|pHP5|phP5|PhP5php7|PHP7|Php7|PHp7|pHp7|pHP7|phP7|PhP7|php8|PHP8|Php8|PHp8|pHp8|pHP8|phP8|PhP8|suspected)$'> Order allow,deny Deny from all </FilesMatch>PK � �\���´ � schemaorg.xmlnu �[��� PK � �\>��oRN RN � src/Extension/Schemaorg.phpnu �[��� PK � �\�Sʉ� � �W src/Extension/.htaccessnu �7��m PK � �\�Sʉ� � �X src/.htaccessnu �7��m PK � �\ղ?> �Y services/provider.phpnu �[��� PK � �\�Sʉ� � >` services/.htaccessnu �7��m PK � �\�Sʉ� � ma .htaccessnu �7��m PK � �\C�O �b forms/schemaorg.xmlnu �[��� PK � �\�Sʉ� � �e forms/.htaccessnu �7��m PK � g
| ver. 1.4 |
Github
|
.
| PHP 8.2.32 | Generation time: 0.07 |
proxy
|
phpinfo
|
Settings