Release of v5.1.1-beta6

Fix bug in the filter of Languages by linked entities. #1230.
This commit is contained in:
2025-07-01 15:21:42 +00:00
parent cf681b2b16
commit 1702bd1f0c
37 changed files with 870 additions and 818 deletions

View File

@ -1,6 +1,6 @@
# v5.1.1-beta5 # v5.1.1-beta6
- Completely refactors the SQL tweaks and SQL dump classes. - Fix bug in the filter of Languages by linked entities. #1230
# v5.1.1-beta # v5.1.1-beta
@ -25,7 +25,8 @@
- Adds advanced version update notice to the Component Builder Dashboard. - Adds advanced version update notice to the Component Builder Dashboard.
- Completely refactors the class that builds the Component Dashboard. #1134 - Completely refactors the class that builds the Component Dashboard. #1134
- Fix the FieldXML interface mismatch. #1228 - Fix the FieldXML interface mismatch. #1228
- Adds Initialize, Reset, and Push functionality to the Repository entities. - Adds Initialize, Reset, and Push functionality to the Repository entities.
- Completely refactors the SQL tweaks and SQL dump classes.
# v5.1.0 # v5.1.0

View File

@ -3292,7 +3292,7 @@ class Com_ComponentbuilderInstallerScript implements InstallerScriptInterface
echo '<div style="background-color: #fff;" class="alert alert-info"><a target="_blank" href="https://dev.vdm.io" title="Component Builder"> echo '<div style="background-color: #fff;" class="alert alert-info"><a target="_blank" href="https://dev.vdm.io" title="Component Builder">
<img src="components/com_componentbuilder/assets/images/vdm-component.jpg"/> <img src="components/com_componentbuilder/assets/images/vdm-component.jpg"/>
</a> </a>
<h3>Upgrade to Version 5.1.1-beta5 Was Successful! Let us know if anything is not working as expected.</h3></div>'; <h3>Upgrade to Version 5.1.1-beta6 Was Successful! Let us know if anything is not working as expected.</h3></div>';
// Add/Update component in the action logs extensions table. // Add/Update component in the action logs extensions table.
$this->setActionLogsExtensions(); $this->setActionLogsExtensions();

View File

