fix: QC-Ratings aus 7 älteren Artikeln entfernt (CHECK 10)
This commit is contained in:
@@ -0,0 +1,515 @@
|
||||
<?php
|
||||
/**
|
||||
* @package BSN_Wertungsbox
|
||||
* @copyright (C) 2026 brettspiel-news.de
|
||||
* @license GPL-2.0-or-later
|
||||
*
|
||||
* System-Plugin: Rendert Infobox + Wertungsbox aus Joomla Custom Fields.
|
||||
* Astroid-kompatibel via onAfterRender. Kategorie-gesteuert.
|
||||
*
|
||||
* REVIEW-ARTIKEL-AUFBAU:
|
||||
* [Einleitung]
|
||||
* {bsn_infobox} ← Shortcode, manuell gesetzt
|
||||
* [Haupttext]
|
||||
* ← Wertungsbox erscheint automatisch hier
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Plugin\CMSPlugin;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\Database\DatabaseInterface;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
|
||||
class PlgSystemBsn_Wertungsbox extends CMSPlugin
|
||||
{
|
||||
protected $app;
|
||||
protected $autoloadLanguage = true;
|
||||
|
||||
// Custom Field definitions
|
||||
private const FIELDS = [
|
||||
// Infobox
|
||||
'bsn-spiel-id' => ['label' => 'BGG-Spiel-ID', 'type' => 'text', 'group' => 'infobox'],
|
||||
'bsn-verlag' => ['label' => 'Verlag', 'type' => 'text', 'group' => 'infobox'],
|
||||
'bsn-designer' => ['label' => 'Designer', 'type' => 'text', 'group' => 'infobox'],
|
||||
'bsn-autor' => ['label' => 'Autor', 'type' => 'text', 'group' => 'infobox'],
|
||||
'bsn-illustrator' => ['label' => 'Illustrator', 'type' => 'text', 'group' => 'infobox'],
|
||||
'bsn-spieler' => ['label' => 'Spieleranzahl', 'type' => 'text', 'group' => 'infobox'],
|
||||
'bsn-alter' => ['label' => 'Alter', 'type' => 'text', 'group' => 'infobox'],
|
||||
'bsn-dauer' => ['label' => 'Spieldauer', 'type' => 'text', 'group' => 'infobox'],
|
||||
'bsn-bgg-rating' => ['label' => 'BGG-Rating', 'type' => 'text', 'group' => 'infobox'],
|
||||
'bsn-bgg-weight' => ['label' => 'BGG-Schwierigkeit', 'type' => 'text', 'group' => 'infobox'],
|
||||
// Wertungsbox
|
||||
'bsn-wertung-titel' => ['label' => 'Wertung – Titel', 'type' => 'text', 'group' => 'wertung'],
|
||||
'bsn-wertung-untertitel' => ['label' => 'Wertung – Untertitel', 'type' => 'text', 'group' => 'wertung'],
|
||||
'bsn-wertung-komplex' => ['label' => 'Wertung – Komplexität', 'type' => 'text', 'group' => 'wertung'],
|
||||
'bsn-wertung-sprache' => ['label' => 'Wertung – Sprache', 'type' => 'text', 'group' => 'wertung'],
|
||||
'bsn-wertung-mechanik' => ['label' => 'Wertung – Mechanismen', 'type' => 'textarea', 'group' => 'wertung'],
|
||||
'bsn-wertung-pro' => ['label' => 'Wertung – Pro', 'type' => 'textarea', 'group' => 'wertung'],
|
||||
'bsn-wertung-kontra' => ['label' => 'Wertung – Kontra', 'type' => 'textarea', 'group' => 'wertung'],
|
||||
'bsn-wertung-autor' => ['label' => 'Wertung – Rezensent', 'type' => 'text', 'group' => 'wertung'],
|
||||
'bsn-wertung-punkte' => ['label' => 'Wertung – Punkte', 'type' => 'integer', 'group' => 'wertung'],
|
||||
];
|
||||
|
||||
/**
|
||||
* onAfterRender — the Astroid-safe injection point
|
||||
*/
|
||||
public function onAfterRender(): void
|
||||
{
|
||||
try {
|
||||
// Safety: only frontend, only HTML
|
||||
if ($this->app->isClient('administrator')) return;
|
||||
|
||||
$body = $this->app->getBody();
|
||||
$contentType = $this->app->getDocument()->getType();
|
||||
if ($contentType !== 'html') return;
|
||||
|
||||
// Only process if we're on an article page (heuristic: com_content article container)
|
||||
$hasArticle = preg_match('/com-content-article.*itemscope/', $body);
|
||||
if (!$hasArticle) return;
|
||||
|
||||
// 1) Replace {bsn_infobox} shortcodes
|
||||
$body = $this->processInfoboxShortcodes($body);
|
||||
|
||||
// 2) Inject wertungsbox if category matches
|
||||
$body = $this->processWertungsbox($body);
|
||||
|
||||
$this->app->setBody($body);
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
// Silent fail — never break the site
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find and replace {bsn_infobox} shortcodes with styled HTML
|
||||
*/
|
||||
private function processInfoboxShortcodes(string $body): string
|
||||
{
|
||||
if (!preg_match_all('/\{bsn_infobox\}/', $body, $matches, PREG_OFFSET_CAPTURE)) {
|
||||
return $body;
|
||||
}
|
||||
|
||||
// Find article IDs for each shortcode occurrence
|
||||
$replacements = [];
|
||||
foreach ($matches[0] as $match) {
|
||||
$pos = $match[1];
|
||||
// Find the enclosing article container
|
||||
$articleId = $this->findArticleId($body, $pos);
|
||||
if (!$articleId) continue;
|
||||
|
||||
$fields = $this->getFieldValues($articleId);
|
||||
if (!$fields) continue;
|
||||
|
||||
$box = $this->buildInfobox($fields);
|
||||
if ($box) {
|
||||
$replacements[] = ['pos' => $pos, 'len' => 14, 'html' => $box];
|
||||
}
|
||||
}
|
||||
|
||||
// Apply in reverse order
|
||||
foreach (array_reverse($replacements) as $r) {
|
||||
$body = substr_replace($body, $r['html'], $r['pos'], $r['len']);
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto-inject wertungsbox at end of article content
|
||||
*/
|
||||
private function processWertungsbox(string $body): string
|
||||
{
|
||||
// Find article containers
|
||||
if (!preg_match_all(
|
||||
'/<div\s+class="[^"]*com-content-article[^"]*"[^>]*>/',
|
||||
$body, $matches, PREG_OFFSET_CAPTURE
|
||||
)) {
|
||||
return $body;
|
||||
}
|
||||
|
||||
// Get authorized categories from plugin params
|
||||
$allowedCategories = $this->params->get('categories_wertung', []);
|
||||
if (empty($allowedCategories) || (is_array($allowedCategories) && count($allowedCategories) === 1 && empty($allowedCategories[0]))) {
|
||||
return $body; // No categories selected → don't inject
|
||||
}
|
||||
|
||||
$injections = [];
|
||||
foreach ($matches[0] as $match) {
|
||||
$containerStart = $match[1];
|
||||
$articleId = $this->findArticleId($body, $containerStart);
|
||||
if (!$articleId) continue;
|
||||
|
||||
// Check category
|
||||
$catId = $this->getArticleCategory($articleId);
|
||||
if (!$catId || !in_array((string)$catId, (array)$allowedCategories)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$fields = $this->getFieldValues($articleId);
|
||||
if (!$fields) continue;
|
||||
|
||||
$box = $this->buildWertungsbox($fields);
|
||||
if (!$box) continue;
|
||||
|
||||
// Find </article> or </div> that closes the article content
|
||||
// Inject just before the closing of the article container
|
||||
$closePos = $this->findArticleContentEnd($body, $containerStart);
|
||||
if ($closePos) {
|
||||
$injections[] = ['pos' => $closePos, 'html' => $box];
|
||||
}
|
||||
}
|
||||
|
||||
foreach (array_reverse($injections) as $inj) {
|
||||
$body = substr_replace($body, $inj['html'], $inj['pos'], 0);
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find article ID from HTML context near a position
|
||||
*/
|
||||
private function findArticleId(string $body, int $nearPos): ?int
|
||||
{
|
||||
$chunk = substr($body, max(0, $nearPos - 500), 3000);
|
||||
|
||||
$patterns = [
|
||||
'/data-id="(\d+)"/',
|
||||
'/itemprop="identifier"[^>]*content="(\d+)"/',
|
||||
'/<meta\s+itemprop="identifier"\s+content="(\d+)"/',
|
||||
];
|
||||
|
||||
foreach ($patterns as $p) {
|
||||
if (preg_match($p, $chunk, $m)) {
|
||||
return (int)$m[1];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the closing position of article content (before the kasten/quellen div)
|
||||
*/
|
||||
private function findArticleContentEnd(string $body, int $containerStart): ?int
|
||||
{
|
||||
// Look for </article> tag, or the </div> before "Quellen" kasten
|
||||
$searchArea = substr($body, $containerStart, 20000);
|
||||
|
||||
// Try </article> first
|
||||
$articleEnd = strpos($searchArea, '</article>');
|
||||
if ($articleEnd !== false) {
|
||||
return $containerStart + $articleEnd;
|
||||
}
|
||||
|
||||
// Try the last </div> before "Quellen" heading
|
||||
if (preg_match('/<h2[^>]*>\s*Quellen\s*<\/h2>/', $searchArea, $m, PREG_OFFSET_CAPTURE)) {
|
||||
$quellenPos = $m[0][1];
|
||||
// Find the closing </div> just before Quellen
|
||||
$before = substr($searchArea, 0, $quellenPos);
|
||||
$lastDiv = strrpos($before, '</div>');
|
||||
if ($lastDiv !== false) {
|
||||
return $containerStart + $lastDiv;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get article's category ID
|
||||
*/
|
||||
private function getArticleCategory(int $articleId): ?int
|
||||
{
|
||||
try {
|
||||
$db = Factory::getContainer()->get(DatabaseInterface::class);
|
||||
$query = $db->getQuery(true)
|
||||
->select('catid')
|
||||
->from('#__content')
|
||||
->where('id = ' . (int)$articleId)
|
||||
->setLimit(1);
|
||||
$db->setQuery($query);
|
||||
return (int)$db->loadResult() ?: null;
|
||||
} catch (\Throwable $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read custom field values for an article
|
||||
*/
|
||||
private function getFieldValues(int $articleId): ?array
|
||||
{
|
||||
try {
|
||||
$db = Factory::getContainer()->get(DatabaseInterface::class);
|
||||
|
||||
$names = array_keys(self::FIELDS);
|
||||
$quotedNames = array_map(function($n) use ($db) {
|
||||
return $db->quote($n);
|
||||
}, $names);
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select(['f.name', 'v.value'])
|
||||
->from($db->quoteName('#__fields', 'f'))
|
||||
->join('LEFT', $db->quoteName('#__fields_values', 'v'),
|
||||
'f.id = v.field_id AND v.item_id = ' . (int)$articleId)
|
||||
->where('f.context = ' . $db->quote('com_content.article'))
|
||||
->where('f.name IN (' . implode(',', $quotedNames) . ')')
|
||||
->where('f.state = 1');
|
||||
|
||||
$db->setQuery($query);
|
||||
$rows = $db->loadAssocList('name');
|
||||
|
||||
if (empty($rows)) return null;
|
||||
|
||||
$fields = [];
|
||||
$hasAny = false;
|
||||
foreach (self::FIELDS as $name => $def) {
|
||||
$val = isset($rows[$name]) && $rows[$name]['value'] !== null
|
||||
? trim($rows[$name]['value']) : '';
|
||||
$fields[$name] = $val;
|
||||
if ($val !== '') $hasAny = true;
|
||||
}
|
||||
|
||||
return $hasAny ? $fields : null;
|
||||
} catch (\Throwable $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the infobox HTML
|
||||
*/
|
||||
private function buildInfobox(array $f): string
|
||||
{
|
||||
$needle = ['bsn-verlag','bsn-designer','bsn-autor','bsn-illustrator','bsn-spieler','bsn-alter','bsn-dauer'];
|
||||
$hasAny = false;
|
||||
foreach ($needle as $n) {
|
||||
if (!empty($f[$n])) { $hasAny = true; break; }
|
||||
}
|
||||
if (!$hasAny) return '';
|
||||
|
||||
$items = [];
|
||||
$labels = [
|
||||
'bsn-verlag' => 'Verlag',
|
||||
'bsn-designer' => 'Designer',
|
||||
'bsn-autor' => 'Autor',
|
||||
'bsn-illustrator' => 'Illustrator',
|
||||
'bsn-spieler' => 'Spieler',
|
||||
'bsn-alter' => 'Alter',
|
||||
'bsn-dauer' => 'Dauer',
|
||||
'bsn-bgg-rating' => 'BGG-Rating',
|
||||
'bsn-bgg-weight' => 'Schwierigkeit',
|
||||
];
|
||||
|
||||
foreach ($labels as $key => $label) {
|
||||
if (!empty($f[$key])) {
|
||||
$items[] = '<strong>' . htmlspecialchars($label) . ':</strong> '
|
||||
. htmlspecialchars($f[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$rows = '';
|
||||
foreach ($items as $item) {
|
||||
$rows .= '<div>' . $item . '</div>';
|
||||
}
|
||||
|
||||
return <<<HTML
|
||||
<div class="bsn-infobox" style="background:#f5f0eb;border:1px solid #d4c5b2;border-radius:8px;padding:1rem 1.3rem;margin:1.5rem 0;font-size:0.9rem;line-height:1.8;">
|
||||
{$rows}
|
||||
</div>
|
||||
HTML;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the wertungsbox HTML
|
||||
*/
|
||||
private function buildWertungsbox(array $f): string
|
||||
{
|
||||
if (empty($f['bsn-wertung-titel'])) return '';
|
||||
|
||||
$titel = htmlspecialchars($f['bsn-wertung-titel']);
|
||||
$subtitel = htmlspecialchars($f['bsn-wertung-untertitel']);
|
||||
$komplex = htmlspecialchars($f['bsn-wertung-komplex']);
|
||||
$sprache = htmlspecialchars($f['bsn-wertung-sprache']);
|
||||
$mechanik = $this->parseLines($f['bsn-wertung-mechanik']);
|
||||
$pro = $this->parseLines($f['bsn-wertung-pro']);
|
||||
$kontra = $this->parseLines($f['bsn-wertung-kontra']);
|
||||
$rezensent = htmlspecialchars($f['bsn-wertung-autor']);
|
||||
$punkte = (int)$f['bsn-wertung-punkte'];
|
||||
|
||||
$meta = '';
|
||||
if ($komplex) $meta .= 'Komplexität: <strong>' . $komplex . '</strong>';
|
||||
if ($sprache) {
|
||||
if ($meta) $meta .= '<br>';
|
||||
$meta .= 'Sprachen: <strong>' . $sprache . '</strong>';
|
||||
}
|
||||
|
||||
return <<<HTML
|
||||
<style>
|
||||
.bsn-wertungsbox{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;max-width:720px;margin:1.5rem 0;line-height:1.4}
|
||||
.bsn-wertungsbox *{box-sizing:border-box}
|
||||
.bsn-wb-header{background:#1a1e6b;color:#fff;padding:1.2rem 1.5rem;display:flex;justify-content:space-between;align-items:center;gap:1rem;flex-wrap:wrap}
|
||||
.bsn-wb-header .bsn-wb-titel-block{flex:1;min-width:200px}
|
||||
.bsn-wb-header .bsn-wb-titel-block .bsn-wb-titel{margin:0;font-size:1.4rem;font-weight:700}
|
||||
.bsn-wb-header .bsn-wb-titel-block .bsn-wb-untertitel{font-size:.9rem;opacity:.8;margin-top:2px}
|
||||
.bsn-wb-header .bsn-wb-meta{text-align:right;font-size:.85rem;line-height:1.6;min-width:150px}
|
||||
.bsn-wb-header .bsn-wb-logo{font-weight:700;font-size:.9rem;letter-spacing:.05em;text-align:right;line-height:1.3}
|
||||
.bsn-wb-content{background:#fff;display:flex;border:1px solid #ddd;border-top:none;flex-wrap:wrap}
|
||||
.bsn-wb-col{flex:1;min-width:200px;padding:1rem 1.2rem 1.2rem}
|
||||
.bsn-wb-col h4{margin:0 0 .6rem;font-size:.8rem;letter-spacing:.08em;color:#1a1e6b;text-align:center;text-transform:uppercase}
|
||||
.bsn-wb-col ul{list-style:none;padding:0;margin:0}
|
||||
.bsn-wb-col li{padding:.5rem 0;border-bottom:1px dotted #ccc;font-size:.85rem}
|
||||
.bsn-wb-col li:last-child{border-bottom:none}
|
||||
.bsn-wb-footer{background:#1a1e6b;color:#fff;padding:.9rem 1.5rem;display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:1rem}
|
||||
.bsn-wb-footer .bsn-wb-rezensent{font-size:.85rem}
|
||||
.bsn-wb-footer .bsn-wb-rezensent .bsn-wb-name{font-size:1.1rem;font-style:italic}
|
||||
.bsn-wb-footer .bsn-wb-score{text-align:right}
|
||||
.bsn-wb-footer .bsn-wb-score .bsn-wb-score-label{font-size:.75rem;opacity:.8;text-transform:uppercase}
|
||||
.bsn-wb-footer .bsn-wb-score .bsn-wb-score-zahl{font-size:2rem;font-weight:700}
|
||||
@media(max-width:600px){.bsn-wb-col{min-width:100%}.bsn-wb-header{flex-direction:column;text-align:center}.bsn-wb-header .bsn-wb-meta{text-align:center}.bsn-wb-header .bsn-wb-logo{text-align:center}}
|
||||
</style>
|
||||
<div class="bsn-wertungsbox">
|
||||
<div class="bsn-wb-header">
|
||||
<div class="bsn-wb-titel-block">
|
||||
<div class="bsn-wb-titel">{$titel}</div>
|
||||
<div class="bsn-wb-untertitel">{$subtitel}</div>
|
||||
</div>
|
||||
<div class="bsn-wb-meta">{$meta}</div>
|
||||
<div class="bsn-wb-logo">BRETT<br>SPIEL<br>NEWS</div>
|
||||
</div>
|
||||
<div class="bsn-wb-content">
|
||||
{$this->renderWbCol('MECHANISMEN', $mechanik)}
|
||||
{$this->renderWbCol('PRO', $pro)}
|
||||
{$this->renderWbCol('KONTRA', $kontra)}
|
||||
</div>
|
||||
<div class="bsn-wb-footer">
|
||||
<div class="bsn-wb-rezensent">
|
||||
Bewertung von:<br>
|
||||
<span class="bsn-wb-name">{$rezensent}</span>
|
||||
</div>
|
||||
<div class="bsn-wb-score">
|
||||
<div class="bsn-wb-score-label">MEINE WERTUNG</div>
|
||||
<div class="bsn-wb-score-zahl">{$punkte} / 100</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
}
|
||||
|
||||
private function renderWbCol(string $title, array $items): string
|
||||
{
|
||||
$h = htmlspecialchars($title);
|
||||
$lis = '';
|
||||
foreach ($items as $item) {
|
||||
$lis .= '<li>' . htmlspecialchars($item) . '</li>';
|
||||
}
|
||||
return <<<HTML
|
||||
<div class="bsn-wb-col">
|
||||
<h4>{$h}</h4>
|
||||
<ul>{$lis}</ul>
|
||||
</div>
|
||||
HTML;
|
||||
}
|
||||
|
||||
private function parseLines(string $text): array
|
||||
{
|
||||
$text = trim($text);
|
||||
if ($text === '') return [];
|
||||
$lines = preg_split('/\r?\n/', $text);
|
||||
return array_values(array_filter(array_map('trim', $lines), fn($l) => $l !== ''));
|
||||
}
|
||||
|
||||
// ─── INSTALL / UNINSTALL ───────────────────────────────
|
||||
|
||||
public function installFields(): bool
|
||||
{
|
||||
try {
|
||||
$db = Factory::getContainer()->get(DatabaseInterface::class);
|
||||
|
||||
// Find or create field group
|
||||
$query = $db->getQuery(true)
|
||||
->select('id')->from('#__fields_groups')
|
||||
->where('context = ' . $db->quote('com_content.article'))
|
||||
->where('title = ' . $db->quote('BSN Wertungsbox'))
|
||||
->setLimit(1);
|
||||
$db->setQuery($query);
|
||||
$groupId = (int)$db->loadResult();
|
||||
|
||||
if (!$groupId) {
|
||||
$db->insertObject('#__fields_groups', (object)[
|
||||
'id' => 0, 'asset_id' => 0,
|
||||
'context' => 'com_content.article',
|
||||
'title' => 'BSN Wertungsbox',
|
||||
'state' => 1, 'access' => 1,
|
||||
'language' => '*', 'params' => '{}',
|
||||
'created' => date('Y-m-d H:i:s'), 'created_by' => 0,
|
||||
], 'id');
|
||||
$groupId = (int)$db->insertid();
|
||||
}
|
||||
|
||||
$order = 1;
|
||||
foreach (self::FIELDS as $name => $def) {
|
||||
$query = $db->getQuery(true)
|
||||
->select('id')->from('#__fields')
|
||||
->where('name = ' . $db->quote($name))
|
||||
->where('context = ' . $db->quote('com_content.article'));
|
||||
$db->setQuery($query);
|
||||
if ($db->loadResult()) { $order++; continue; }
|
||||
|
||||
$params = match($def['type']) {
|
||||
'integer' => '{"class":"","default":"","first":"0","last":"100","step":"1","showlabel":"1"}',
|
||||
'textarea' => '{"class":"","rows":"4","cols":"20","filter":"raw","showlabel":"1"}',
|
||||
default => '{"class":"","showlabel":"1"}',
|
||||
};
|
||||
|
||||
$db->insertObject('#__fields', (object)[
|
||||
'id' => 0, 'asset_id' => 0,
|
||||
'context' => 'com_content.article',
|
||||
'group_id' => $groupId,
|
||||
'title' => $def['label'], 'name' => $name,
|
||||
'label' => $def['label'], 'type' => $def['type'],
|
||||
'state' => 1, 'required' => 0,
|
||||
'default_value' => '', 'params' => $params,
|
||||
'fieldparams' => '{}', 'access' => 1,
|
||||
'language' => '*', 'ordering' => $order++,
|
||||
'created' => date('Y-m-d H:i:s'), 'created_by' => 0,
|
||||
]);
|
||||
}
|
||||
return true;
|
||||
} catch (\Throwable $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function uninstallFields(): bool
|
||||
{
|
||||
try {
|
||||
$db = Factory::getContainer()->get(DatabaseInterface::class);
|
||||
$names = array_keys(self::FIELDS);
|
||||
$quoted = array_map(fn($n) => $db->quote($n), $names);
|
||||
|
||||
// Delete values first
|
||||
$query = $db->getQuery(true)
|
||||
->delete('#__fields_values')
|
||||
->where('field_id IN (SELECT id FROM ' . $db->quoteName('#__fields')
|
||||
. ' WHERE context = ' . $db->quote('com_content.article')
|
||||
. ' AND name IN (' . implode(',', $quoted) . '))');
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
|
||||
// Delete fields
|
||||
$query = $db->getQuery(true)
|
||||
->delete('#__fields')
|
||||
->where('context = ' . $db->quote('com_content.article'))
|
||||
->where('name IN (' . implode(',', $quoted) . ')');
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
|
||||
return true;
|
||||
} catch (\Throwable $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user