Release of v3.2.1-rc1
Improved the Schema Table update engine (more). Fix autoloader timing, and loading. Implement the Joomla Powers in JCB code, to move away from JClasses.
This commit is contained in:
@ -486,56 +486,52 @@ abstract class Schema implements SchemaInterface
|
||||
*
|
||||
* This function checks if there's a significant difference between the current
|
||||
* data type and the expected data type that would require updating the database schema.
|
||||
* It ignores size and other modifiers for certain data types where MySQL considers
|
||||
* these attributes irrelevant for storage.
|
||||
* It ignores display width for numeric types where MySQL considers these attributes
|
||||
* irrelevant for storage but considers size and other modifiers for types like VARCHAR.
|
||||
*
|
||||
* @param string $currentType The current data type from the database schema.
|
||||
* @param string $expectedType The expected data type to validate against.
|
||||
* @param string $currentType The current data type from the database schema.
|
||||
* @param string $expectedType The expected data type to validate against.
|
||||
*
|
||||
* @return bool Returns true if the data type change is significant, otherwise false.
|
||||
* @return bool Returns true if the data type change is significant, otherwise false.
|
||||
* @since 3.2.1
|
||||
*/
|
||||
function isDataTypeChangeSignificant(string $currentType, string $expectedType): bool
|
||||
protected function isDataTypeChangeSignificant(string $currentType, string $expectedType): bool
|
||||
{
|
||||
// we only do this for Joomla 4+
|
||||
if ($this->currentVersion != 3)
|
||||
// Normalize both input types to lowercase for case-insensitive comparison
|
||||
$currentType = strtolower($currentType);
|
||||
$expectedType = strtolower($expectedType);
|
||||
|
||||
// Regex to extract the base data type and numeric parameters with named groups
|
||||
$typePattern = '/^(?<datatype>\w+)(\((?<params>\d+(,\d+)?)\))?/';
|
||||
|
||||
// Match types and parameters
|
||||
preg_match($typePattern, $currentType, $currentMatches);
|
||||
preg_match($typePattern, $expectedType, $expectedMatches);
|
||||
|
||||
// Compare base types
|
||||
if ($currentMatches['datatype'] !== $expectedMatches['datatype'])
|
||||
{
|
||||
// Normalize both input types to lowercase for case-insensitive comparison
|
||||
$currentType = strtolower($currentType);
|
||||
$expectedType = strtolower($expectedType);
|
||||
|
||||
// Define types where size or other modifiers are irrelevant
|
||||
$sizeIrrelevantTypes = [
|
||||
'int', 'tinyint', 'smallint', 'mediumint', 'bigint', // Standard integer types
|
||||
'int unsigned', 'tinyint unsigned', 'smallint unsigned', 'mediumint unsigned', 'bigint unsigned', // Unsigned integer types
|
||||
];
|
||||
|
||||
// Check if the type involves size-irrelevant types
|
||||
foreach ($sizeIrrelevantTypes as $type)
|
||||
{
|
||||
if (strpos($expectedType, $type) !== false)
|
||||
{
|
||||
// Remove any numeric sizes and modifiers for comparison
|
||||
$pattern = '/\(\d+\)|unsigned|\s*/';
|
||||
$cleanCurrentType = preg_replace($pattern, '', $currentType);
|
||||
$cleanExpectedType = preg_replace($pattern, '', $expectedType);
|
||||
|
||||
// Compare the cleaned types
|
||||
if ($cleanCurrentType === $cleanExpectedType)
|
||||
{
|
||||
return false; // No significant change
|
||||
}
|
||||
}
|
||||
}
|
||||
return true; // Base types differ
|
||||
}
|
||||
|
||||
// Perform a standard case-insensitive comparison for other types
|
||||
if (strcasecmp($currentType, $expectedType) == 0)
|
||||
// Define types where size and other modifiers are irrelevant
|
||||
$sizeIrrelevantTypes = [
|
||||
'int', 'tinyint', 'smallint', 'mediumint', 'bigint',
|
||||
'float', 'double', 'decimal', 'numeric' // Numeric types where display width is irrelevant
|
||||
];
|
||||
|
||||
// If the type is not in the size irrelevant list, compare full definitions
|
||||
if (!in_array($currentMatches['datatype'], $sizeIrrelevantTypes))
|
||||
{
|
||||
return false; // No significant change
|
||||
return $currentType !== $expectedType; // Use full definition for types where size matters
|
||||
}
|
||||
|
||||
return true; // Significant datatype change detected
|
||||
// For size irrelevant types, only compare base type, ignoring size and unsigned
|
||||
$currentBaseType = preg_replace('/\(\d+(,\d+)?\)|unsigned/', '', $currentType);
|
||||
$expectedBaseType = preg_replace('/\(\d+(,\d+)?\)|unsigned/', '', $expectedType);
|
||||
|
||||
// Perform a final comparison for numeric types ignoring size
|
||||
return $currentBaseType !== $expectedBaseType;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -293,6 +293,24 @@ class Config extends BaseConfig
|
||||
return strlen((string) $this->component_code_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* get component autoloader path
|
||||
*
|
||||
* @return string The component autoloader path
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function getComponentautoloaderpath(): string
|
||||
{
|
||||
if ($this->joomla_version == 3)
|
||||
{
|
||||
return 'helpers/powerloader.php';
|
||||
}
|
||||
else
|
||||
{
|
||||
return 'src/Helper/PowerloaderHelper.php';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get add namespace prefix
|
||||
*
|
||||
@ -636,9 +654,12 @@ class Config extends BaseConfig
|
||||
return [
|
||||
'jjt' => 'Joomla' . '.JText._(',
|
||||
'js' => 'Text:' . ':script(',
|
||||
't' => 'Text:' . ':_(', // namespace and J version will be found
|
||||
't' => 'Text:' . ':_(', // namespace and J version will be found
|
||||
'ts' => 'Text:' . ':sprintf(', // namespace and J version will be found
|
||||
'jt' => 'JustTEXT:' . ':_('
|
||||
'jt' => 'JustTEXT:' . ':_(',
|
||||
'spjs' => 'Joomla__' . '_ba6326ef_cb79_4348_80f4_ab086082e3c5___Power:' . ':script(', // the joomla power version
|
||||
'spt' => 'Joomla__' . '_ba6326ef_cb79_4348_80f4_ab086082e3c5___Power:' . ':_(', // the joomla power version
|
||||
'spts' => 'Joomla__' . '_ba6326ef_cb79_4348_80f4_ab086082e3c5___Power:' . ':sprintf(' // the joomla power version
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -546,10 +546,14 @@ final class CustomFieldTypeFile
|
||||
if ($this->config->get('joomla_version', 3) != 3)
|
||||
{
|
||||
$placeholders['JFactory::getUser()'] = 'Factory::getApplication()->getIdentity()';
|
||||
$placeholders['\JFactory::getUser()'] = 'Factory::getApplication()->getIdentity()';
|
||||
$placeholders['Factory::getUser()'] = 'Factory::getApplication()->getIdentity()';
|
||||
$placeholders['JFactory::'] = 'Factory::';
|
||||
$placeholders['\JFactory::'] = 'Factory::';
|
||||
$placeholders['JHtml::'] = 'Html::';
|
||||
$placeholders['\JHtml::'] = 'Html::';
|
||||
$placeholders['JText::'] = 'Text::';
|
||||
$placeholders['\JText::'] = 'Text::';
|
||||
$placeholders['JComponentHelper::'] = 'ComponentHelper::';
|
||||
$placeholders['\JComponentHelper::'] = 'ComponentHelper::';
|
||||
}
|
||||
|
@ -405,7 +405,7 @@ class Compiler extends Infusion
|
||||
{
|
||||
CFactory::_('Power')->load($super_powers);
|
||||
}
|
||||
// set the autoloader for Powers (second time)
|
||||
// set the autoloader for Powers
|
||||
CFactory::_('Power.Autoloader')->set();
|
||||
// get the bom file
|
||||
$bom = FileHelper::getContent(CFactory::_('Config')->bom_path);
|
||||
|
@ -2149,8 +2149,8 @@ class Infusion extends Interpretation
|
||||
CFactory::_('Compiler.Builder.Component.Fields')->varExport(null, 1)
|
||||
);
|
||||
|
||||
// set the autoloader for Powers (first time)
|
||||
CFactory::_('Power.Autoloader')->set();
|
||||
// set the autoloader for Powers
|
||||
CFactory::_('Power.Autoloader')->setFiles();
|
||||
|
||||
// tweak system to set stuff to the module domain
|
||||
$_backup_target = CFactory::_('Config')->build_target;
|
||||
|
@ -147,7 +147,9 @@ class Extractor
|
||||
}
|
||||
}
|
||||
// now get the JText: :script()
|
||||
if (in_array('JText:' . ':script(', $lang_string_targets) || in_array('Text:' . ':script(', $lang_string_targets))
|
||||
if (in_array('JText:' . ':script(', $lang_string_targets)
|
||||
|| in_array('Text:' . ':script(', $lang_string_targets)
|
||||
|| in_array('Joomla__' . '_ba6326ef_cb79_4348_80f4_ab086082e3c5___Power:' . ':script(', $lang_string_targets))
|
||||
{
|
||||
$sc_text[] = GetHelper::allBetween(
|
||||
$content, "JText:" . ":script('", "'"
|
||||
@ -161,6 +163,12 @@ class Extractor
|
||||
$sc_text[] = GetHelper::allBetween(
|
||||
$content, 'Text:' . ':script("', '"'
|
||||
);
|
||||
$sc_text[] = GetHelper::allBetween(
|
||||
$content, "Joomla__" ."_ba6326ef_cb79_4348_80f4_ab086082e3c5___Power:" . ":script('", "'"
|
||||
);
|
||||
$sc_text[] = GetHelper::allBetween(
|
||||
$content, 'Joomla__' . '_ba6326ef_cb79_4348_80f4_ab086082e3c5___Power:' . ':script("', '"'
|
||||
);
|
||||
// combine into one array
|
||||
$sc_text = ArrayHelper::merge($sc_text);
|
||||
// we need to add a check to insure these JavaScript lang matchup
|
||||
@ -192,6 +200,7 @@ class Extractor
|
||||
if ($lang_string_target === 'Joomla' . '.JText._('
|
||||
|| $lang_string_target === 'JText:' . ':script('
|
||||
|| $lang_string_target === 'Text:' . ':script('
|
||||
|| $lang_string_target === 'Joomla__' . '_ba6326ef_cb79_4348_80f4_ab086082e3c5___Power:' . ':script('
|
||||
|| $lang_string_target === 'JustTEXT:' . ':_(')
|
||||
{
|
||||
continue;
|
||||
|
@ -77,7 +77,27 @@ class Autoloader
|
||||
// reset all autoloaders power placeholders
|
||||
$this->content->set('ADMIN_POWER_HELPER', '');
|
||||
$this->content->set('SITE_POWER_HELPER', '');
|
||||
$this->content->set('PLUGIN_POWER_AUTOLOADER', '');
|
||||
$this->content->set('CUSTOM_POWER_AUTOLOADER', '');
|
||||
$this->content->set('SITE_PLUGIN_POWER_AUTOLOADER', '');
|
||||
$this->content->set('SITE_CUSTOM_POWER_AUTOLOADER', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the autoloader into the active content array
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function setFiles()
|
||||
{
|
||||
// check if we are using a plugin
|
||||
$this->content->set('PLUGIN_POWER_AUTOLOADER', PHP_EOL . PHP_EOL . $this->getAutoloaderFile(2));
|
||||
$this->content->set('SITE_PLUGIN_POWER_AUTOLOADER', PHP_EOL . PHP_EOL . $this->getAutoloaderFile(2, 'JPATH_SITE'));
|
||||
|
||||
// to add to custom files
|
||||
$this->content->add('CUSTOM_POWER_AUTOLOADER', $this->getAutoloaderFile(0));
|
||||
$this->content->add('SITE_CUSTOM_POWER_AUTOLOADER', $this->getAutoloaderFile(0, 'JPATH_SITE'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -89,9 +109,9 @@ class Autoloader
|
||||
public function set()
|
||||
{
|
||||
// make sure we only load this once
|
||||
if (ArrayHelper::check($this->power->namespace) && !$this->content->isString('CUSTOM_POWER_AUTOLOADER'))
|
||||
if (ArrayHelper::check($this->power->namespace) && !$this->content->isString('ADMIN_POWER_HELPER'))
|
||||
{
|
||||
/************************* IMPORTANT SORT NOTICE ***********************************************
|
||||
/* ********************** IMPORTANT SORT NOTICE *****************************************
|
||||
* make sure the name space values are sorted from the longest string to the shortest
|
||||
* so that the search do not mistakenly match a shorter namespace before a longer one
|
||||
* that has the same short namespace for example:
|
||||
@ -102,110 +122,18 @@ class Autoloader
|
||||
* ^^^^^^^^^^^^^^^^^^^^^^
|
||||
* NameSpace\SubName\SubSubName\ClassName
|
||||
* ^^^^^^^^^^^^^^^^^^^^^^
|
||||
***********************************************************************************************/
|
||||
** *********************************************************************************************/
|
||||
|
||||
uksort($this->power->namespace, fn($a, $b) => strlen((string) $b) - strlen((string) $a));
|
||||
|
||||
// check if we are using a plugin
|
||||
if ($this->loadPluginAutoloader())
|
||||
{
|
||||
$this->content->set('PLUGIN_POWER_AUTOLOADER', $this->getPluginAutoloader());
|
||||
}
|
||||
// load to admin helper class
|
||||
$this->content->add('ADMIN_POWER_HELPER', $this->getHelperAutoloader());
|
||||
|
||||
// load to the helper class
|
||||
if ($this->loadHelperAutoloader())
|
||||
{
|
||||
// load to admin helper class
|
||||
$this->content->add('ADMIN_POWER_HELPER', $this->getHelperAutoloader());
|
||||
|
||||
// load to site helper class if needed
|
||||
if ($this->loadSiteAutoloader())
|
||||
{
|
||||
$this->content->add('SITE_POWER_HELPER', $this->getHelperAutoloader());
|
||||
}
|
||||
}
|
||||
|
||||
// to add to custom files
|
||||
$this->content->add('CUSTOM_POWER_AUTOLOADER', $this->getHelperAutoloader());
|
||||
// load to site helper class if needed
|
||||
$this->content->add('SITE_POWER_HELPER', $this->getHelperAutoloader());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should we load the plugin autoloader
|
||||
*
|
||||
* @return bool
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function loadPluginAutoloader(): bool
|
||||
{
|
||||
return $this->content->exists('PLUGIN_POWER_AUTOLOADER');
|
||||
}
|
||||
|
||||
/**
|
||||
* Should we load the helper class autoloader
|
||||
*
|
||||
* @return bool
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function loadHelperAutoloader(): bool
|
||||
{
|
||||
// for now we load it if the plugin is not loaded
|
||||
// but we may want to add a switch that
|
||||
// controls this behaviour.
|
||||
// return !$this->loadPluginAutoloader();
|
||||
// lets load it anyway (can't break anything)
|
||||
// but we will still like a switch for this
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should we load the autoloader in site area
|
||||
*
|
||||
* @return bool
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function loadSiteAutoloader(): bool
|
||||
{
|
||||
return (!$this->config->remove_site_folder || !$this->config->remove_site_edit_folder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get helper autoloader code
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function getPluginAutoloader(): string
|
||||
{
|
||||
// load the code
|
||||
$code = [];
|
||||
|
||||
// if we should not load in the site are
|
||||
if (($script = $this->getBLockSiteLoading()) !== null)
|
||||
{
|
||||
$code[] = $script;
|
||||
}
|
||||
|
||||
// add the composer stuff here
|
||||
if (($script = $this->getComposer(2)) !== null)
|
||||
{
|
||||
$code[] = $script;
|
||||
}
|
||||
|
||||
// get the helper autoloader
|
||||
if (($script = $this->getAutoloader(2)) !== null)
|
||||
{
|
||||
$code[] = $script;
|
||||
}
|
||||
|
||||
// if we have any
|
||||
if (!empty($code))
|
||||
{
|
||||
return PHP_EOL . PHP_EOL . implode(PHP_EOL . PHP_EOL, $code);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get helper autoloader code
|
||||
*
|
||||
@ -245,30 +173,29 @@ class Autoloader
|
||||
}
|
||||
|
||||
/**
|
||||
* Get code that will block the plugin from loading
|
||||
* the autoloader in the site area
|
||||
* Get autoloader file
|
||||
*
|
||||
* @param int $tabSpace The dynamic tab spacer
|
||||
* @param string $area The target area
|
||||
*
|
||||
* @return string|null
|
||||
* @since 3.2.0
|
||||
* @since 3.2.1
|
||||
*/
|
||||
private function getBLockSiteLoading(): ?string
|
||||
private function getAutoloaderFile(int $tabSpace, string $area = 'JPATH_ADMINISTRATOR'): ?string
|
||||
{
|
||||
// if we should not load in the site are
|
||||
if (!$this->loadSiteAutoloader())
|
||||
{
|
||||
// we add code to prevent this plugin from triggering on the site area
|
||||
$not_site = [];
|
||||
$not_site[] = Indent::_(2) . '//'
|
||||
. Line::_(__Line__, __Class__) . ' do not run the autoloader in the site area';
|
||||
$not_site[] = Indent::_(2) . 'if ($this->app->isClient(\'site\'))';
|
||||
$not_site[] = Indent::_(2) . '{';
|
||||
$not_site[] = Indent::_(3) . 'return;';
|
||||
$not_site[] = Indent::_(2) . '}';
|
||||
// we start building the autoloaded file loader
|
||||
$autoload_file = [];
|
||||
$autoload_file[] = Indent::_($tabSpace) . '//'
|
||||
. Line::_(__Line__, __Class__) . " The power autoloader for this project ($area) area.";
|
||||
$autoload_file[] = Indent::_($tabSpace) . "\$power_autoloader = $area . '/components/com_"
|
||||
. $this->config->get('component_code_name', 'ERROR') . '/'
|
||||
. $this->config->get('component_autoloader_path', 'ERROR') . "';";
|
||||
$autoload_file[] = Indent::_($tabSpace) . 'if (file_exists($power_autoloader))';
|
||||
$autoload_file[] = Indent::_($tabSpace) . '{';
|
||||
$autoload_file[] = Indent::_($tabSpace) . Indent::_(1) . 'require_once $power_autoloader;';
|
||||
$autoload_file[] = Indent::_($tabSpace) . '}';
|
||||
|
||||
return implode(PHP_EOL, $not_site);
|
||||
}
|
||||
|
||||
return null;
|
||||
return implode(PHP_EOL, $autoload_file);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -287,7 +214,7 @@ class Autoloader
|
||||
$autoload_method = [];
|
||||
$autoload_method[] = Indent::_($tabSpace) . '//'
|
||||
. Line::_(__Line__, __Class__) . ' register additional namespace';
|
||||
$autoload_method[] = Indent::_($tabSpace) . '\spl_autoload_register(function ($class) {';
|
||||
$autoload_method[] = Indent::_($tabSpace) . 'spl_autoload_register(function ($class) {';
|
||||
$autoload_method[] = Indent::_($tabSpace) . Indent::_(1) . '//'
|
||||
. Line::_(__Line__, __Class__) . ' project-specific base directories and namespace prefix';
|
||||
$autoload_method[] = Indent::_($tabSpace) . Indent::_(1) . '$search = [';
|
||||
|
@ -158,28 +158,38 @@ class Data
|
||||
// check if layout keys were passed
|
||||
if (!ArrayHelper::check($layouts))
|
||||
{
|
||||
$layout_bucket = [];
|
||||
// set the Layout data
|
||||
$lay1 = GetHelper::allBetween(
|
||||
if (($layouts_found = GetHelper::allBetween(
|
||||
$content, "LayoutHelper::render('", "',"
|
||||
);
|
||||
$lay2 = GetHelper::allBetween(
|
||||
$content, 'LayoutHelper::render("', '",'
|
||||
);
|
||||
if (ArrayHelper::check($lay1)
|
||||
&& ArrayHelper::check($lay2))
|
||||
)) !== null)
|
||||
{
|
||||
$layouts = array_merge($lay1, $lay2);
|
||||
$layout_bucket[] = $layouts_found;
|
||||
}
|
||||
else
|
||||
if (($layouts_found = GetHelper::allBetween(
|
||||
$content, 'LayoutHelper::render("', '",'
|
||||
)) !== null)
|
||||
{
|
||||
if (ArrayHelper::check($lay1))
|
||||
{
|
||||
$layouts = $lay1;
|
||||
}
|
||||
elseif (ArrayHelper::check($lay2))
|
||||
{
|
||||
$layouts = $lay2;
|
||||
}
|
||||
$layout_bucket[] = $layouts_found;
|
||||
}
|
||||
// set the Layout data
|
||||
if (($layouts_found = GetHelper::allBetween(
|
||||
$content, "Joomla__" . "_7ab82272_0b3d_4bb1_af35_e63a096cfe0b___Power::render('", "',"
|
||||
)) !== null)
|
||||
{
|
||||
$layout_bucket[] = $layouts_found;
|
||||
}
|
||||
if (($layouts_found = GetHelper::allBetween(
|
||||
$content, 'Joomla__' . '_7ab82272_0b3d_4bb1_af35_e63a096cfe0b___Power::render("', '",'
|
||||
)) !== null)
|
||||
{
|
||||
$layout_bucket[] = $layouts_found;
|
||||
}
|
||||
|
||||
// Flatten and merge all collected layouts if any
|
||||
if ($layout_bucket !== [])
|
||||
{
|
||||
$layouts = array_merge($layouts, ...$layout_bucket);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user