@ -9,7 +9,7 @@ This is a professional-grade [Joomla 5.x](https://extensions.joomla.org/extensio
JCB generates native Joomla components, plugins, and modules for Joomla 3.x, 4.x, and 5.x - and is already prepared for Joomla 6. Every compiled project is tailored for the specific version without needing backward compatibility plugins. With integrated version-aware compiling, smart boilerplating, and Git-powered project syncing, JCB is much more than a code generator-it's a **full-stack development pipeline for Joomla extensions**. JCB generates native Joomla components, plugins, and modules for Joomla 3.x, 4.x, and 5.x - and is already prepared for Joomla 6. Every compiled project is tailored for the specific version without needing backward compatibility plugins. With integrated version-aware compiling, smart boilerplating, and Git-powered project syncing, JCB is much more than a code generator-it's a **full-stack development pipeline for Joomla extensions**.
You can install this component easily. The latest release (**5.1.1-beta5**) is available on [Releases](https://git.vdm.dev/joomla/pkg-component-builder/releases) and updated frequently with full source access. You can install this component easily. The latest release (**5.1.1-beta6**) is available on [Releases](https://git.vdm.dev/joomla/pkg-component-builder/releases) and updated frequently with full source access.
Upgrades are seamless through Joomla's built-in extension update mechanism. Upgrades are seamless through Joomla's built-in extension update mechanism.
@ -229,9 +229,9 @@ JCB is developed by developers for developers. Its purpose is to democratize hig
* **Company:** [Vast Development Method](https://dev.vdm.io) * **Company:** [Vast Development Method](https://dev.vdm.io)
* **Author:** [Llewellyn van der Merwe](mailto:joomla@vdm.io) * **Author:** [Llewellyn van der Merwe](mailto:joomla@vdm.io)
* **Component:** [Component Builder](https://git.vdm.dev/joomla/Component-Builder) * **Component:** [Component Builder](https://git.vdm.dev/joomla/Component-Builder)
* **Created:** 30th April, 2015 · **Last Build:** 25th June, 2025 · **Version:** 5.1.1-beta5 * **Created:** 30th April, 2015 · **Last Build:** 1st July, 2025 · **Version:** 5.1.1-beta6
* **License:** GNU General Public License version 2 or later; see LICENSE.txt · **Copyright:** Copyright (C) 2015 Vast Development Method. All rights reserved. * **License:** GNU General Public License version 2 or later; see LICENSE.txt · **Copyright:** Copyright (C) 2015 Vast Development Method. All rights reserved.
* **Lines:** 1092899 · **Fields:** 2096 · **Files:** 7506 · **Folders:** 728 * **Lines:** 1094999 · **Fields:** 2096 · **Files:** 7514 · **Folders:** 728
> Generated with [JCB](https://www.joomlacomponentbuilder.com) — The Smartest Way to Build Joomla Extensions. > Generated with [JCB](https://www.joomlacomponentbuilder.com) — The Smartest Way to Build Joomla Extensions.

View File

@ -9,7 +9,7 @@ This is a professional-grade [Joomla 5.x](https://extensions.joomla.org/extensio
JCB generates native Joomla components, plugins, and modules for Joomla 3.x, 4.x, and 5.x - and is already prepared for Joomla 6. Every compiled project is tailored for the specific version without needing backward compatibility plugins. With integrated version-aware compiling, smart boilerplating, and Git-powered project syncing, JCB is much more than a code generator-it's a **full-stack development pipeline for Joomla extensions**. JCB generates native Joomla components, plugins, and modules for Joomla 3.x, 4.x, and 5.x - and is already prepared for Joomla 6. Every compiled project is tailored for the specific version without needing backward compatibility plugins. With integrated version-aware compiling, smart boilerplating, and Git-powered project syncing, JCB is much more than a code generator-it's a **full-stack development pipeline for Joomla extensions**.
You can install this component easily. The latest release (**5.1.1-beta5**) is available on [Releases](https://git.vdm.dev/joomla/pkg-component-builder/releases) and updated frequently with full source access. You can install this component easily. The latest release (**5.1.1-beta6**) is available on [Releases](https://git.vdm.dev/joomla/pkg-component-builder/releases) and updated frequently with full source access.
Upgrades are seamless through Joomla's built-in extension update mechanism. Upgrades are seamless through Joomla's built-in extension update mechanism.
@ -229,9 +229,9 @@ JCB is developed by developers for developers. Its purpose is to democratize hig
* **Company:** [Vast Development Method](https://dev.vdm.io) * **Company:** [Vast Development Method](https://dev.vdm.io)
* **Author:** [Llewellyn van der Merwe](mailto:joomla@vdm.io) * **Author:** [Llewellyn van der Merwe](mailto:joomla@vdm.io)
* **Component:** [Component Builder](https://git.vdm.dev/joomla/Component-Builder) * **Component:** [Component Builder](https://git.vdm.dev/joomla/Component-Builder)
* **Created:** 30th April, 2015 · **Last Build:** 25th June, 2025 · **Version:** 5.1.1-beta5 * **Created:** 30th April, 2015 · **Last Build:** 1st July, 2025 · **Version:** 5.1.1-beta6
* **License:** GNU General Public License version 2 or later; see LICENSE.txt · **Copyright:** Copyright (C) 2015 Vast Development Method. All rights reserved. * **License:** GNU General Public License version 2 or later; see LICENSE.txt · **Copyright:** Copyright (C) 2015 Vast Development Method. All rights reserved.
* **Lines:** 1092899 · **Fields:** 2096 · **Files:** 7506 · **Folders:** 728 * **Lines:** 1094999 · **Fields:** 2096 · **Files:** 7514 · **Folders:** 728
> Generated with [JCB](https://www.joomlacomponentbuilder.com) — The Smartest Way to Build Joomla Extensions. > Generated with [JCB](https://www.joomlacomponentbuilder.com) — The Smartest Way to Build Joomla Extensions.

View File

@ -20,76 +20,104 @@ use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Mail\Mail; use Joomla\CMS\Mail\Mail;
use Joomla\Registry\Registry; use Joomla\Registry\Registry;
// No direct access to this file
\defined('_JEXEC') or die; \defined('_JEXEC') or die;
/** /**
* ###Component### component email helper * ###Component### component email helper
* *
* @since 3.0 * Provides a complete and configurable mailer integration for Joomla components.
* Allows for custom headers, DKIM signing, embedded images, and HTML styling.
*
* @since 3.0
*/ */
abstract class ###Component###Email abstract class ###Component###Email
{ {
/** /**
* The active recipient * The active recipient.
* *
* @var activeRecipient (array) * @var array<string, mixed>
* @since 3.0
*/ */
public static $active = []; public static array $active = [];
/** /**
* Configuration object * Mail instances container.
* *
* @var Registry * @var Joomla___890fd6b1_0127_4f35_9b6e_ee6f2dc61bcc___Power[]
* @since 1.7.3
*/ */
public static ?Registry $config = null; protected static array $instances = [];
/** /**
* Mailer object * Global Configuration object.
* *
* @var Mail * @var Registry|null
* @since 5.1.1
*/ */
public static ?Mail $mailer = null; protected static ?Registry $gConfig = null;
/** /**
* Custom Headers * Component Configuration object.
* *
* @var array * @var Registry|null
* @since 3.0
*/
protected static ?Registry $config = null;
/**
* Mailer object.
*
* @var Joomla___890fd6b1_0127_4f35_9b6e_ee6f2dc61bcc___Power|null
* @since 3.0
*/
protected static ?Joomla___890fd6b1_0127_4f35_9b6e_ee6f2dc61bcc___Power $mailer = null;
/**
* Custom email headers.
*
* @var array<string, string>
* @since 3.0
*/ */
protected static array $header = []; protected static array $header = [];
/** /**
* Get a configuration object * Retrieve the component configuration.
* *
* @return Registry Component configuration object
* @since 3.0
*/ */
public static function getConfig() protected static function getConfig(): Registry
{ {
if (!self::$config) return self::$config ??= Joomla___aeb8e463_291f_4445_9ac4_34b637c12dbd___Power::getParams('com_###component###');
{
self::$config = Joomla___aeb8e463_291f_4445_9ac4_34b637c12dbd___Power::getParams('com_###component###');
}
return self::$config;
} }
/** /**
* Returns the global mailer object, only creating it if it doesn't already exist. * Retrieve the global configuration.
* *
* @return Registry Global configuration object
* @since 3.0
*/ */
public static function getMailerInstance() protected static function getGlobalConfig(): Registry
{ {
if (!self::$mailer) return self::$gConfig ??= Joomla___39403062_84fb_46e0_bac4_0023f766e827___Power::getApplication()->getConfig();
{
self::$mailer = self::createMailer();
}
return self::$mailer;
} }
/** /**
* Check that a string looks like an email address. * Get or create a Mailer instance.
* @param string $address The email address to check *
* @param string|callable $patternselect A selector for the validation pattern to use : * @return Joomla___890fd6b1_0127_4f35_9b6e_ee6f2dc61bcc___Power A cloned Mail object instance
* @since 3.0
*/
public static function getMailer(): Joomla___890fd6b1_0127_4f35_9b6e_ee6f2dc61bcc___Power
{
return self::$mailer ??= self::createMailer();
}
/**
* Validate an email address using a selected pattern or callable.
*
* @param string $address Email address to validate.
* @param string|callable|null $patternselect Validation pattern or callable.
* * `auto` Pick best pattern automatically; * * `auto` Pick best pattern automatically;
* * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14; * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14;
* * `pcre` Use old PCRE implementation; * * `pcre` Use old PCRE implementation;
@ -101,374 +129,357 @@ abstract class ###Component###Email
* return (strpos($address, '@') !== false); * return (strpos($address, '@') !== false);
* }); * });
* You can also set the PHPMailer::$validator static to a callable, allowing built-in methods to use your validator. * You can also set the PHPMailer::$validator static to a callable, allowing built-in methods to use your validator.
* @return boolean *
* @static * @return bool True if valid, false otherwise
* @access public * @since 3.0
*/ */
public static function validateAddress($address, $patternselect = null): bool public static function validateAddress(string $address, $patternselect = null): bool
{ {
return self::getMailerInstance()->validateAddress($address, $patternselect); return self::getMailer()->validateAddress($address, $patternselect);
} }
/** /**
* Get a mailer object. * Set a custom email header.
* *
* Returns the global {@link Mail} object, only creating it if it doesn't already exist. * @param string $key Header name.
* @param string $value Header value.
* *
* @return Mail object * @return void
* * @since 3.0
* @see Mail
*/ */
public static function getMailer(): Mail public static function setHeader(string $key, string $value): void
{ {
if (!self::$mailer) self::$header[$key] = $value;
}
/**
* Get or create a Mail instance with specific configuration.
*
* @param string $id Instance ID.
* @param bool $exceptions Enable exceptions.
*
* @return Joomla___890fd6b1_0127_4f35_9b6e_ee6f2dc61bcc___Power Configured Mail instance
* @since 5.1.1
*/
public static function getInstance(string $id = 'Joomla', bool $exceptions = true): Joomla___890fd6b1_0127_4f35_9b6e_ee6f2dc61bcc___Power
{
if (!isset(self::$instances[$id]))
{ {
self::$mailer = self::createMailer(); $config = clone self::getGlobalConfig();
$config->set('throw_exceptions', $exceptions);
self::$instances[$id] = Joomla___39403062_84fb_46e0_bac4_0023f766e827___Power::getContainer()->get(Joomla___3e2779e9_b33f_42b8_a13b_53f08d99f15b___Power::class)->createMailer($config);
} }
$copy = clone self::$mailer; return self::$instances[$id];
return $copy;
} }
/** /**
* Create a mailer object * Create a configured Mail instance.
* *
* @return Mail object * @return Joomla___890fd6b1_0127_4f35_9b6e_ee6f2dc61bcc___Power The created Mail object with sender, reply-to and transport settings.
* * @since 3.0
* @see Mail
*/ */
protected static function createMailer(): Mail protected static function createMailer(): Joomla___890fd6b1_0127_4f35_9b6e_ee6f2dc61bcc___Power
{ {
// set component params $conf = self::getConfig();
$conf = self::getConfig();
// now load the mailer
$mailer = $conf->get('mailer', 'global'); $mailer = $conf->get('mailer', 'global');
$mail = self::getInstance();
// Create a Mail object if ($mailer === 'global')
$mail = Mail::getInstance();
// check if set to global
if ('global' == $mailer)
{ {
// get the global details $global = self::getGlobalConfig();
$globalConf = Joomla___39403062_84fb_46e0_bac4_0023f766e827___Power::getConfig(); $mailer = $global->get('mailer');
$params = [
$mailer = $globalConf->get('mailer'); 'smtpauth' => $global->get('smtpauth') ? 1 : null,
$smtpauth = ($globalConf->get('smtpauth') == 0) ? null : 1; 'smtpuser' => $global->get('smtpuser'),
$smtpuser = $globalConf->get('smtpuser'); 'smtppass' => $global->get('smtppass'),
$smtppass = $globalConf->get('smtppass'); 'smtphost' => $global->get('smtphost'),
$smtphost = $globalConf->get('smtphost'); 'smtpsecure' => $global->get('smtpsecure'),
$smtpsecure = $globalConf->get('smtpsecure'); 'smtpport' => $global->get('smtpport'),
$smtpport = $globalConf->get('smtpport'); 'sendmail' => $global->get('sendmail'),
$sendmail = $globalConf->get('sendmail'); 'from' => $global->get('mailfrom'),
$mailfrom = $globalConf->get('mailfrom'); 'name' => $global->get('fromname'),
$fromname = $globalConf->get('fromname'); 'replyto' => $global->get('replyto'),
$replyto = $globalConf->get('replyto'); 'replytoname' => $global->get('replytoname'),
$replytoname = $globalConf->get('replytoname'); ];
} }
else else
{ {
$smtpauth = ($conf->get('smtpauth') == 0) ? null : 1; $params = [
$smtpuser = $conf->get('smtpuser'); 'smtpauth' => $conf->get('smtpauth') ? 1 : null,
$smtppass = $conf->get('smtppass'); 'smtpuser' => $conf->get('smtpuser'),
$smtphost = $conf->get('smtphost'); 'smtppass' => $conf->get('smtppass'),
$smtpsecure = $conf->get('smtpsecure'); 'smtphost' => $conf->get('smtphost'),
$smtpport = $conf->get('smtpport'); 'smtpsecure' => $conf->get('smtpsecure'),
$sendmail = $conf->get('sendmail'); 'smtpport' => $conf->get('smtpport'),
$mailfrom = $conf->get('emailfrom'); 'sendmail' => $conf->get('sendmail'),
$fromname = $conf->get('fromname'); 'from' => $conf->get('emailfrom'),
$replyto = $conf->get('replyto'); 'name' => $conf->get('fromname'),
$replytoname = $conf->get('replytoname'); 'replyto' => $conf->get('replyto'),
'replytoname' => $conf->get('replytoname'),
];
} }
// Set global sender $mail->setSender([$params['from'], $params['name']]);
$mail->setSender(array($mailfrom, $fromname));
// set the global reply-to if found if (!empty($params['replyto']) && !empty($params['replytoname']))
if ($replyto && $replytoname) {
{
$mail->ClearReplyTos(); $mail->ClearReplyTos();
$mail->addReplyTo($replyto, $replytoname); $mail->addReplyTo($params['replyto'], $params['replytoname']);
} }
// Default mailer is to use PHP's mail function
switch ($mailer) switch ($mailer)
{ {
case 'smtp': case 'smtp':
// set the SMTP option $mail->useSMTP(
$mail->useSMTP($smtpauth, $smtphost, $smtpuser, $smtppass, $smtpsecure, $smtpport); $params['smtpauth'],
$params['smtphost'],
$params['smtpuser'],
$params['smtppass'],
$params['smtpsecure'],
$params['smtpport']
);
break; break;
case 'sendmail': case 'sendmail':
// set the sendmail option $mail->useSendmail($params['sendmail']);
$mail->useSendmail($sendmail);
$mail->IsSendmail(); $mail->IsSendmail();
break; break;
default: default:
$mail->IsMail(); $mail->IsMail();
break;
} }
return $mail; return $mail;
} }
/** /**
* Set a Mail custom header. * Compose and send an email with full options including attachments, HTML, DKIM, and reply-to support.
* *
* @return void * @param string|array $recipient Email or list of recipients.
* @param string $subject Subject line.
* @param string $body HTML body.
* @param string|null $textonly Optional plain text fallback.
* @param int $mode 1 = HTML, 0 = plain text.
* @param string|null $bounce_email Optional bounce email address.
* @param string|null $idsession Optional message tracking tag.
* @param string|array|null $mailreply Optional reply-to address(es).
* @param string|array|null $replyname Optional reply-to name(s).
* @param string|null $mailfrom Optional sender email override.
* @param string|null $fromname Optional sender name override.
* @param array|null $cc CC recipients.
* @param array|null $bcc BCC recipients.
* @param array|string|null $attachment Attachments.
* @param bool $embeded Embed image flag.
* @param array|null $embeds Embedded image definitions.
*
* @return bool True on success, false on failure.
* @since 3.0
*/ */
public static function setHeader($target, $value) public static function send(
{ $recipient,
// set the header string $subject,
self::$header[$target] = $value; string $body,
} ?string $textonly,
int $mode = 0,
/** ?string $bounce_email = null,
* Send an email ?string $idsession = null,
* $mailreply = null,
* @return bool on success $replyname = null,
* ?string $mailfrom = null,
*/ ?string $fromname = null,
public static function send($recipient, $subject, $body, $textonly, $mode = 0, $bounce_email = null, $idsession = null, $mailreply = null, $replyname = null , $mailfrom = null, $fromname = null, $cc = null, $bcc = null, $attachment = null, $embeded = null , $embeds = null) ?array $cc = null,
{ ?array $bcc = null,
// Get a Mail instance $attachment = null,
bool $embeded = false,
?array $embeds = null
): bool {
$mail = self::getMailer(); $mail = self::getMailer();
// set component params
$conf = self::getConfig(); $conf = self::getConfig();
// set if we have override
if ($mailfrom && $fromname) if ($mailfrom && $fromname)
{ {
$mail->setSender(array($mailfrom, $fromname)); $mail->setSender([$mailfrom, $fromname]);
} }
// load the bounce email as sender if set if ($bounce_email)
if (!is_null($bounce_email))
{ {
$mail->Sender = $bounce_email; $mail->Sender = $bounce_email;
} }
// Add tag to email to identify it if ($idsession)
if (!is_null($idsession))
{ {
$mail->addCustomHeader('X-VDMmethodID:'.$idsession); $mail->addCustomHeader('X-VDMmethodID:' . $idsession);
} }
// set headers if found foreach (self::$header as $key => $val)
if (isset(self::$header) && is_array(self::$header) && count((array)self::$header) > 0)
{ {
foreach (self::$header as $_target => $_value) $mail->addCustomHeader($key . ':' . $val);
{
$mail->addCustomHeader($_target.':'.$_value);
}
} }
// set the subject & Body
$mail->setSubject($subject); $mail->setSubject($subject);
$mail->setBody($body); $mail->setBody($body);
// Are we sending the email as HTML?
if ($mode) if ($mode)
{ {
$mail->IsHTML(true); $mail->isHTML(true);
$mail->AltBody = $textonly; $mail->AltBody = $textonly;
} }
//embed images if ($embeded && !empty($embeds))
if ($embeded)
{ {
if(Super___0a59c65c_9daf_4bc9_baf4_e063ff9e6a8a___Power::check($embeds)) foreach ($embeds as $embed)
{ {
foreach($embeds as $embed) $mail->addEmbeddedImage($embed->Path, $embed->FileName);
{
$mail->AddEmbeddedImage($embed->Path,$embed->FileName);
}
} }
} }
$mail->addRecipient($recipient); $mail->addRecipient($recipient);
$mail->addCC($cc); if (!empty($cc)) $mail->addCC($cc);
$mail->addBCC($bcc); if (!empty($bcc)) $mail->addBCC($bcc);
$mail->addAttachment($attachment); if (!empty($attachment)) $mail->addAttachment($attachment);
// Take care of reply email addresses if (!empty($mailreply))
if (is_array($mailreply))
{ {
$mail->ClearReplyTos(); $mail->ClearReplyTos();
$numReplyTo = count((array)$mailreply); if (is_array($mailreply))
for ($i=0; $i < $numReplyTo; $i++)
{ {
$mail->addReplyTo($mailreply[$i], $replyname[$i]); foreach ($mailreply as $i => $reply)
{
$mail->addReplyTo($reply, $replyname[$i] ?? '');
}
}
else
{
$mail->addReplyTo($mailreply, (string) $replyname);
} }
} }
elseif (!empty($mailreply))
{
$mail->ClearReplyTos();
$mail->addReplyTo($mailreply, $replyname);
}
// check if we can add the DKIM to email $sent = false;
if ($conf->get('enable_dkim')) $tmp = null;
{
if (!empty($conf->get('dkim_domain')) && !empty($conf->get('dkim_selector')) && !empty($conf->get('dkim_private')) && !empty($conf->get('dkim_public'))) try {
{ if (
$mail->DKIM_domain = $conf->get('dkim_domain'); $conf->get('enable_dkim') &&
$mail->DKIM_selector = $conf->get('dkim_selector'); ($domain = $conf->get('dkim_domain')) &&
$mail->DKIM_identity = $conf->get('dkim_identity'); ($selector = $conf->get('dkim_selector')) &&
$mail->DKIM_passphrase = $conf->get('dkim_passphrase'); ($privateKey = $conf->get('dkim_private'))
) {
$mail->DKIM_domain = $domain;
$mail->DKIM_selector = $selector;
$mail->DKIM_identity = $conf->get('dkim_identity') ?: $domain;
$mail->DKIM_passphrase = $conf->get('dkim_passphrase');
$tmp = tempnam(sys_get_temp_dir(), 'VDM'); $tmp = tempnam(sys_get_temp_dir(), 'VDM');
$h = fopen($tmp, 'w'); if ($tmp === false || file_put_contents($tmp, $privateKey) === false)
fwrite($h, $conf->get('dkim_private')); {
fclose($h); throw new \RuntimeException('Failed to create temporary DKIM private key file.');
$mail->DKIM_private = $tmp; }
$mail->DKIM_private = $tmp;
}
$sent = $mail->Send();
} finally {
if ($tmp && file_exists($tmp))
{
@unlink($tmp);
} }
} }
$sendmail = $mail->Send(); $sent = $mail->Send();
if ($conf->get('enable_dkim') && !empty($conf->get('dkim_domain')) && !empty($conf->get('dkim_selector')) && !empty($conf->get('dkim_private')) && !empty($conf->get('dkim_public'))) if ($tmp)
{ {
@unlink($tmp); @unlink($tmp);
} }
if (method_exists('###Component###Helper','storeMessage')) if (method_exists('###Component###Helper', 'storeMessage'))
{ {
// if we have active recipient details $data = self::$active[$recipient] ?? $recipient;
if (isset(self::$active[$recipient])) ###Component###Helper::storeMessage($sent, $data, $subject, $body, $textonly, $mode, 'email');
{ unset(self::$active[$recipient]);
// store the massage if the method is set
###Component###Helper::storeMessage($sendmail, self::$active[$recipient], $subject, $body, $textonly, $mode, 'email');
// clear memory
unset(self::$active[$recipient]);
}
else
{
// store the massage if the method is set
###Component###Helper::storeMessage($sendmail, $recipient, $subject, $body, $textonly, $mode, 'email');
}
} }
return $sendmail; return $sent;
} }
/** /**
* Set html text (in a row) and subject (as title) to a email table. * Build a complete minimal HTML email body with basic headers.
* do not use <p> instead use <br /> * Use <br /> instead of <p> for layout consistency in emails.
* in your html that you pass to this method
* since it is a table row it does not
* work well with paragraphs
* *
* @return string on success * @param string $html Body HTML content.
* @param string $subject Email subject/title used in the <title> tag.
* *
* @return string Full HTML email body.
* @since 3.0
*/ */
public static function setBasicBody($html, $subject) public static function setBasicBody(string $html, string $subject): string
{ {
$body = []; return implode("\n", [
$body[] = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"; '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
$body[] = "<html xmlns=\"http://www.w3.org/1999/xhtml\">"; '<html xmlns="http://www.w3.org/1999/xhtml">',
$body[] = "<head>"; '<head>',
$body[] = "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />"; '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />',
$body[] = "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"/>"; '<meta name="viewport" content="width=device-width, initial-scale=1.0"/>',
$body[] = "<title>" . $subject . "</title>"; '<title>' . htmlspecialchars($subject) . '</title>',
$body[] = "<style type=\"text/css\">"; '<style type="text/css">',
$body[] = "#outlook a {padding:0;}"; '#outlook a {padding:0;} .ExternalClass {width:100%;} .ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {line-height:100%;}',
$body[] = ".ExternalClass {width:100%;}"; 'p {margin: 0; padding: 0; font-size: 0px; line-height: 0px;}',
$body[] = ".ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {line-height: 100%;} "; 'table, table td {border-collapse: collapse;}',
$body[] = "p {margin: 0; padding: 0; font-size: 0px; line-height: 0px;} "; 'img {display:block; outline:none; text-decoration:none; -ms-interpolation-mode:bicubic;}',
$body[] = "table td {border-collapse: collapse;}"; 'a img {border:none;} a {text-decoration:none; color:#000001;} a.phone {pointer-events:auto; cursor:default; color:#000001 !important;}',
$body[] = "table {border-collapse: collapse; mso-table-lspace:0pt; mso-table-rspace:0pt; }"; 'span {font-size:13px; line-height:17px; font-family:monospace; color:#000001;}',
$body[] = "img {display: block; outline: none; text-decoration: none; -ms-interpolation-mode: bicubic;}"; '</style>',
$body[] = "a img {border: none;}"; '<!--[if gte mso 9]><style>/* Target Outlook 2007 and 2010 */</style><![endif]-->',
$body[] = "a {text-decoration: none; color: #000001;}"; '</head>',
$body[] = "a.phone {text-decoration: none; color: #000001 !important; pointer-events: auto; cursor: default;}"; '<body style="width:100%; margin:0; padding:0; -webkit-text-size-adjust:100%; -ms-text-size-adjust:100%;">',
$body[] = "span {font-size: 13px; line-height: 17px; font-family: monospace; color: #000001;}"; $html,
$body[] = "</style>"; '</body>',
$body[] = "<!--[if gte mso 9]>"; '</html>'
$body[] = "<style>"; ]);
$body[] = "/* Target Outlook 2007 and 2010 */";
$body[] = "</style>";
$body[] = "<![endif]-->";
$body[] = "</head>";
$body[] = "<body style=\"width:100%; margin:0; padding:0; -webkit-text-size-adjust:100%; -ms-text-size-adjust:100%;\">";
$body[] = $html;
$body[] = "</body>";
$body[] = "</html>";
return implode("\n", $body);
} }
/** /**
* Set html text (in a row) and subject (as title) to a email table. * Build a styled HTML email with outer table formatting for wide layout support.
* do not use <p> instead use <br /> * Suitable for rich content emails that need outer table structure.
* in your html that you pass to this method
* since it is a table row it does not
* work well with paragraphs
* *
* @return string on success * @param string $html Inner body HTML content.
* @param string $subject Email subject/title used in the <title> tag.
* *
* @return string Complete HTML email content.
* @since 3.0
*/ */
public static function setTableBody($html, $subject) public static function setTableBody(string $html, string $subject): string
{ {
$body = []; return implode("\n", [
$body[] = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"; '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
$body[] = "<html xmlns=\"http://www.w3.org/1999/xhtml\">"; '<html xmlns="http://www.w3.org/1999/xhtml">',
$body[] = "<head>"; '<head>',
$body[] = "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />"; '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />',
$body[] = "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"/>"; '<meta name="viewport" content="width=device-width, initial-scale=1.0"/>',
$body[] = "<title>" . $subject . "</title>"; '<title>' . htmlspecialchars($subject) . '</title>',
$body[] = "<style type=\"text/css\">"; '<style type="text/css">',
$body[] = "#outlook a {padding:0;}"; '#outlook a {padding:0;} .ExternalClass {width:100%;} .ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {line-height:100%;}',
$body[] = ".ExternalClass {width:100%;}"; 'p {margin: 0; padding: 0; font-size: 0px; line-height: 0px;}',
$body[] = ".ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {line-height: 100%;} "; 'table, table td {border-collapse: collapse;}',
$body[] = "p {margin: 0; padding: 0; font-size: 0px; line-height: 0px;} "; 'img {display:block; outline:none; text-decoration:none; -ms-interpolation-mode:bicubic;}',
$body[] = "table td {border-collapse: collapse;}"; 'a img {border:none;} a {text-decoration:none; color:#000001;} a.phone {pointer-events:auto; cursor:default; color:#000001 !important;}',
$body[] = "table {border-collapse: collapse; mso-table-lspace:0pt; mso-table-rspace:0pt; }"; 'span {font-size:13px; line-height:17px; font-family:monospace; color:#000001;}',
$body[] = "img {display: block; outline: none; text-decoration: none; -ms-interpolation-mode: bicubic;}"; '</style>',
$body[] = "a img {border: none;}"; '<!--[if gte mso 9]><style>/* Target Outlook 2007 and 2010 */</style><![endif]-->',
$body[] = "a {text-decoration: none; color: #000001;}"; '</head>',
$body[] = "a.phone {text-decoration: none; color: #000001 !important; pointer-events: auto; cursor: default;}"; '<body style="width:100%; margin:0; padding:0; -webkit-text-size-adjust:100%; -ms-text-size-adjust:100%;">',
$body[] = "span {font-size: 13px; line-height: 17px; font-family: monospace; color: #000001;}"; '<table cellpadding="0" cellspacing="0" border="0" width="100%" style="line-height:100% !important;">',
$body[] = "</style>"; '<tr><td valign="top">',
$body[] = "<!--[if gte mso 9]>"; '<table cellpadding="0" cellspacing="0" border="0" align="center" width="800">',
$body[] = "<style>"; '<tr><td valign="top">',
$body[] = "/* Target Outlook 2007 and 2010 */"; '<table cellpadding="0" cellspacing="0" border="0" align="center" width="780">',
$body[] = "</style>"; '<tr><td valign="top" style="vertical-align:top;">',
$body[] = "<![endif]-->"; $html,
$body[] = "</head>"; '</td></tr></table>',
$body[] = "<body style=\"width:100%; margin:0; padding:0; -webkit-text-size-adjust:100%; -ms-text-size-adjust:100%;\">"; '</td></tr></table>',
$body[] = "\n<!-- body wrapper -->"; '</td></tr></table>',
$body[] = "<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"margin:0; padding:0; width:100%; line-height: 100% !important;\">"; '</body>',
$body[] = "<tr>"; '</html>'
$body[] = "<td valign=\"top\">"; ]);
$body[] = "<!-- edge wrapper -->";
$body[] = "<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" align=\"center\" width=\"800\" >";
$body[] = "<tr>";
$body[] = "<td valign=\"top\">";
$body[] = "<!-- content wrapper -->";
$body[] = "<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" align=\"center\" width=\"780\">";
$body[] = "<tr>";
$body[] = "<td valign=\"top\" style=\"vertical-align: top;\">";
$body[] = $html;
$body[] = "</td>";
$body[] = "</tr>";
$body[] = "</table>";
$body[] = "<!-- / content wrapper -->";
$body[] = "</td>";
$body[] = "</tr>";
$body[] = "</table>";
$body[] = "<!-- / edge wrapper -->";
$body[] = "</td>";
$body[] = "</tr>";
$body[] = "</table>";
$body[] = "<!-- / page wrapper -->";
$body[] = "</body>";
$body[] = "</html>";
return implode("\n", $body);
} }
} }

View File

@ -138,18 +138,18 @@ class HtmlView extends BaseHtmlView
if ($this->refid && $this->ref) if ($this->refid && $this->ref)
{ {
// return to the item that referred to this item // return to the item that referred to this item
$this->referral = '&ref=' . (string)$this->ref . '&refid=' . (int)$this->refid; $this->referral = '&ref=' . (string) $this->ref . '&refid=' . (int) $this->refid;
} }
elseif($this->ref) elseif($this->ref)
{ {
// return to the list view that referred to this item // return to the list view that referred to this item
$this->referral = '&ref=' . (string)$this->ref; $this->referral = '&ref=' . (string) $this->ref;
} }
// check return value // check return value
if (!is_null($return)) if (!is_null($return))
{ {
// add the return value // add the return value
$this->referral .= '&return=' . (string)$return; $this->referral .= '&return=' . (string) $return;
}###LINKEDVIEWITEMS### }###LINKEDVIEWITEMS###
// Set the toolbar // Set the toolbar
@ -178,8 +178,8 @@ class HtmlView extends BaseHtmlView
{ {
###ADDTOOLBAR### ###ADDTOOLBAR###
// now initiate the toolbar // add the toolbar if it's not already loaded
$this->toolbar ??= Toolbar::getInstance(); $this->toolbar ??= Joomla___39403062_84fb_46e0_bac4_0023f766e827___Power::getContainer()->get(Joomla___5d2ae99b_1ea1_44f0_9b59_f1aa7eab9e2e___Power::class)->createToolbar('toolbar');
} }
/** /**

View File

@ -28,7 +28,7 @@ extract($displayData);
* Layout variables * Layout variables
* ----------------- * -----------------
* @var Form $tmpl The Empty form for template * @var Form $tmpl The Empty form for template
* @var array $forms Array of JForm instances for render the rows * @var array $forms Array of Form instances for render the rows
* @var bool $multiple The multiple state for the form field * @var bool $multiple The multiple state for the form field
* @var int $min Count of minimum repeating in multiple mode * @var int $min Count of minimum repeating in multiple mode
* @var int $max Count of maximum repeating in multiple mode * @var int $max Count of maximum repeating in multiple mode

File diff suppressed because one or more lines are too long

View File

@ -14,78 +14,107 @@ use Joomla\CMS\Factory;
use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Mail\Mail; use Joomla\CMS\Mail\Mail;
use Joomla\Registry\Registry; use Joomla\Registry\Registry;
use VDM\Joomla\Utilities\ArrayHelper; use Joomla\CMS\Mail\MailerInterface;
use Joomla\CMS\Mail\MailerFactoryInterface;
// No direct access to this file
\defined('_JEXEC') or die; \defined('_JEXEC') or die;
/** /**
* Componentbuilder component email helper * Componentbuilder component email helper
* *
* @since 3.0 * Provides a complete and configurable mailer integration for Joomla components.
* Allows for custom headers, DKIM signing, embedded images, and HTML styling.
*
* @since 3.0
*/ */
abstract class ComponentbuilderEmail abstract class ComponentbuilderEmail
{ {
/** /**
* The active recipient * The active recipient.
* *
* @var activeRecipient (array) * @var array<string, mixed>
* @since 3.0
*/ */
public static $active = []; public static array $active = [];
/** /**
* Configuration object * Mail instances container.
* *
* @var Registry * @var MailerInterface[]
* @since 1.7.3
*/ */
public static ?Registry $config = null; protected static array $instances = [];
/** /**
* Mailer object * Global Configuration object.
* *
* @var Mail * @var Registry|null
* @since 5.1.1
*/ */
public static ?Mail $mailer = null; protected static ?Registry $gConfig = null;
/** /**
* Custom Headers * Component Configuration object.
* *
* @var array * @var Registry|null
* @since 3.0
*/
protected static ?Registry $config = null;
/**
* Mailer object.
*
* @var MailerInterface|null
* @since 3.0
*/
protected static ?MailerInterface $mailer = null;
/**
* Custom email headers.
*
* @var array<string, string>
* @since 3.0
*/ */
protected static array $header = []; protected static array $header = [];
/** /**
* Get a configuration object * Retrieve the component configuration.
* *
* @return Registry Component configuration object
* @since 3.0
*/ */
public static function getConfig() protected static function getConfig(): Registry
{ {
if (!self::$config) return self::$config ??= ComponentHelper::getParams('com_componentbuilder');
{
self::$config = ComponentHelper::getParams('com_componentbuilder');
}
return self::$config;
} }
/** /**
* Returns the global mailer object, only creating it if it doesn't already exist. * Retrieve the global configuration.
* *
* @return Registry Global configuration object
* @since 3.0
*/ */
public static function getMailerInstance() protected static function getGlobalConfig(): Registry
{ {
if (!self::$mailer) return self::$gConfig ??= Factory::getApplication()->getConfig();
{
self::$mailer = self::createMailer();
}
return self::$mailer;
} }
/** /**
* Check that a string looks like an email address. * Get or create a Mailer instance.
* @param string $address The email address to check *
* @param string|callable $patternselect A selector for the validation pattern to use : * @return MailerInterface A cloned Mail object instance
* @since 3.0
*/
public static function getMailer(): MailerInterface
{
return self::$mailer ??= self::createMailer();
}
/**
* Validate an email address using a selected pattern or callable.
*
* @param string $address Email address to validate.
* @param string|callable|null $patternselect Validation pattern or callable.
* * `auto` Pick best pattern automatically; * * `auto` Pick best pattern automatically;
* * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14; * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14;
* * `pcre` Use old PCRE implementation; * * `pcre` Use old PCRE implementation;
@ -97,374 +126,357 @@ abstract class ComponentbuilderEmail
* return (strpos($address, '@') !== false); * return (strpos($address, '@') !== false);
* }); * });
* You can also set the PHPMailer::$validator static to a callable, allowing built-in methods to use your validator. * You can also set the PHPMailer::$validator static to a callable, allowing built-in methods to use your validator.
* @return boolean *
* @static * @return bool True if valid, false otherwise
* @access public * @since 3.0
*/ */
public static function validateAddress($address, $patternselect = null): bool public static function validateAddress(string $address, $patternselect = null): bool
{ {
return self::getMailerInstance()->validateAddress($address, $patternselect); return self::getMailer()->validateAddress($address, $patternselect);
} }
/** /**
* Get a mailer object. * Set a custom email header.
* *
* Returns the global {@link Mail} object, only creating it if it doesn't already exist. * @param string $key Header name.
* @param string $value Header value.
* *
* @return Mail object * @return void
* * @since 3.0
* @see Mail
*/ */
public static function getMailer(): Mail public static function setHeader(string $key, string $value): void
{ {
if (!self::$mailer) self::$header[$key] = $value;
}
/**
* Get or create a Mail instance with specific configuration.
*
* @param string $id Instance ID.
* @param bool $exceptions Enable exceptions.
*
* @return MailerInterface Configured Mail instance
* @since 5.1.1
*/
public static function getInstance(string $id = 'Joomla', bool $exceptions = true): MailerInterface
{
if (!isset(self::$instances[$id]))
{ {
self::$mailer = self::createMailer(); $config = clone self::getGlobalConfig();
$config->set('throw_exceptions', $exceptions);
self::$instances[$id] = Factory::getContainer()->get(MailerFactoryInterface::class)->createMailer($config);
} }
$copy = clone self::$mailer; return self::$instances[$id];
return $copy;
} }
/** /**
* Create a mailer object * Create a configured Mail instance.
* *
* @return Mail object * @return MailerInterface The created Mail object with sender, reply-to and transport settings.
* * @since 3.0
* @see Mail
*/ */
protected static function createMailer(): Mail protected static function createMailer(): MailerInterface
{ {
// set component params $conf = self::getConfig();
$conf = self::getConfig();
// now load the mailer
$mailer = $conf->get('mailer', 'global'); $mailer = $conf->get('mailer', 'global');
$mail = self::getInstance();
// Create a Mail object if ($mailer === 'global')
$mail = Mail::getInstance();
// check if set to global
if ('global' == $mailer)
{ {
// get the global details $global = self::getGlobalConfig();
$globalConf = Factory::getConfig(); $mailer = $global->get('mailer');
$params = [
$mailer = $globalConf->get('mailer'); 'smtpauth' => $global->get('smtpauth') ? 1 : null,
$smtpauth = ($globalConf->get('smtpauth') == 0) ? null : 1; 'smtpuser' => $global->get('smtpuser'),
$smtpuser = $globalConf->get('smtpuser'); 'smtppass' => $global->get('smtppass'),
$smtppass = $globalConf->get('smtppass'); 'smtphost' => $global->get('smtphost'),
$smtphost = $globalConf->get('smtphost'); 'smtpsecure' => $global->get('smtpsecure'),
$smtpsecure = $globalConf->get('smtpsecure'); 'smtpport' => $global->get('smtpport'),
$smtpport = $globalConf->get('smtpport'); 'sendmail' => $global->get('sendmail'),
$sendmail = $globalConf->get('sendmail'); 'from' => $global->get('mailfrom'),
$mailfrom = $globalConf->get('mailfrom'); 'name' => $global->get('fromname'),
$fromname = $globalConf->get('fromname'); 'replyto' => $global->get('replyto'),
$replyto = $globalConf->get('replyto'); 'replytoname' => $global->get('replytoname'),
$replytoname = $globalConf->get('replytoname'); ];
} }
else else
{ {
$smtpauth = ($conf->get('smtpauth') == 0) ? null : 1; $params = [
$smtpuser = $conf->get('smtpuser'); 'smtpauth' => $conf->get('smtpauth') ? 1 : null,
$smtppass = $conf->get('smtppass'); 'smtpuser' => $conf->get('smtpuser'),
$smtphost = $conf->get('smtphost'); 'smtppass' => $conf->get('smtppass'),
$smtpsecure = $conf->get('smtpsecure'); 'smtphost' => $conf->get('smtphost'),
$smtpport = $conf->get('smtpport'); 'smtpsecure' => $conf->get('smtpsecure'),
$sendmail = $conf->get('sendmail'); 'smtpport' => $conf->get('smtpport'),
$mailfrom = $conf->get('emailfrom'); 'sendmail' => $conf->get('sendmail'),
$fromname = $conf->get('fromname'); 'from' => $conf->get('emailfrom'),
$replyto = $conf->get('replyto'); 'name' => $conf->get('fromname'),
$replytoname = $conf->get('replytoname'); 'replyto' => $conf->get('replyto'),
'replytoname' => $conf->get('replytoname'),
];
} }
// Set global sender $mail->setSender([$params['from'], $params['name']]);
$mail->setSender(array($mailfrom, $fromname));
// set the global reply-to if found if (!empty($params['replyto']) && !empty($params['replytoname']))
if ($replyto && $replytoname) {
{
$mail->ClearReplyTos(); $mail->ClearReplyTos();
$mail->addReplyTo($replyto, $replytoname); $mail->addReplyTo($params['replyto'], $params['replytoname']);
} }
// Default mailer is to use PHP's mail function
switch ($mailer) switch ($mailer)
{ {
case 'smtp': case 'smtp':
// set the SMTP option $mail->useSMTP(
$mail->useSMTP($smtpauth, $smtphost, $smtpuser, $smtppass, $smtpsecure, $smtpport); $params['smtpauth'],
$params['smtphost'],
$params['smtpuser'],
$params['smtppass'],
$params['smtpsecure'],
$params['smtpport']
);
break; break;
case 'sendmail': case 'sendmail':
// set the sendmail option $mail->useSendmail($params['sendmail']);
$mail->useSendmail($sendmail);
$mail->IsSendmail(); $mail->IsSendmail();
break; break;
default: default:
$mail->IsMail(); $mail->IsMail();
break;
} }
return $mail; return $mail;
} }
/** /**
* Set a Mail custom header. * Compose and send an email with full options including attachments, HTML, DKIM, and reply-to support.
* *
* @return void * @param string|array $recipient Email or list of recipients.
* @param string $subject Subject line.
* @param string $body HTML body.
* @param string|null $textonly Optional plain text fallback.
* @param int $mode 1 = HTML, 0 = plain text.
* @param string|null $bounce_email Optional bounce email address.
* @param string|null $idsession Optional message tracking tag.
* @param string|array|null $mailreply Optional reply-to address(es).
* @param string|array|null $replyname Optional reply-to name(s).
* @param string|null $mailfrom Optional sender email override.
* @param string|null $fromname Optional sender name override.
* @param array|null $cc CC recipients.
* @param array|null $bcc BCC recipients.
* @param array|string|null $attachment Attachments.
* @param bool $embeded Embed image flag.
* @param array|null $embeds Embedded image definitions.
*
* @return bool True on success, false on failure.
* @since 3.0
*/ */
public static function setHeader($target, $value) public static function send(
{ $recipient,
// set the header string $subject,
self::$header[$target] = $value; string $body,
} ?string $textonly,
int $mode = 0,
/** ?string $bounce_email = null,
* Send an email ?string $idsession = null,
* $mailreply = null,
* @return bool on success $replyname = null,
* ?string $mailfrom = null,
*/ ?string $fromname = null,
public static function send($recipient, $subject, $body, $textonly, $mode = 0, $bounce_email = null, $idsession = null, $mailreply = null, $replyname = null , $mailfrom = null, $fromname = null, $cc = null, $bcc = null, $attachment = null, $embeded = null , $embeds = null) ?array $cc = null,
{ ?array $bcc = null,
// Get a Mail instance $attachment = null,
bool $embeded = false,
?array $embeds = null
): bool {
$mail = self::getMailer(); $mail = self::getMailer();
// set component params
$conf = self::getConfig(); $conf = self::getConfig();
// set if we have override
if ($mailfrom && $fromname) if ($mailfrom && $fromname)
{ {
$mail->setSender(array($mailfrom, $fromname)); $mail->setSender([$mailfrom, $fromname]);
} }
// load the bounce email as sender if set if ($bounce_email)
if (!is_null($bounce_email))
{ {
$mail->Sender = $bounce_email; $mail->Sender = $bounce_email;
} }
// Add tag to email to identify it if ($idsession)
if (!is_null($idsession))
{ {
$mail->addCustomHeader('X-VDMmethodID:'.$idsession); $mail->addCustomHeader('X-VDMmethodID:' . $idsession);
} }
// set headers if found foreach (self::$header as $key => $val)
if (isset(self::$header) && is_array(self::$header) && count((array)self::$header) > 0)
{ {
foreach (self::$header as $_target => $_value) $mail->addCustomHeader($key . ':' . $val);
{
$mail->addCustomHeader($_target.':'.$_value);
}
} }
// set the subject & Body
$mail->setSubject($subject); $mail->setSubject($subject);
$mail->setBody($body); $mail->setBody($body);
// Are we sending the email as HTML?
if ($mode) if ($mode)
{ {
$mail->IsHTML(true); $mail->isHTML(true);
$mail->AltBody = $textonly; $mail->AltBody = $textonly;
} }
//embed images if ($embeded && !empty($embeds))
if ($embeded)
{ {
if(ArrayHelper::check($embeds)) foreach ($embeds as $embed)
{ {
foreach($embeds as $embed) $mail->addEmbeddedImage($embed->Path, $embed->FileName);
{
$mail->AddEmbeddedImage($embed->Path,$embed->FileName);
}
} }
} }
$mail->addRecipient($recipient); $mail->addRecipient($recipient);
$mail->addCC($cc); if (!empty($cc)) $mail->addCC($cc);
$mail->addBCC($bcc); if (!empty($bcc)) $mail->addBCC($bcc);
$mail->addAttachment($attachment); if (!empty($attachment)) $mail->addAttachment($attachment);
// Take care of reply email addresses if (!empty($mailreply))
if (is_array($mailreply))
{ {
$mail->ClearReplyTos(); $mail->ClearReplyTos();
$numReplyTo = count((array)$mailreply); if (is_array($mailreply))
for ($i=0; $i < $numReplyTo; $i++)
{ {
$mail->addReplyTo($mailreply[$i], $replyname[$i]); foreach ($mailreply as $i => $reply)
{
$mail->addReplyTo($reply, $replyname[$i] ?? '');
}
}
else
{
$mail->addReplyTo($mailreply, (string) $replyname);
} }
} }
elseif (!empty($mailreply))
{
$mail->ClearReplyTos();
$mail->addReplyTo($mailreply, $replyname);
}
// check if we can add the DKIM to email $sent = false;
if ($conf->get('enable_dkim')) $tmp = null;
{
if (!empty($conf->get('dkim_domain')) && !empty($conf->get('dkim_selector')) && !empty($conf->get('dkim_private')) && !empty($conf->get('dkim_public'))) try {
{ if (
$mail->DKIM_domain = $conf->get('dkim_domain'); $conf->get('enable_dkim') &&
$mail->DKIM_selector = $conf->get('dkim_selector'); ($domain = $conf->get('dkim_domain')) &&
$mail->DKIM_identity = $conf->get('dkim_identity'); ($selector = $conf->get('dkim_selector')) &&
$mail->DKIM_passphrase = $conf->get('dkim_passphrase'); ($privateKey = $conf->get('dkim_private'))
) {
$mail->DKIM_domain = $domain;
$mail->DKIM_selector = $selector;
$mail->DKIM_identity = $conf->get('dkim_identity') ?: $domain;
$mail->DKIM_passphrase = $conf->get('dkim_passphrase');
$tmp = tempnam(sys_get_temp_dir(), 'VDM'); $tmp = tempnam(sys_get_temp_dir(), 'VDM');
$h = fopen($tmp, 'w'); if ($tmp === false || file_put_contents($tmp, $privateKey) === false)
fwrite($h, $conf->get('dkim_private')); {
fclose($h); throw new \RuntimeException('Failed to create temporary DKIM private key file.');
$mail->DKIM_private = $tmp; }
$mail->DKIM_private = $tmp;
}
$sent = $mail->Send();
} finally {
if ($tmp && file_exists($tmp))
{
@unlink($tmp);
} }
} }
$sendmail = $mail->Send(); $sent = $mail->Send();
if ($conf->get('enable_dkim') && !empty($conf->get('dkim_domain')) && !empty($conf->get('dkim_selector')) && !empty($conf->get('dkim_private')) && !empty($conf->get('dkim_public'))) if ($tmp)
{ {
@unlink($tmp); @unlink($tmp);
} }
if (method_exists('ComponentbuilderHelper','storeMessage')) if (method_exists('ComponentbuilderHelper', 'storeMessage'))
{ {
// if we have active recipient details $data = self::$active[$recipient] ?? $recipient;
if (isset(self::$active[$recipient])) ComponentbuilderHelper::storeMessage($sent, $data, $subject, $body, $textonly, $mode, 'email');
{ unset(self::$active[$recipient]);
// store the massage if the method is set
ComponentbuilderHelper::storeMessage($sendmail, self::$active[$recipient], $subject, $body, $textonly, $mode, 'email');
// clear memory
unset(self::$active[$recipient]);
}
else
{
// store the massage if the method is set
ComponentbuilderHelper::storeMessage($sendmail, $recipient, $subject, $body, $textonly, $mode, 'email');
}
} }
return $sendmail; return $sent;
} }
/** /**
* Set html text (in a row) and subject (as title) to a email table. * Build a complete minimal HTML email body with basic headers.
* do not use <p> instead use <br /> * Use <br /> instead of <p> for layout consistency in emails.
* in your html that you pass to this method
* since it is a table row it does not
* work well with paragraphs
* *
* @return string on success * @param string $html Body HTML content.
* @param string $subject Email subject/title used in the <title> tag.
* *
* @return string Full HTML email body.
* @since 3.0
*/ */
public static function setBasicBody($html, $subject) public static function setBasicBody(string $html, string $subject): string
{ {
$body = []; return implode("\n", [
$body[] = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"; '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
$body[] = "<html xmlns=\"http://www.w3.org/1999/xhtml\">"; '<html xmlns="http://www.w3.org/1999/xhtml">',
$body[] = "<head>"; '<head>',
$body[] = "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />"; '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />',
$body[] = "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"/>"; '<meta name="viewport" content="width=device-width, initial-scale=1.0"/>',
$body[] = "<title>" . $subject . "</title>"; '<title>' . htmlspecialchars($subject) . '</title>',
$body[] = "<style type=\"text/css\">"; '<style type="text/css">',
$body[] = "#outlook a {padding:0;}"; '#outlook a {padding:0;} .ExternalClass {width:100%;} .ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {line-height:100%;}',
$body[] = ".ExternalClass {width:100%;}"; 'p {margin: 0; padding: 0; font-size: 0px; line-height: 0px;}',
$body[] = ".ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {line-height: 100%;} "; 'table, table td {border-collapse: collapse;}',
$body[] = "p {margin: 0; padding: 0; font-size: 0px; line-height: 0px;} "; 'img {display:block; outline:none; text-decoration:none; -ms-interpolation-mode:bicubic;}',
$body[] = "table td {border-collapse: collapse;}"; 'a img {border:none;} a {text-decoration:none; color:#000001;} a.phone {pointer-events:auto; cursor:default; color:#000001 !important;}',
$body[] = "table {border-collapse: collapse; mso-table-lspace:0pt; mso-table-rspace:0pt; }"; 'span {font-size:13px; line-height:17px; font-family:monospace; color:#000001;}',
$body[] = "img {display: block; outline: none; text-decoration: none; -ms-interpolation-mode: bicubic;}"; '</style>',
$body[] = "a img {border: none;}"; '<!--[if gte mso 9]><style>/* Target Outlook 2007 and 2010 */</style><![endif]-->',
$body[] = "a {text-decoration: none; color: #000001;}"; '</head>',
$body[] = "a.phone {text-decoration: none; color: #000001 !important; pointer-events: auto; cursor: default;}"; '<body style="width:100%; margin:0; padding:0; -webkit-text-size-adjust:100%; -ms-text-size-adjust:100%;">',
$body[] = "span {font-size: 13px; line-height: 17px; font-family: monospace; color: #000001;}"; $html,
$body[] = "</style>"; '</body>',
$body[] = "<!--[if gte mso 9]>"; '</html>'
$body[] = "<style>"; ]);
$body[] = "/* Target Outlook 2007 and 2010 */";
$body[] = "</style>";
$body[] = "<![endif]-->";
$body[] = "</head>";
$body[] = "<body style=\"width:100%; margin:0; padding:0; -webkit-text-size-adjust:100%; -ms-text-size-adjust:100%;\">";
$body[] = $html;
$body[] = "</body>";
$body[] = "</html>";
return implode("\n", $body);
} }
/** /**
* Set html text (in a row) and subject (as title) to a email table. * Build a styled HTML email with outer table formatting for wide layout support.
* do not use <p> instead use <br /> * Suitable for rich content emails that need outer table structure.
* in your html that you pass to this method
* since it is a table row it does not
* work well with paragraphs
* *
* @return string on success * @param string $html Inner body HTML content.
* @param string $subject Email subject/title used in the <title> tag.
* *
* @return string Complete HTML email content.
* @since 3.0
*/ */
public static function setTableBody($html, $subject) public static function setTableBody(string $html, string $subject): string
{ {
$body = []; return implode("\n", [
$body[] = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"; '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
$body[] = "<html xmlns=\"http://www.w3.org/1999/xhtml\">"; '<html xmlns="http://www.w3.org/1999/xhtml">',
$body[] = "<head>"; '<head>',
$body[] = "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />"; '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />',
$body[] = "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"/>"; '<meta name="viewport" content="width=device-width, initial-scale=1.0"/>',
$body[] = "<title>" . $subject . "</title>"; '<title>' . htmlspecialchars($subject) . '</title>',
$body[] = "<style type=\"text/css\">"; '<style type="text/css">',
$body[] = "#outlook a {padding:0;}"; '#outlook a {padding:0;} .ExternalClass {width:100%;} .ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {line-height:100%;}',
$body[] = ".ExternalClass {width:100%;}"; 'p {margin: 0; padding: 0; font-size: 0px; line-height: 0px;}',
$body[] = ".ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {line-height: 100%;} "; 'table, table td {border-collapse: collapse;}',
$body[] = "p {margin: 0; padding: 0; font-size: 0px; line-height: 0px;} "; 'img {display:block; outline:none; text-decoration:none; -ms-interpolation-mode:bicubic;}',
$body[] = "table td {border-collapse: collapse;}"; 'a img {border:none;} a {text-decoration:none; color:#000001;} a.phone {pointer-events:auto; cursor:default; color:#000001 !important;}',
$body[] = "table {border-collapse: collapse; mso-table-lspace:0pt; mso-table-rspace:0pt; }"; 'span {font-size:13px; line-height:17px; font-family:monospace; color:#000001;}',
$body[] = "img {display: block; outline: none; text-decoration: none; -ms-interpolation-mode: bicubic;}"; '</style>',
$body[] = "a img {border: none;}"; '<!--[if gte mso 9]><style>/* Target Outlook 2007 and 2010 */</style><![endif]-->',
$body[] = "a {text-decoration: none; color: #000001;}"; '</head>',
$body[] = "a.phone {text-decoration: none; color: #000001 !important; pointer-events: auto; cursor: default;}"; '<body style="width:100%; margin:0; padding:0; -webkit-text-size-adjust:100%; -ms-text-size-adjust:100%;">',
$body[] = "span {font-size: 13px; line-height: 17px; font-family: monospace; color: #000001;}"; '<table cellpadding="0" cellspacing="0" border="0" width="100%" style="line-height:100% !important;">',
$body[] = "</style>"; '<tr><td valign="top">',
$body[] = "<!--[if gte mso 9]>"; '<table cellpadding="0" cellspacing="0" border="0" align="center" width="800">',
$body[] = "<style>"; '<tr><td valign="top">',
$body[] = "/* Target Outlook 2007 and 2010 */"; '<table cellpadding="0" cellspacing="0" border="0" align="center" width="780">',
$body[] = "</style>"; '<tr><td valign="top" style="vertical-align:top;">',
$body[] = "<![endif]-->"; $html,
$body[] = "</head>"; '</td></tr></table>',
$body[] = "<body style=\"width:100%; margin:0; padding:0; -webkit-text-size-adjust:100%; -ms-text-size-adjust:100%;\">"; '</td></tr></table>',
$body[] = "\n<!-- body wrapper -->"; '</td></tr></table>',
$body[] = "<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"margin:0; padding:0; width:100%; line-height: 100% !important;\">"; '</body>',
$body[] = "<tr>"; '</html>'
$body[] = "<td valign=\"top\">"; ]);
$body[] = "<!-- edge wrapper -->";
$body[] = "<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" align=\"center\" width=\"800\" >";
$body[] = "<tr>";
$body[] = "<td valign=\"top\">";
$body[] = "<!-- content wrapper -->";
$body[] = "<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" align=\"center\" width=\"780\">";
$body[] = "<tr>";
$body[] = "<td valign=\"top\" style=\"vertical-align: top;\">";
$body[] = $html;
$body[] = "</td>";
$body[] = "</tr>";
$body[] = "</table>";
$body[] = "<!-- / content wrapper -->";
$body[] = "</td>";
$body[] = "</tr>";
$body[] = "</table>";
$body[] = "<!-- / edge wrapper -->";
$body[] = "</td>";
$body[] = "</tr>";
$body[] = "</table>";
$body[] = "<!-- / page wrapper -->";
$body[] = "</body>";
$body[] = "</html>";
return implode("\n", $body);
} }
} }

View File

@ -46,6 +46,7 @@ use VDM\Joomla\Utilities\FileHelper;
use VDM\Joomla\Utilities\JsonHelper; use VDM\Joomla\Utilities\JsonHelper;
use VDM\Joomla\Utilities\ObjectHelper; use VDM\Joomla\Utilities\ObjectHelper;
use VDM\Joomla\Utilities\Component\Helper; use VDM\Joomla\Utilities\Component\Helper;
use VDM\Joomla\Utilities\SessionHelper;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\FieldHelper; use VDM\Joomla\Componentbuilder\Compiler\Utilities\FieldHelper;
use VDM\Joomla\Componentbuilder\Compiler\Factory as CompilerFactory; use VDM\Joomla\Componentbuilder\Compiler\Factory as CompilerFactory;
use VDM\Joomla\Utilities\Base64Helper; use VDM\Joomla\Utilities\Base64Helper;
@ -1469,15 +1470,6 @@ abstract class ComponentbuilderHelper
return false; return false;
} }
/**
* set the session defaults if not set
**/
protected static function setSessionDefaults()
{
// noting for now
return true;
}
/** /**
* check if it is a new hash * check if it is a new hash
**/ **/
@ -2294,61 +2286,70 @@ abstract class ComponentbuilderHelper
/** /**
* the Butler * Local in-memory cache of session values for faster access.
**/ *
public static $session = array(); * @var array<string, mixed>
* @since 3.5.2
*/
protected static array $localSession = [];
/** /**
* the Butler Assistant * Initialize the session and set default values.
**/ *
protected static $localSession = array(); * This ensures the session is ready and can be used safely.
* Defaults can be loaded or checked here if needed.
/** *
* start a session if not already set, and load with data * @return void
**/ * @throws \RuntimeException if the session cannot be initialized
public static function loadSession() * @since 3.5.2
*/
public static function loadSession(): void
{ {
if (!isset(self::$session) || !ObjectHelper::check(self::$session)) // Ensure the session is initialized (handled by the session() method).
SessionHelper::session();
// Set default session values if needed
if (method_exists(static::class, 'setSessionDefaults'))
{ {
self::$session = Factory::getApplication()->getSession(); static::setSessionDefaults();
} }
// set the defaults
self::setSessionDefaults();
} }
/** /**
* give Session more to keep * Store a key-value pair in the session and local memory.
**/ *
public static function set($key, $value) * @param string $key The session key name
* @param mixed $value The value to store
*
* @return mixed The previous session value if it existed
* @since 3.5.2
*/
public static function set(string $key, $value)
{ {
if (!isset(self::$session) || !ObjectHelper::check(self::$session)) static::$localSession[$key] = $value;
{
self::$session = Factory::getApplication()->getSession(); return SessionHelper::set($key, $value);
}
// set to local memory to speed up program
self::$localSession[$key] = $value;
// load to session for later use
return self::$session->set($key, self::$localSession[$key]);
} }
/** /**
* get info from Session * Retrieve a value from the session.
**/ * Uses local cache if already fetched during this request.
public static function get($key, $default = null) *
* @param string $key The session key name
* @param mixed $default Default value if the key is not found
*
* @return mixed The session value
* @since 3.5.2
*/
public static function get(string $key, $default = null)
{ {
if (!isset(self::$session) || !ObjectHelper::check(self::$session)) if (!array_key_exists($key, static::$localSession))
{ {
self::$session = Factory::getApplication()->getSession(); static::$localSession[$key] = SessionHelper::get($key, $default);
} }
// check if in local memory
if (!isset(self::$localSession[$key]))
{
// set to local memory to speed up program
self::$localSession[$key] = self::$session->get($key, $default);
}
return self::$localSession[$key];
}
return static::$localSession[$key];
}
/** /**
* get field type properties * get field type properties

View File

@ -970,7 +970,7 @@ class Admin_viewModel extends AdminModel
/** /**
* Method to validate the form data. * Method to validate the form data.
* *
* @param JForm $form The form to validate against. * @param Form $form The form to validate against.
* @param array $data The data to validate. * @param array $data The data to validate.
* @param string $group The name of the field group to validate. * @param string $group The name of the field group to validate.
* *

View File

@ -28,6 +28,7 @@ use VDM\Joomla\Utilities\FormHelper as JCBFormHelper;
use VDM\Joomla\Utilities\ArrayHelper as UtilitiesArrayHelper; use VDM\Joomla\Utilities\ArrayHelper as UtilitiesArrayHelper;
use VDM\Joomla\Utilities\ObjectHelper; use VDM\Joomla\Utilities\ObjectHelper;
use VDM\Joomla\Utilities\StringHelper; use VDM\Joomla\Utilities\StringHelper;
use Joomla\CMS\Form\Form;
// No direct access to this file // No direct access to this file
\defined('_JEXEC') or die; \defined('_JEXEC') or die;
@ -109,7 +110,7 @@ class Admin_viewsModel extends ListModel
* @param array $data data * @param array $data data
* @param boolean $loadData load current data * @param boolean $loadData load current data
* *
* @return \JForm|boolean The \JForm object or false on error * @return Form|boolean The Form object or false on error
* *
* @since JCB 2.12.5 * @since JCB 2.12.5
*/ */

View File

@ -28,6 +28,7 @@ use VDM\Joomla\Componentbuilder\Utilities\FilterHelper as JCBFilterHelper;
use VDM\Joomla\Utilities\ArrayHelper as UtilitiesArrayHelper; use VDM\Joomla\Utilities\ArrayHelper as UtilitiesArrayHelper;
use VDM\Joomla\Utilities\ObjectHelper; use VDM\Joomla\Utilities\ObjectHelper;
use VDM\Joomla\Utilities\StringHelper; use VDM\Joomla\Utilities\StringHelper;
use Joomla\CMS\Form\Form;
// No direct access to this file // No direct access to this file
\defined('_JEXEC') or die; \defined('_JEXEC') or die;
@ -108,7 +109,7 @@ class Custom_admin_viewsModel extends ListModel
* @param array $data data * @param array $data data
* @param boolean $loadData load current data * @param boolean $loadData load current data
* *
* @return \JForm|boolean The \JForm object or false on error * @return Form|boolean The Form object or false on error
* *
* @since JCB 2.12.5 * @since JCB 2.12.5
*/ */

View File

@ -592,7 +592,7 @@ class Custom_codeModel extends AdminModel
/** /**
* Method to validate the form data. * Method to validate the form data.
* *
* @param JForm $form The form to validate against. * @param Form $form The form to validate against.
* @param array $data The data to validate. * @param array $data The data to validate.
* @param string $group The name of the field group to validate. * @param string $group The name of the field group to validate.
* *

View File

@ -747,7 +747,7 @@ class Dynamic_getModel extends AdminModel
/** /**
* Method to validate the form data. * Method to validate the form data.
* *
* @param JForm $form The form to validate against. * @param Form $form The form to validate against.
* @param array $data The data to validate. * @param array $data The data to validate.
* @param string $group The name of the field group to validate. * @param string $group The name of the field group to validate.
* *

View File

@ -678,7 +678,7 @@ class FieldModel extends AdminModel
/** /**
* Method to validate the form data. * Method to validate the form data.
* *
* @param JForm $form The form to validate against. * @param Form $form The form to validate against.
* @param array $data The data to validate. * @param array $data The data to validate.
* @param string $group The name of the field group to validate. * @param string $group The name of the field group to validate.
* *

View File

@ -28,6 +28,7 @@ use VDM\Joomla\Componentbuilder\Utilities\FilterHelper as JCBFilterHelper;
use VDM\Joomla\Utilities\ArrayHelper as UtilitiesArrayHelper; use VDM\Joomla\Utilities\ArrayHelper as UtilitiesArrayHelper;
use VDM\Joomla\Utilities\ObjectHelper; use VDM\Joomla\Utilities\ObjectHelper;
use VDM\Joomla\Utilities\StringHelper; use VDM\Joomla\Utilities\StringHelper;
use Joomla\CMS\Form\Form;
// No direct access to this file // No direct access to this file
\defined('_JEXEC') or die; \defined('_JEXEC') or die;
@ -111,7 +112,7 @@ class FieldsModel extends ListModel
* @param array $data data * @param array $data data
* @param boolean $loadData load current data * @param boolean $loadData load current data
* *
* @return \JForm|boolean The \JForm object or false on error * @return Form|boolean The Form object or false on error
* *
* @since JCB 2.12.5 * @since JCB 2.12.5
*/ */

View File

@ -611,7 +611,7 @@ class FieldtypeModel extends AdminModel
/** /**
* Method to validate the form data. * Method to validate the form data.
* *
* @param JForm $form The form to validate against. * @param Form $form The form to validate against.
* @param array $data The data to validate. * @param array $data The data to validate.
* @param string $group The name of the field group to validate. * @param string $group The name of the field group to validate.
* *

View File

@ -477,7 +477,7 @@ class Help_documentModel extends AdminModel
/** /**
* Method to validate the form data. * Method to validate the form data.
* *
* @param JForm $form The form to validate against. * @param Form $form The form to validate against.
* @param array $data The data to validate. * @param array $data The data to validate.
* @param string $group The name of the field group to validate. * @param string $group The name of the field group to validate.
* *

View File

@ -904,7 +904,7 @@ class Joomla_componentModel extends AdminModel
/** /**
* Method to validate the form data. * Method to validate the form data.
* *
* @param JForm $form The form to validate against. * @param Form $form The form to validate against.
* @param array $data The data to validate. * @param array $data The data to validate.
* @param string $group The name of the field group to validate. * @param string $group The name of the field group to validate.
* *

View File

@ -202,6 +202,30 @@ class Language_translationModel extends AdminModel
$item->metadata = $registry->toArray(); $item->metadata = $registry->toArray();
} }
if (!empty($item->plugins))
{
// Convert the plugins field to an array.
$plugins = new Registry;
$plugins->loadString($item->plugins);
$item->plugins = $plugins->toArray();
}
if (!empty($item->modules))
{
// Convert the modules field to an array.
$modules = new Registry;
$modules->loadString($item->modules);
$item->modules = $modules->toArray();
}
if (!empty($item->components))
{
// Convert the components field to an array.
$components = new Registry;
$components->loadString($item->components);
$item->components = $components->toArray();
}
if (!empty($item->translation)) if (!empty($item->translation))
{ {
// Convert the translation field to an array. // Convert the translation field to an array.
@ -210,24 +234,6 @@ class Language_translationModel extends AdminModel
$item->translation = $translation->toArray(); $item->translation = $translation->toArray();
} }
if (!empty($item->plugins))
{
// JSON Decode plugins.
$item->plugins = json_decode($item->plugins);
}
if (!empty($item->modules))
{
// JSON Decode modules.
$item->modules = json_decode($item->modules);
}
if (!empty($item->components))
{
// JSON Decode components.
$item->components = json_decode($item->components);
}
if (empty($item->id)) if (empty($item->id))
{ {
@ -987,6 +993,45 @@ class Language_translationModel extends AdminModel
$data['metadata'] = (string) $metadata; $data['metadata'] = (string) $metadata;
} }
// Set the plugins items to data.
if (isset($data['plugins']) && is_array($data['plugins']))
{
$plugins = new Registry;
$plugins->loadArray($data['plugins']);
$data['plugins'] = (string) $plugins;
}
elseif (!isset($data['plugins']))
{
// Set the empty plugins to data
$data['plugins'] = '';
}
// Set the modules items to data.
if (isset($data['modules']) && is_array($data['modules']))
{
$modules = new Registry;
$modules->loadArray($data['modules']);
$data['modules'] = (string) $modules;
}
elseif (!isset($data['modules']))
{
// Set the empty modules to data
$data['modules'] = '';
}
// Set the components items to data.
if (isset($data['components']) && is_array($data['components']))
{
$components = new Registry;
$components->loadArray($data['components']);
$data['components'] = (string) $components;
}
elseif (!isset($data['components']))
{
// Set the empty components to data
$data['components'] = '';
}
// Set the translation items to data. // Set the translation items to data.
if (isset($data['translation']) && is_array($data['translation'])) if (isset($data['translation']) && is_array($data['translation']))
{ {
@ -1000,24 +1045,6 @@ class Language_translationModel extends AdminModel
$data['translation'] = ''; $data['translation'] = '';
} }
// Set the plugins string to JSON string.
if (isset($data['plugins']))
{
$data['plugins'] = (string) json_encode($data['plugins']);
}
// Set the modules string to JSON string.
if (isset($data['modules']))
{
$data['modules'] = (string) json_encode($data['modules']);
}
// Set the components string to JSON string.
if (isset($data['components']))
{
$data['components'] = (string) json_encode($data['components']);
}
// Set the Params Items to data // Set the Params Items to data
if (isset($data['params']) && is_array($data['params'])) if (isset($data['params']) && is_array($data['params']))
{ {

View File

@ -29,6 +29,7 @@ use VDM\Joomla\Utilities\ArrayHelper as UtilitiesArrayHelper;
use VDM\Joomla\Utilities\ObjectHelper; use VDM\Joomla\Utilities\ObjectHelper;
use VDM\Joomla\Utilities\StringHelper; use VDM\Joomla\Utilities\StringHelper;
use VDM\Joomla\Utilities\JsonHelper; use VDM\Joomla\Utilities\JsonHelper;
use Joomla\CMS\Form\Form;
// No direct access to this file // No direct access to this file
\defined('_JEXEC') or die; \defined('_JEXEC') or die;
@ -104,7 +105,7 @@ class Language_translationsModel extends ListModel
* @param array $data data * @param array $data data
* @param boolean $loadData load current data * @param boolean $loadData load current data
* *
* @return \JForm|boolean The \JForm object or false on error * @return Form|boolean The Form object or false on error
* *
* @since JCB 2.12.5 * @since JCB 2.12.5
*/ */
@ -355,54 +356,50 @@ class Language_translationsModel extends ListModel
// From the componentbuilder_item table // From the componentbuilder_item table
$query->from($db->quoteName('#__componentbuilder_language_translation', 'a')); $query->from($db->quoteName('#__componentbuilder_language_translation', 'a'));
// do not use these filters in the export method // Filtering "translated in"
if (!isset($_export) || !$_export) $filter_translated = $this->state->get("filter.translated");
if ($filter_translated !== null && !empty($filter_translated))
{ {
// Filtering "translated in" if (($ids = JCBFilterHelper::translations($filter_translated)) !== null)
$filter_translated = $this->state->get("filter.translated");
if ($filter_translated !== null && !empty($filter_translated))
{ {
if (($ids = JCBFilterHelper::translations($filter_translated)) !== null) $query->where($db->quoteName('a.id') . ' IN (' . implode(',', $ids) . ')');
{
$query->where($db->quoteName('a.id') . ' IN (' . implode(',', $ids) . ')');
}
else
{
// there is none
$query->where($db->quoteName('a.id') . ' = ' . 0);
}
} }
else
// Filtering "not translated in"
$filter_not_translated = $this->state->get("filter.not_translated");
if ($filter_not_translated !== null && !empty($filter_not_translated))
{ {
if (($ids = JCBFilterHelper::translations($filter_not_translated, false)) !== null) // there is none
{ $query->where($db->quoteName('a.id') . ' = ' . 0);
$query->where($db->quoteName('a.id') . ' IN (' . implode(',',$ids) . ')');
}
else
{
// there is none
$query->where($db->quoteName('a.id') . ' = ' . 0);
}
} }
}
// Filtering "extension" // Filtering "not translated in"
$filter_extension = $this->state->get("filter.extension"); $filter_not_translated = $this->state->get("filter.not_translated");
if ($filter_extension !== null && !empty($filter_extension)) if ($filter_not_translated !== null && !empty($filter_not_translated))
{
if (($ids = JCBFilterHelper::translations($filter_not_translated, false)) !== null)
{ {
// column name, and id $query->where($db->quoteName('a.id') . ' IN (' . implode(',',$ids) . ')');
$type_extension = explode('__', $filter_extension); }
if (($ids = JCBFilterHelper::translation((int) $type_extension[1], $type_extension[0])) !== null) else
{ {
$query->where($db->quoteName('a.id') . ' IN (' . implode(',', $ids) . ')'); // there is none
} $query->where($db->quoteName('a.id') . ' = ' . 0);
else }
{ }
// there is none
$query->where($db->quoteName('a.id') . ' = ' . 0); // Filtering "extension"
} $filter_extension = $this->state->get("filter.extension");
if ($filter_extension !== null && !empty($filter_extension))
{
// column name, and id
$type_extension = explode('__', $filter_extension);
if (($ids = JCBFilterHelper::translation((string) $type_extension[1], (string) $type_extension[0])) !== null)
{
$query->where($db->quoteName('a.id') . ' IN (' . implode(',', $ids) . ')');
}
else
{
// there is none
$query->where($db->quoteName('a.id') . ' = ' . 0);
} }
} }
@ -516,54 +513,50 @@ class Language_translationsModel extends ListModel
$query->where('a.id IN (' . implode(',',$pks) . ')'); $query->where('a.id IN (' . implode(',',$pks) . ')');
} }
// do not use these filters in the export method
if (!isset($_export) || !$_export)
{
// Filtering "translated in" // Filtering "translated in"
$filter_translated = $this->state->get("filter.translated"); $filter_translated = $this->state->get("filter.translated");
if ($filter_translated !== null && !empty($filter_translated)) if ($filter_translated !== null && !empty($filter_translated))
{
if (($ids = JCBFilterHelper::translations($filter_translated)) !== null)
{ {
if (($ids = JCBFilterHelper::translations($filter_translated)) !== null) $query->where($db->quoteName('a.id') . ' IN (' . implode(',', $ids) . ')');
{
$query->where($db->quoteName('a.id') . ' IN (' . implode(',', $ids) . ')');
}
else
{
// there is none
$query->where($db->quoteName('a.id') . ' = ' . 0);
}
} }
else
// Filtering "not translated in"
$filter_not_translated = $this->state->get("filter.not_translated");
if ($filter_not_translated !== null && !empty($filter_not_translated))
{ {
if (($ids = JCBFilterHelper::translations($filter_not_translated, false)) !== null) // there is none
{ $query->where($db->quoteName('a.id') . ' = ' . 0);
$query->where($db->quoteName('a.id') . ' IN (' . implode(',',$ids) . ')');
}
else
{
// there is none
$query->where($db->quoteName('a.id') . ' = ' . 0);
}
} }
}
// Filtering "extension" // Filtering "not translated in"
$filter_extension = $this->state->get("filter.extension"); $filter_not_translated = $this->state->get("filter.not_translated");
if ($filter_extension !== null && !empty($filter_extension)) if ($filter_not_translated !== null && !empty($filter_not_translated))
{
if (($ids = JCBFilterHelper::translations($filter_not_translated, false)) !== null)
{ {
// column name, and id $query->where($db->quoteName('a.id') . ' IN (' . implode(',',$ids) . ')');
$type_extension = explode('__', $filter_extension); }
if (($ids = JCBFilterHelper::translation((int) $type_extension[1], $type_extension[0])) !== null) else
{ {
$query->where($db->quoteName('a.id') . ' IN (' . implode(',', $ids) . ')'); // there is none
} $query->where($db->quoteName('a.id') . ' = ' . 0);
else }
{ }
// there is none
$query->where($db->quoteName('a.id') . ' = ' . 0); // Filtering "extension"
} $filter_extension = $this->state->get("filter.extension");
if ($filter_extension !== null && !empty($filter_extension))
{
// column name, and id
$type_extension = explode('__', $filter_extension);
if (($ids = JCBFilterHelper::translation((string) $type_extension[1], (string) $type_extension[0])) !== null)
{
$query->where($db->quoteName('a.id') . ' IN (' . implode(',', $ids) . ')');
}
else
{
// there is none
$query->where($db->quoteName('a.id') . ' = ' . 0);
} }
} }
// Implement View Level Access // Implement View Level Access

View File

@ -615,7 +615,7 @@ class LibraryModel extends AdminModel
/** /**
* Method to validate the form data. * Method to validate the form data.
* *
* @param JForm $form The form to validate against. * @param Form $form The form to validate against.
* @param array $data The data to validate. * @param array $data The data to validate.
* @param string $group The name of the field group to validate. * @param string $group The name of the field group to validate.
* *

View File

@ -28,6 +28,7 @@ use VDM\Joomla\Utilities\FormHelper as JCBFormHelper;
use VDM\Joomla\Utilities\ArrayHelper as UtilitiesArrayHelper; use VDM\Joomla\Utilities\ArrayHelper as UtilitiesArrayHelper;
use VDM\Joomla\Utilities\ObjectHelper; use VDM\Joomla\Utilities\ObjectHelper;
use VDM\Joomla\Utilities\StringHelper; use VDM\Joomla\Utilities\StringHelper;
use Joomla\CMS\Form\Form;
// No direct access to this file // No direct access to this file
\defined('_JEXEC') or die; \defined('_JEXEC') or die;
@ -107,7 +108,7 @@ class PowersModel extends ListModel
* @param array $data data * @param array $data data
* @param boolean $loadData load current data * @param boolean $loadData load current data
* *
* @return \JForm|boolean The \JForm object or false on error * @return Form|boolean The Form object or false on error
* *
* @since JCB 2.12.5 * @since JCB 2.12.5
*/ */

View File

@ -534,7 +534,7 @@ class ServerModel extends AdminModel
/** /**
* Method to validate the form data. * Method to validate the form data.
* *
* @param JForm $form The form to validate against. * @param Form $form The form to validate against.
* @param array $data The data to validate. * @param array $data The data to validate.
* @param string $group The name of the field group to validate. * @param string $group The name of the field group to validate.
* *

View File

@ -28,6 +28,7 @@ use VDM\Joomla\Componentbuilder\Utilities\FilterHelper as JCBFilterHelper;
use VDM\Joomla\Utilities\ArrayHelper as UtilitiesArrayHelper; use VDM\Joomla\Utilities\ArrayHelper as UtilitiesArrayHelper;
use VDM\Joomla\Utilities\ObjectHelper; use VDM\Joomla\Utilities\ObjectHelper;
use VDM\Joomla\Utilities\StringHelper; use VDM\Joomla\Utilities\StringHelper;
use Joomla\CMS\Form\Form;
// No direct access to this file // No direct access to this file
\defined('_JEXEC') or die; \defined('_JEXEC') or die;
@ -109,7 +110,7 @@ class Site_viewsModel extends ListModel
* @param array $data data * @param array $data data
* @param boolean $loadData load current data * @param boolean $loadData load current data
* *
* @return \JForm|boolean The \JForm object or false on error * @return Form|boolean The Form object or false on error
* *
* @since JCB 2.12.5 * @since JCB 2.12.5
*/ */

View File

@ -1,15 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="5.0" method="upgrade"> <extension type="component" version="5.0" method="upgrade">
<name>COM_COMPONENTBUILDER</name> <name>COM_COMPONENTBUILDER</name>
<creationDate>25th June, 2025</creationDate> <creationDate>1st July, 2025</creationDate>
<author>Llewellyn van der Merwe</author> <author>Llewellyn van der Merwe</author>
<authorEmail>joomla@vdm.io</authorEmail> <authorEmail>joomla@vdm.io</authorEmail>
<authorUrl>https://dev.vdm.io</authorUrl> <authorUrl>https://dev.vdm.io</authorUrl>
<copyright>Copyright (C) 2015 Vast Development Method. All rights reserved.</copyright> <copyright>Copyright (C) 2015 Vast Development Method. All rights reserved.</copyright>
<license>GNU General Public License version 2 or later; see LICENSE.txt</license> <license>GNU General Public License version 2 or later; see LICENSE.txt</license>
<version>5.1.1-beta5</version> <version>5.1.1-beta6</version>
<description><![CDATA[ <description><![CDATA[
<h1>Component Builder (v.5.1.1-beta5)</h1> <h1>Component Builder (v.5.1.1-beta6)</h1>
<div style="clear: both;"></div> <div style="clear: both;"></div>
<p>The Component Builder for [Joomla](https://extensions.joomla.org/extension/component-builder/) is highly advanced tool that is truly able to build extremely complex components in a fraction of the time. <p>The Component Builder for [Joomla](https://extensions.joomla.org/extension/component-builder/) is highly advanced tool that is truly able to build extremely complex components in a fraction of the time.

View File

@ -8,7 +8,7 @@
<version>3.2.5</version> <version>3.2.5</version>
<infourl title="Component Builder!">https://dev.vdm.io</infourl> <infourl title="Component Builder!">https://dev.vdm.io</infourl>
<downloads> <downloads>
<downloadurl type="full" format="zip">https://github.com/vdm-io/pkg-component-builder/archive/refs/tags/v3.2.5.zip</downloadurl> <downloadurl type="full" format="zip">https://github.com/joomengine/pkg-component-builder/archive/refs/tags/v3.2.5.zip</downloadurl>
</downloads> </downloads>
<tags> <tags>
<tag>stable</tag> <tag>stable</tag>
@ -26,7 +26,7 @@
<version>4.1.0</version> <version>4.1.0</version>
<infourl title="Component Builder!">https://dev.vdm.io</infourl> <infourl title="Component Builder!">https://dev.vdm.io</infourl>
<downloads> <downloads>
<downloadurl type="full" format="zip">https://github.com/vdm-io/pkg-component-builder/archive/refs/tags/v4.1.0.zip</downloadurl> <downloadurl type="full" format="zip">https://github.com/joomengine/pkg-component-builder/archive/refs/tags/v4.1.0.zip</downloadurl>
</downloads> </downloads>
<tags> <tags>
<tag>stable</tag> <tag>stable</tag>
@ -44,7 +44,7 @@
<version>5.0.0</version> <version>5.0.0</version>
<infourl title="Component Builder!">https://dev.vdm.io</infourl> <infourl title="Component Builder!">https://dev.vdm.io</infourl>
<downloads> <downloads>
<downloadurl type="full" format="zip">https://github.com/vdm-io/pkg-component-builder/archive/refs/tags/v5.0.0.zip</downloadurl> <downloadurl type="full" format="zip">https://github.com/joomengine/pkg-component-builder/archive/refs/tags/v5.0.0.zip</downloadurl>
</downloads> </downloads>
<tags> <tags>
<tag>stable</tag> <tag>stable</tag>
@ -62,7 +62,7 @@
<version>5.0.1</version> <version>5.0.1</version>
<infourl title="Component Builder!">https://dev.vdm.io</infourl> <infourl title="Component Builder!">https://dev.vdm.io</infourl>
<downloads> <downloads>
<downloadurl type="full" format="zip">https://github.com/vdm-io/pkg-component-builder/archive/refs/tags/v5.0.1.zip</downloadurl> <downloadurl type="full" format="zip">https://github.com/joomengine/pkg-component-builder/archive/refs/tags/v5.0.1.zip</downloadurl>
</downloads> </downloads>
<tags> <tags>
<tag>stable</tag> <tag>stable</tag>
@ -80,7 +80,7 @@
<version>5.0.2</version> <version>5.0.2</version>
<infourl title="Component Builder!">https://dev.vdm.io</infourl> <infourl title="Component Builder!">https://dev.vdm.io</infourl>
<downloads> <downloads>
<downloadurl type="full" format="zip">https://github.com/vdm-io/pkg-component-builder/archive/refs/tags/v5.0.2.zip</downloadurl> <downloadurl type="full" format="zip">https://github.com/joomengine/pkg-component-builder/archive/refs/tags/v5.0.2.zip</downloadurl>
</downloads> </downloads>
<tags> <tags>
<tag>stable</tag> <tag>stable</tag>
@ -98,7 +98,7 @@
<version>5.0.3</version> <version>5.0.3</version>
<infourl title="Component Builder!">https://dev.vdm.io</infourl> <infourl title="Component Builder!">https://dev.vdm.io</infourl>
<downloads> <downloads>
<downloadurl type="full" format="zip">https://github.com/vdm-io/pkg-component-builder/archive/refs/tags/v5.0.3.zip</downloadurl> <downloadurl type="full" format="zip">https://github.com/joomengine/pkg-component-builder/archive/refs/tags/v5.0.3.zip</downloadurl>
</downloads> </downloads>
<tags> <tags>
<tag>stable</tag> <tag>stable</tag>
@ -116,7 +116,7 @@
<version>5.1.0</version> <version>5.1.0</version>
<infourl title="Component Builder!">https://dev.vdm.io</infourl> <infourl title="Component Builder!">https://dev.vdm.io</infourl>
<downloads> <downloads>
<downloadurl type="full" format="zip">https://github.com/vdm-io/pkg-component-builder/archive/refs/tags/v5.1.0.zip</downloadurl> <downloadurl type="full" format="zip">https://github.com/joomengine/pkg-component-builder/archive/refs/tags/v5.1.0.zip</downloadurl>
</downloads> </downloads>
<tags> <tags>
<tag>stable</tag> <tag>stable</tag>
@ -134,7 +134,7 @@
<version>5.1.1-beta</version> <version>5.1.1-beta</version>
<infourl title="Component Builder!">https://dev.vdm.io</infourl> <infourl title="Component Builder!">https://dev.vdm.io</infourl>
<downloads> <downloads>
<downloadurl type="full" format="zip">https://github.com/vdm-io/pkg-component-builder/archive/refs/tags/v5.1.1-beta5.zip</downloadurl> <downloadurl type="full" format="zip">https://github.com/joomengine/pkg-component-builder/archive/refs/tags/v5.1.1-beta6.zip</downloadurl>
</downloads> </downloads>
<tags> <tags>
<tag>beta</tag> <tag>beta</tag>
@ -149,10 +149,10 @@
<element>pkg_component_builder</element> <element>pkg_component_builder</element>
<type>package</type> <type>package</type>
<client>site</client> <client>site</client>
<version>5.1.1-beta5</version> <version>5.1.1-beta6</version>
<infourl title="Component Builder!">https://dev.vdm.io</infourl> <infourl title="Component Builder!">https://dev.vdm.io</infourl>
<downloads> <downloads>
<downloadurl type="full" format="zip">https://github.com/vdm-io/pkg-component-builder/archive/refs/tags/v5.1.1-beta5.zip</downloadurl> <downloadurl type="full" format="zip">https://github.com/joomengine/pkg-component-builder/archive/refs/tags/v5.1.1-beta6.zip</downloadurl>
</downloads> </downloads>
<tags> <tags>
<tag>beta</tag> <tag>beta</tag>

View File

@ -29,6 +29,7 @@ use VDM\Joomla\Componentbuilder\Compiler\Utilities\Indent;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Line; use VDM\Joomla\Componentbuilder\Compiler\Utilities\Line;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Minify; use VDM\Joomla\Componentbuilder\Compiler\Utilities\Minify;
use VDM\Joomla\Componentbuilder\Compiler\Helper\Fields; use VDM\Joomla\Componentbuilder\Compiler\Helper\Fields;
use Joomla\CMS\Form\Form;
/** /**
@ -17415,7 +17416,7 @@ class Interpretation extends Fields
. " * Method to validate the form data."; . " * Method to validate the form data.";
$fix .= PHP_EOL . Indent::_(1) . " *"; $fix .= PHP_EOL . Indent::_(1) . " *";
$fix .= PHP_EOL . Indent::_(1) $fix .= PHP_EOL . Indent::_(1)
. " * @param JForm \$form The form to validate against."; . " * @param Form \$form The form to validate against.";
$fix .= PHP_EOL . Indent::_(1) $fix .= PHP_EOL . Indent::_(1)
. " * @param array \$data The data to validate."; . " * @param array \$data The data to validate.";
$fix .= PHP_EOL . Indent::_(1) $fix .= PHP_EOL . Indent::_(1)

View File

@ -25,6 +25,7 @@ use VDM\Joomla\Componentbuilder\Compiler\Builder\Tags;
use VDM\Joomla\Utilities\ArrayHelper; use VDM\Joomla\Utilities\ArrayHelper;
use VDM\Joomla\Utilities\StringHelper; use VDM\Joomla\Utilities\StringHelper;
use VDM\Joomla\Componentbuilder\Compiler\Interfaces\HeaderInterface; use VDM\Joomla\Componentbuilder\Compiler\Interfaces\HeaderInterface;
use Joomla\CMS\Form\FormHelper;
/** /**
@ -422,7 +423,7 @@ final class Header implements HeaderInterface
case 'form.custom.field': case 'form.custom.field':
$headers[] = 'use Joomla\CMS\HTML\HTMLHelper as Html;'; $headers[] = 'use Joomla\CMS\HTML\HTMLHelper as Html;';
$headers[] = "jimport('joomla.form.helper');"; $headers[] = "jimport('joomla.form.helper');";
$headers[] = "\JFormHelper::loadFieldClass('###JFORM_extends###');"; $headers[] = "FormHelper::loadFieldClass('###JFORM_extends###');";
break; break;
default: default:

View File

@ -78,7 +78,7 @@ You write clean, readable logic — and JCB ensures compatibility under the hood
MD; MD;
// What can be found here // What can be found here
$readme[] = '### What's in This Repository?'; $readme[] = '### What\'s in This Repository?';
$readme[] = <<<MD $readme[] = <<<MD
This repository contains a **index of Joomla Powers** to be used in a JCB instance. This repository contains a **index of Joomla Powers** to be used in a JCB instance.

View File

@ -241,7 +241,7 @@ class Table extends BaseTable implements TableInterface
'type' => 'TINYINT(1)', 'type' => 'TINYINT(1)',
'default' => '1', 'default' => '1',
'GUID' => '2089f202-667a-4fbd-881c-cc0fe1343ce4', 'GUID' => '2089f202-667a-4fbd-881c-cc0fe1343ce4',
'null_switch' => 'NOT NULL', 'null_switch' => 'NULL',
'unique_key' => false, 'unique_key' => false,
'key' => true, 'key' => true,
], ],
@ -10863,7 +10863,7 @@ class Table extends BaseTable implements TableInterface
'store' => 'json', 'store' => 'json',
'tab_name' => 'Details', 'tab_name' => 'Details',
'db' => [ 'db' => [
'type' => 'TEXT', 'type' => 'MEDIUMTEXT',
'default' => 'EMPTY', 'default' => 'EMPTY',
'GUID' => '36edbdce-b9b7-4b89-b2d9-03f91bb56019', 'GUID' => '36edbdce-b9b7-4b89-b2d9-03f91bb56019',
'null_switch' => 'NULL', 'null_switch' => 'NULL',

View File

@ -42,7 +42,7 @@ final class Delete extends Database implements DeleteInterface
} }
// get a query object // get a query object
$query = $this->db->getQuery(true); $query = $this->db->createQuery();
// start the conditions bucket // start the conditions bucket
$_conditions = []; $_conditions = [];

View File

@ -219,7 +219,7 @@ final class Insert extends Versioning implements InsertInterface
$this->historyGuid = []; $this->historyGuid = [];
// get a query object // get a query object
$query = $this->db->getQuery(true); $query = $this->db->createQuery();
$table = $this->getTable($table); $table = $this->getTable($table);
// set the query targets // set the query targets
@ -242,7 +242,7 @@ final class Insert extends Versioning implements InsertInterface
$limit = 300; $limit = 300;
// get a query object // get a query object
$query = $this->db->getQuery(true); $query = $this->db->createQuery();
// set the query targets // set the query targets
$query->insert($this->db->quoteName($table))->columns($this->db->quoteName(array_keys($columns))); $query->insert($this->db->quoteName($table))->columns($this->db->quoteName(array_keys($columns)));
@ -334,7 +334,7 @@ final class Insert extends Versioning implements InsertInterface
{ {
try try
{ {
$query = $this->db->getQuery(true) $query = $this->db->createQuery()
->select($this->db->quoteName('id')) ->select($this->db->quoteName('id'))
->from($this->db->quoteName($table)) ->from($this->db->quoteName($table))
->where( ->where(

View File

@ -330,7 +330,7 @@ final class Load extends Database implements LoadInterface
protected function query(array $select, array $tables, ?array $where = null, protected function query(array $select, array $tables, ?array $where = null,
?array $order = null, ?int $limit = null): ?object ?array $order = null, ?int $limit = null): ?object
{ {
$query = $this->db->getQuery(true); $query = $this->db->createQuery();
$this->applySelect($query, $select); $this->applySelect($query, $select);
$this->applyFromAndJoins($query, $tables); $this->applyFromAndJoins($query, $tables);

View File

@ -167,7 +167,7 @@ final class Update extends Versioning implements UpdateInterface
$table = $this->getTable($table); $table = $this->getTable($table);
// get a query object // get a query object
$query = $this->db->getQuery(true); $query = $this->db->createQuery();
// set the query targets // set the query targets
$query->update($this->db->quoteName($table)); $query->update($this->db->quoteName($table));
@ -270,7 +270,7 @@ final class Update extends Versioning implements UpdateInterface
} }
// Get a query object // Get a query object
$query = $this->db->getQuery(true); $query = $this->db->createQuery();
// Prepare the update statement // Prepare the update statement
$query->update($this->db->quoteName($this->getTable($table))) $query->update($this->db->quoteName($this->getTable($table)))
@ -317,7 +317,7 @@ final class Update extends Versioning implements UpdateInterface
try try
{ {
$query = $this->db->getQuery(true) $query = $this->db->createQuery()
->select($this->db->quoteName('id')) ->select($this->db->quoteName('id'))
->from($this->db->quoteName($table)) ->from($this->db->quoteName($table))
->where($this->db->quoteName('guid') . ' = ' . $this->quote($guid)); ->where($this->db->quoteName('guid') . ' = ' . $this->quote($guid));

View File

@ -87,12 +87,12 @@ abstract class StringHelper
{ {
// Safely escape output for HTML // Safely escape output for HTML
$title = self::shorten($string, 400 , false); $title = self::shorten($string, 400 , false);
$escapedTitle = htmlspecialchars($title, ENT_QUOTES, 'UTF-8');
$escapedShort = htmlspecialchars($shortened, ENT_QUOTES, 'UTF-8');
return '<span class="hasTip" title="' . $escapedTitle . '" style="cursor:help">' return sprintf(
. $escapedShort '<span class="hasTip" title="%s" style="cursor:help">%s</span>',
. '</span>'; htmlspecialchars($title, ENT_QUOTES, 'UTF-8'),
htmlspecialchars($shortened, ENT_QUOTES, 'UTF-8')
);
} }
// Return shortened version without tooltip // Return shortened version without tooltip