Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
ef18543
feat : add ogtest field plugin
shahzan01 Aug 11, 2025
3f24db8
Merge branch 'feature/seo-improvements' into opengraph/custom-field
shahzan01 Aug 11, 2025
e9cc55b
fix : fixed the imports in OpengraphField.php
shahzan01 Aug 11, 2025
3193217
feat : made the OpenGraph field more flexible , removed hardcoded com…
shahzan01 Aug 15, 2025
a8be0cd
fix : changed component name to use dynamic value
shahzan01 Aug 15, 2025
3af8e0f
feat : added support for multi article page view
shahzan01 Aug 26, 2025
96038a3
fix : removed extra line from git ignore file
shahzan01 Sep 1, 2025
ece0934
feat : add ogtest field plugin
shahzan01 Aug 11, 2025
f308e0e
fix : fixed the imports in OpengraphField.php
shahzan01 Aug 11, 2025
310ba1f
feat : made the OpenGraph field more flexible , removed hardcoded com…
shahzan01 Aug 15, 2025
e0ac562
fix : changed component name to use dynamic value
shahzan01 Aug 15, 2025
d7b2a27
feat : added support for multi article page view
shahzan01 Aug 26, 2025
0519912
fix : removed extra line from git ignore file
shahzan01 Sep 1, 2025
9eba47f
Merge branch 'opengraph/custom-field' of https://github.com/joomla-pr…
shahzan01 Sep 1, 2025
6c4de79
fix : add missing fieldhelper import
shahzan01 Sep 1, 2025
1301bb9
fix : removed duplicate enum error
shahzan01 Sep 1, 2025
d5395e4
Merge remote-tracking branch 'Academy2025_SEO/6.1-dev' into academy/2…
bembelimen Sep 12, 2025
d9e6d49
fix : removed the PHPstan and PHPcs errors
shahzan01 Sep 15, 2025
d9ea675
Merge branch 'opengraph/custom-field' of https://github.com/joomla-pr…
shahzan01 Sep 15, 2025
931c540
Merge branch 'feature/seo-improvements' into opengraph/custom-field
shahzan01 Sep 15, 2025
236b1bb
fix : phpcs fix
shahzan01 Sep 15, 2025
0289875
fix : removed extra else statement
shahzan01 Sep 15, 2025
ae490ff
fix the imports
shahzan01 Sep 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions libraries/src/Opengraph/MappableFieldInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/**
* Joomla! Content Management System
*
* @copyright (C) 2025 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/

namespace Joomla\CMS\Opengraph;

// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects


/**
* Interface for fields that can be mapped to OpenGraph groups.
*
* @since __DEPLOY_VERSION__
*/
interface MappableFieldInterface
{
/**
* Returns the OpenGraph group this field should be listed under.
*
* @return OpengraphGroup One of the enum cases defined in {@see OpengraphGroup}.
*
* @since __DEPLOY_VERSION__
*/
public static function getOpengraphGroup(): OpengraphGroup;
}
36 changes: 36 additions & 0 deletions libraries/src/Opengraph/OpengraphGroup.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

/**
* Joomla! Content Management System
*
* @copyright (C) 2025 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/

namespace Joomla\CMS\Opengraph;

// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects

/**
* Enumerates the logical OpenGraph groups that a custom field-type can
* register itself under.
*
* Third-party field-type plugins should return one of these cases from
* {@see MappableFieldInterface::getOpengraphGroup()} so the System – OpenGraph
* plugin knows how to categorise the field inside its mapping drop-down.
*
* @since __DEPLOY_VERSION__
*/
enum OpengraphGroup: string
{
/** Standard textual content (e.g. single-line, multi-line). */
case TEXT = 'text-fields';

/** Image or media file (intro/full images, custom media fields, …). */
case IMAGE = 'image-fields';

/** Alternate-text associated with an image (accessibility / SEO). */
case IMAGE_ALT = 'image-alt-fields';
}
20 changes: 20 additions & 0 deletions plugins/system/opengraph/src/Extension/opengraph.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
use Joomla\CMS\Uri\Uri;
use Joomla\Component\Categories\Administrator\Model\CategoryModel;
use Joomla\Component\Content\Administrator\Model\ArticleModel;
use Joomla\Component\Fields\Administrator\Helper\FieldsHelper;
use Joomla\Event\SubscriberInterface;
use Joomla\Registry\Registry;

Expand Down Expand Up @@ -425,8 +426,10 @@ private function getMultipleArticleMenuParams(string $option, string $view, ?int
return $active->getParams();
}
} elseif ($view === 'featured') {
// For featured view (no category ID)
return $active->getParams();
} else {
// For other multi-article views, just return menu params
return $active->getParams();
}
}
Expand Down Expand Up @@ -511,6 +514,23 @@ private function getOgTagsFromCategoryMappings(Registry $categoryParams, object
*/
private function getFieldValue(object $article, string $fieldName, array $articleImages): string
{

// Check if it's a custom field
if (strpos($fieldName, 'field.') === 0) {
$customFieldName = substr($fieldName, 6);
// Load custom fields for the article
$customFields = FieldsHelper::getFields('com_content.article', $article, true);

foreach ($customFields as $field) {
if ($field->name == $customFieldName) {
return $field->value ?? '';
}
}

return '';
}

// Handle standard article fields
$value = '';

switch ($fieldName) {
Expand Down
80 changes: 80 additions & 0 deletions plugins/system/opengraph/src/Field/OpengraphField.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,15 @@
namespace Joomla\Plugin\System\Opengraph\Field;

use Joomla\CMS\Factory;
use Joomla\CMS\Fields\FieldsServiceInterface;
use Joomla\CMS\Form\Field\GroupedlistField;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Opengraph\MappableFieldInterface;
use Joomla\CMS\Opengraph\OpengraphGroup;
use Joomla\CMS\Opengraph\OpengraphServiceInterface;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\Component\Fields\Administrator\Helper\FieldsHelper;

// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
Expand Down Expand Up @@ -97,6 +102,81 @@ protected function getGroups()
}



if (!$cmp instanceof FieldsServiceInterface) {
return $groups;
}

// Allowed field types for each OpenGraph group
$allowedFieldTypes = [
OpengraphGroup::TEXT->value => ['text', 'textarea'],
OpengraphGroup::IMAGE->value => ['media', 'imagelist'],
OpengraphGroup::IMAGE_ALT->value => ['text'],
];

$nativeTypes = $allowedFieldTypes[$fieldType] ?? [];



$catId = (int) $this->form->getValue('id'); // editing existing cat
if (!$catId) {
// Creating a new category: use the chosen parent so assignments still work
$catId = (int) $this->form->getValue('parent_id');
}

// Dummy item with catid so FieldsService filters by assignment
$scopeItem = $catId ? (object) ['catid' => $catId] : null;

$customFields = FieldsHelper::getFields('com_content.article', $scopeItem);
$customOptions = [];

foreach ($customFields as $field) {
$accept = \in_array($field->type, $nativeTypes, true);


// If not native-allowed, see if the field’s plugin implements our interface
if (!$accept) {
// Ensure the specific fields plugin is loaded
PluginHelper::importPlugin('fields', $field->type);

$ucType = ucfirst((string) $field->type);

// Candidate class names in priority order (modern first, then legacy)
$candidates = [
"Joomla\\Plugin\\Fields\\{$ucType}\\Extension\\{$ucType}", // J4/5 namespaced
"Joomla\\Plugin\\Fields\\{$ucType}\\Field\\{$ucType}Field", // some third-party patterns
"PlgFields{$ucType}", // legacy non-namespaced
];

$implements = false;

foreach ($candidates as $fqcn) {
if (class_exists($fqcn) && is_subclass_of($fqcn, MappableFieldInterface::class)) {
$implements = ($fqcn::getOpengraphGroup()->value === $fieldType);
if ($implements) {
$accept = true;
break;
}
}
}
}


if (!$accept) {
continue;
}



$label = $field->title . ' (' . $field->name . ')';
$customOptions[] = HTMLHelper::_('select.option', 'field.' . $field->name, $label);
}

if (!empty($customOptions)) {
$groups['Custom Fields'] = $customOptions;
}


return $groups;
}
}
Loading