While using the back-end installer to update from J3.3.6 to 3.4, both front and back-ends now show the following error:
Fatal error: Call to undefined method JLoader::applyAliasFor() in .../public/libraries/ClassLoader.php on line 45
All extensions were fully updated prior to the Joomla update attempt, and the update procedure went directly to the error message
It appears that I am not the only updater with this result:
http://forum.joomla.org/viewtopic.php?f=707&t=874775&p=3272296#p3271767
Our LAMP server is Centos 5.11, running php 5.4.36, mysql 5.5.40 & apache 2.2.3.
Labels |
Added:
?
|
It's a new file in 3.4 - https://github.com/joomla/joomla-cms/blob/staging/libraries/ClassLoader.php
If relevant, the site was originally developed under an early J2.5.x, and migrated to J3.3.0 I believe, about three months ago. It has since been updated two or three times to reach 3.3.6 without issues.
I do have Akeeba extensions installed (one of which was updated just prior to my running the J update), but this error is pointing to a Joomla file, as mbabker mentioned. The contents of the file within the error are below, and I'm guessing that the other poster simply found the wrong ClassLoader file.
<?php
/**
namespace Composer\Autoload;
defined('_JEXEC') or die;
// We have to manually require the base ClassLoader as the autoloader isn't loaded yet, but only if it doesn't exist
if (!class_exists('Composer\Autoload\ClassLoader'))
{
require_once DIR . '/vendor/composer/ClassLoader.php';
}
/**
@since 3.4
/
class ClassLoaderJoomla extends ClassLoader
{
/*
@since 3.4
*/
public function loadClass($class)
{
if ($file = $this->findFile($class))
{
includeFile($file);
\JLoader::applyAliasFor($class);
return true;
}
}
}
I now see where you found Nicholas' name in the file, but it still appears to be a Joomla-produced file where, perhaps Nicholas contributed some of the code.
@mbabker Thanks, I overlooked the ClassLoader.php file when I opened up the 3.4 ZIP on my end (I had directories sorted in descending order and my eyes stopped when I saw loader.php file).
In that case though, since it doesn't seem like it would have anything to do with having an Akeeba product installed, I wonder what the issue would be in this case?
@LTIOfficial Can you confirm whether or not the loader.php file on your end contains the applyAliasFor() function? (It should be listed on line 534 of the file...if it's not there, then it would indicate you still have the 3.3.6 version of the file on your site...if it is there, then it might indicate that this is more of a coding issue).
Line 534 shows:
protected function __construct () {
clearstatcache();
if (is_readable(_JALOADER_CLASS_CACHE) AND filemtime(_JALOADER_CLASS_CACHE) > (time() - 3600*24)) $this->discovered = unserialize(file_get_contents (_JALOADER_CLASS_CACHE));
}
And the top of the file includes the following, implying that it is an older version of the file.
@copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
On another note, the server shows it with today's date, at the time I performed the update attempt. All other updated files show Feb 24th as their date.
Another note: This loader file is twice the size of the one in the J3.4 upgrade download tar. It's contents are below:
<?php
/**
// Jaliro version, modified from Joomla 2.5
// CMS independent check to prevent direct execution
if (basename(@$SERVER['REQUEST_URI']) == basename(__FILE_)) die ('This software is for use within a larger system');
if (!function_exists('version_compare') OR version_compare(phpversion(), '5.2.3', '<')) {
die('Jaliro requires at least PHP 5.2.3');
}
if(!defined('DS')) define( 'DS', DIRECTORY_SEPARATOR );
if(!defined('_CMSAPI_CMS_BASE')) define ('_CMSAPI_CMS_BASE', 'Joomla');
if(!defined('_CMSAPI_ABSOLUTE_PATH')) define ('_CMSAPI_ABSOLUTE_PATH', JPATH_SITE);
if (!defined('_CMSAPI_CHARSET')) define ('_CMSAPI_CHARSET', 'utf-8');
if ('utf-8' == _CMSAPI_CHARSET) define ('_CMSAPI_LANGFILE', 'language-utf/');
else define ('_CMSAPI_LANGFILE', 'language/');
if (file_exists(_CMSAPI_ABSOLUTE_PATH.'/libraries/cms/version/version.php')) {
define('_CMSAPI_JOOMLA_VERSION', '2.5');
define ('_CMSAPI_PARAMETER_CLASS', 'JForm');
}
elseif (file_exists(_CMSAPI_ABSOLUTE_PATH.'/libraries/joomla/version.php')) {
define('_CMSAPI_JOOMLA_VERSION', '1.5');
define ('_CMSAPI_PARAMETER_CLASS', 'JParameter');
}
else {
define('_CMSAPI_JOOMLA_VERSION', '1.0');
define ('_CMSAPI_PARAMETER_CLASS', 'JParameter');
}
// Aliro definitions that are set dynamically
// Needs more work to be dynamic in Joomla
define ('_ALIRO_IS_ADMIN', 0);
define ('_ALIRO_SITE_BASE', _CMSAPI_ABSOLUTE_PATH);
define ('_ALIRO_ABSOLUTE_PATH', _CMSAPI_ABSOLUTE_PATH);
// Standard definitions for Aliro
// define ('_ALIRO_CLASS_BASE', '/var/www/OutsideDocRoot');
DEFINE('ALIRO_REGEXP_URL','/(https?|ftps?):\/\/[a-zA-Z0-9-.]+.[a-zA-Z]{2,3}(:[a-zA-Z0-9]*)?\/?([a-zA-Z0-9-.\?\,\'\/\+&%\$#\=~])[^.\,)(\s]/');
DEFINE('ALIRO_REGEXP_IP','/(https?|ftps?):\/\/\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}\/?([a-zA-Z0-9-.\?\,\'\/\+&%\$#\=~])[^.\,)(\s]/');
// Define the class to handle storage of cached data, must inherit from aliroCacheStorage
define ('_ALIRO_CACHE_HANDLER', 'aliroCacheDiskStorage');
// Define values for login validation results
define ('_ALIRO_LOGIN_GOOD', 0);
define ('_ALIRO_LOGIN_FAILED', 1);
define ('_ALIRO_LOGIN_PROHIBITED', 2);
// Allows extensions written for Joomla 1.5+ to run
//define ('_JEXEC', 1);
//define ('JPATH_BASE', _ALIRO_ABSOLUTE_PATH);
//define ('DS', '/');
// Used with the getParam method of aliroAbstractRequest
if (!defined('_MOS_NOTRIM')) define( '_MOS_NOTRIM', 0x0001 ); // prevent getParam trimming input
if (!defined('_MOS_ALLOWHTML')) define( '_MOS_ALLOWHTML', 0x0002 ); // cause getParam to allow HTML - purified on user side
if (!defined('_MOS_ALLOWRAW')) define( '_MOS_ALLOWRAW', 0x0004 ); // suppresses forcing of integer if default is numeric
if (!defined('_MOS_NOSTRIP')) define( '_MOS_NOSTRIP', 0x0008 ); // suppress stripping of magic quotes
// Aliro error levels
if (!defined('_ALIRO_ERROR_INFORM')) define ('_ALIRO_ERROR_INFORM', 0);
if (!defined('_ALIRO_ERROR_WARN')) define ('_ALIRO_ERROR_WARN', 1);
if (!defined('_ALIRO_ERROR_SEVERE')) define ('_ALIRO_ERROR_SEVERE', 2);
if (!defined('_ALIRO_ERROR_FATAL')) define ('_ALIRO_ERROR_FATAL', 3);
// Aliro cache parameters
if (!defined('_ALIRO_HTML_CACHE_TIME_LIMIT')) define('_ALIRO_HTML_CACHE_TIME_LIMIT', 600);
if (!defined('_ALIRO_HTML_CACHE_SIZE_LIMIT')) define('_ALIRO_HTML_CACHE_SIZE_LIMIT', 100000);
if (!defined('_ALIRO_OBJECT_CACHE_TIME_LIMIT')) define('_ALIRO_OBJECT_CACHE_TIME_LIMIT', 600);
if (!defined('_ALIRO_OBJECT_CACHE_SIZE_LIMIT')) define('_ALIRO_OBJECT_CACHE_SIZE_LIMIT', 100000);
// Aliro parameter fetching parameters
if (!defined('_MOS_NOTRIM')) define( '_MOS_NOTRIM', 0x0001 ); // prevent getParam trimming input
if (!defined('_MOS_ALLOWHTML')) define( '_MOS_ALLOWHTML', 0x0002 ); // cause getParam to allow HTML - purified on user side
if (!defined('_MOS_ALLOWRAW')) define( '_MOS_ALLOWRAW', 0x0004 ); // suppresses forcing of integer if default is numeric
// Aliro form checking mechanism
if (!defined('_ALIRO_FORM_CHECK_OK')) define ('_ALIRO_FORM_CHECK_OK', 0);
if (!defined('_ALIRO_FORM_CHECK_REPEAT')) define ('_ALIRO_FORM_CHECK_REPEAT', 1);
if (!defined('_ALIRO_FORM_CHECK_FAIL')) define ('_ALIRO_FORM_CHECK_FAIL', 2);
if (!defined('_ALIRO_FORM_CHECK_NULL')) define ('_ALIRO_FORM_CHECK_NULL', 3);
if (!defined('_ALIRO_FORM_CHECK_EXPIRED')) define ('_ALIRO_FORM_CHECK_EXPIRED', 4);
// Database error conditions
define ('_ALIRO_DB_NO_INTERFACE', 1);
define ('_ALIRO_DB_CONNECT_FAILED', 2);
define ('_ALIRO_USER_SIDE', 1);
define ('_ALIRO_ADMIN_SIDE', 2);
// Menu options
define ('_ALIRO_SHOW_NO_SUBMENUS', 0);
define ('_ALIRO_SHOW_ACTIVE_SUBMENUS', 1);
define ('_ALIRO_SHOW_ALL_SUBMENUS', 2);
// Default user side page size
DEFINE ('_ALIRO_PAGE_NAV_DISPLAY_PAGES', 10);
define ('_ALIRO_SEF_MAX_CACHE_SIZE', 500000);
define ('_ALIRO_SEF_MAX_CACHE_TIME', 3600);
define ('_ALIRO_AUTHORISER_SESSION_CACHE_TIME', 600);
define ('_ALIRO_DATABASE_CACHE_TIME', 3600);
// How long to keep records of material checked for spam
define ('_ALIRO_KEEP_DAYS_OF_SPAM', 7);
// Location for class location cache
define ('_JALOADER_CLASS_CACHE', _CMSAPI_ABSOLUTE_PATH.'/cache/jaliroclasses');
interface ifAliroModule {
public function activate ($module, &$content, $area, $params);
}
interface ifAliroTemplate {
public static function defaultModulePosition ();
public function positions ();
public function render ();
}
interface ifAliroMainTemplate {
public static function defaultModulePosition ();
public function positions ();
public function render ();
public function component_render ();
}
interface ifAliroLocalTemplate {
public static function defaultModulePosition ();
public function positions ();
public function render ();
}
interface ifTemplateRenderer {
public function display ($template='');
public function fetch ($template='');
public function getengine ();
public function addvar ($key, $value);
public function addbyref ($key, &$value);
public function getvars ($name);
public function setdir ($dir);
public function settemplate ($template);
}
class jaliro {
public static $version = '1.4.4';
// Doesn't presently do anything except contain the version number
// Version MUST be changed if new library contents are to overwrite existing
public static function trace ($error=true, $useHTML=true) {
static $counter = 0;
$html = '';
$newline = $useHTML ? '<br />' : "\n";
foreach(debug_backtrace() as $back) {
if (isset($back['file']) AND $back['file']) {
$html .= $newline.$back['file'].':'.$back['line'];
}
}
if ($error) $counter++;
if (1000 < $counter) {
echo $html;
die ('Program killed - Probably looping');
}
return $html;
}
}
class aliro {
private static $instance = null;
public $installed = true;
private $timer = 0;
private function __construct () {
$this->timer = new aliroProfiler();
}
public function getElapsed () {
return $this->timer->getElapsed();
}
public static function convertClass ($object, $toclass) {
if (is_object($object)) {
$quotedfrom = '"'.get_class($object).'"';
$ser = serialize($object);
$ser = substr_replace($ser, "\"$toclass\"", strpos($ser, $quotedfrom), strlen($quotedfrom));
return unserialize($ser);
}
return null;
}
public static function getInstance () {
return self::$instance instanceof self ? self::$instance : self::$instance = new self();
}
}
class aliroCore {
private static $instance = null;
private $config = array();
protected function __construct () {
// Set time zone to UTC in case we have not yet installed
//if (function_exists('date_default_timezone_set')) date_default_timezone_set('UTC');
//$this->config = aliroCore::getConfigData('configuration.php');
//if (function_exists('date_default_timezone_set') AND !empty($this->config['timezone'])) {
//date_default_timezone_set($this->config['timezone']);
//}
}
public static function getInstance () {
return is_object(self::$instance) ? self::$instance : (self::$instance = new self());
}
public function getCfg ($name) {
if ('cachetype' == $name) return 'Disk';
return JFactory::getApplication()->getCfg($name);
}
public static function getConfigData ($configname) {
if ('corecredentials.php' == $configname OR 'credentials.php' == $configname) {
$config = self::getInstance();
$credentials['dbhost'] = $config->getCfg('host');
$credentials['dbusername'] = $config->getCfg('user');
$credentials['dbpassword'] = $config->getCfg('password');
$credentials['dbname'] = $config->getCfg('db');
$credentials['dbprefix'] = $config->getCfg('dbprefix');
return $credentials;
}
}
public static function set () { }
public function fixlanguage () {}
}
class aliroRequest {
public static function getInstance () {
return cmsapiInterface::getParticular('bot_jaliro');
}
}
/**
@since 11.1
/
abstract class JLoader
{
/*
/**
/**
/**
/**
/**
public static function discover($classPrefix, $parentPath, $force = true, $recurse = false)
{
JALoader::getInstance()->fileIterator('jaDiscover', $parentPath, $recurse, $classPrefix, $force);
}
/**
/**
/**
/**
/**
/**
class_alias()
./**
/**
/**
/**
/**
/**
final class JALoader extends JLoader {
/**
* Container for singleton instance.
*
* @var object
* @since 11.1
*/
protected static $instance = null;
/**
* Container for auto discovered classes.
*
* @var array
* @since Jaliro
*/
protected $discovered = array();
/**
* List of Jaliro libraries
*
* @var array
* @since Jaliro
* Must be kept the same as the declaration in the Jaliro plugin
*/
public static $jalirolibs = array(
'aliro', 'cmsapi', 'extclasses'
);
/**
* Constructor.
*
* @since 11.1
*/
protected function __construct () {
clearstatcache();
if (is_readable(_JALOADER_CLASS_CACHE) AND filemtime(_JALOADER_CLASS_CACHE) > (time() - 3600*24)) $this->discovered = unserialize(file_get_contents (_JALOADER_CLASS_CACHE));
}
/**
* Method to cache class location information
*
* @return null
*
* @since 11.1
*/
protected function saveToCache () {
file_put_contents(_JALOADER_CLASS_CACHE, serialize($this->discovered));
}
/**
* Method to get singleton instance.
*
* @return object
*
* @since 11.1
*/
public static function getInstance () {
return (self::$instance instanceof self) ? self::$instance : self::$instance = new self();
}
/**
* Method to discover classes of a given type in a given path.
*
* @param string $classPrefix The class name prefix to use for discovery.
* @param string $parentPath Full path to the parent folder for the classes to discover.
* @param boolean $force True to overwrite the autoload path value for the class if it already exists.
* @param boolean $recurse Recurse through all child directories as well as the parent path.
*
* @return void
*
* @since 11.1
*/
public function jaDiscover ($file, $fileName, $classPrefix, $force = true)
{
// Get the class name and full path for each file.
$class = strtolower($classPrefix . preg_replace('#\.php$#', '', $fileName));
// Register the class with the autoloader if not already registered or the force flag is set.
if (empty(parent::$classes[$class]) || $force)
{
$this->jaRegister($class, $file->getPath() . '/' . $fileName);
}
}
/**
* Method to discover classes of a given type in a given path.
*
* @param string $parentPath Full path to the parent folder for the classes to discover.
* @param boolean $recurse Recurse through all child directories as well as the parent path.
*
* @return void
*
* @since 11.1
*/
public function jaAutoDiscover ($parentPath, $recurse=true) {
if (!isset($this->discovered[$parentPath])) {
$this->fileIterator('jaAutoDiscoverFile', $parentPath, $recurse);
$this->saveToCache();
}
}
public function jaClearDiscovery ($parentPath) {
if (isset($this->discovered[$parentPath])) unset($this->discovered[$parentPath]);
}
public function jaAutoDiscoverFile ($file, $fileName, $parentPath)
{
$filedir = $file->getPath();
$tokens = @token_get_all(file_get_contents($filedir.'/'.$fileName)); //http://php.filearena.net/manual/en/function.token-get-all.php#79502
if (!empty($tokens)) foreach ($tokens as $key=>$token) {
if (T_CLASS == $token[0]) {
$classname = isset($tokens[$key+2][1]) ? $tokens[$key+2][1] : '';
$extends = (isset($tokens[$key+4][0]) AND T_EXTENDS == $tokens[$key+4][0] AND isset($tokens[$key+6][1])) ? $tokens[$key+6][1] : '';
if (isset($classes[$classname])) {
if ($extends != $classes[$classname]) $classes[$classname] = '';
}
else $classes[$classname] = $extends;
}
}
if (!empty($classes)) {
$filemap = ('.' == $filedir ? '' : $filedir.'/').basename($fileName);
foreach ($classes as $classname=>$extends) {
$this->discovered[$parentPath][strtolower($classname)]=array('path' => $filemap, 'extends' => $extends);
}
}
unset($tokens);
}
/**
* Method to iterate through PHP files in a directory - with or without recursion.
*
* @param callback $callback Callback to operate on each file.
* @param string $parentPath Full path to the parent folder for the classes to discover.
* @param boolean $recurse Recurse through all child directories as well as the parent path.
*
* @return void
*
* @since 11.1
*/
protected function fileIterator () {
$args = func_get_args();
$callbackmethod = array_shift($args);
$parentPath = array_shift($args);
$recurse = count($args) ? array_shift($args) : true;
if ('jaAutoDiscoverFile' == $callbackmethod) array_unshift($args, $parentPath);
try
{
if ($recurse)
{
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($parentPath),
RecursiveIteratorIterator::SELF_FIRST
);
}
else
{
$iterator = new DirectoryIterator($parentPath);
}
foreach ($iterator as $file)
{
$fileName = $file->getFilename();
// Only load for php files.
// Note: DirectoryIterator::getExtension only available PHP >= 5.3.6
if ($file->isFile() && substr($fileName, strrpos($fileName, '.') + 1) == 'php')
{
$fargs = $args;
array_unshift($fargs, $fileName);
array_unshift($fargs, $file);
call_user_func_array(array($this, $callbackmethod), $fargs);
}
}
}
catch (UnexpectedValueException $e)
{
// Exception will be thrown if the path is not a directory. Ignore it.
}
}
/**
* Method to get the list of registered classes and their respective file paths for the autoloader.
*
* @return array The array of class => path values for the autoloader.
*
* @since 11.1
*/
public function jaGetClassList ()
{
return parent::$classes;
}
/**
* Loads a class from specified directories.
*
* @param string $key The class name to look for (dot notation).
* @param string $base Search this directory for the class.
*
* @return boolean True on success.
*
* @since 11.1
*/
public function jaImport ($key, $base = null)
{
// Only import the library if not already attempted.
if (!isset(parent::$imported[$key]))
{
// Setup some variables.
$success = false;
$parts = explode('.', $key);
$class = array_pop($parts);
$base = (!empty($base)) ? $base : __DIR__;
$path = str_replace('.', DIRECTORY_SEPARATOR, $key);
// Handle special case for helper classes.
if ($class == 'helper')
{
$class = ucfirst(array_pop($parts)) . ucfirst($class);
}
// Standard class.
else
{
$class = ucfirst($class);
}
// If we are importing a library from the Joomla namespace set the class to autoload.
if (strpos($path, 'joomla') === 0)
{
// Since we are in the Joomla namespace prepend the classname with J.
$class = 'J' . $class;
// Only register the class for autoloading if the file exists.
if (is_file($base . '/' . $path . '.php'))
{
parent::$classes[strtolower($class)] = $base . '/' . $path . '.php';
$success = true;
}
}
/*
* If we are not importing a library from the Joomla namespace directly include the
* file since we cannot assert the file/folder naming conventions.
*/
else
{
// If the file exists attempt to include it.
if (is_file($base . '/' . $path . '.php'))
{
$success = (bool) include_once $base . '/' . $path . '.php';
}
}
// Add the import key to the memory cache container.
parent::$imported[$key] = $success;
}
return parent::$imported[$key];
}
/**
* Load the file for a class.
*
* @param string $class The class to be loaded.
*
* @return boolean True on success
*
* @since 11.1
*/
public function jaLoad ($class)
{
// Sanitize class name.
$class = strtolower($class);
// If the class already exists do nothing.
if (class_exists($class, false))
{
return true;
}
// If the class is registered include the file.
if (isset(parent::$classes[$class]))
{
include_once parent::$classes[$class];
return true;
}
return false;
}
/**
* Directly register a class to the autoload list.
*
* @param string $class The class name to register.
* @param string $path Full path to the file that holds the class to register.
* @param boolean $force True to overwrite the autoload path value for the class if it already exists.
*
* @return void
*
* @since 11.1
*/
public function jaRegister ($class, $path, $force = true)
{
// Sanitize class name.
$class = strtolower($class);
// Only attempt to register the class if the name and file exist.
if (!empty($class) && is_readable($path))
{
// Register the class with the autoloader if not already registered or the force flag is set.
if (empty(parent::$classes[$class]) || $force)
{
parent::$classes[$class] = $path;
}
}
}
/**
* Register a class prefix with lookup path. This will allow developers to register library
* packages with different class prefixes to the system autoloader. More than one lookup path
* may be registered for the same class prefix, but if this method is called with the reset flag
* set to true then any registered lookups for the given prefix will be overwritten with the current
* lookup path. When loaded, prefix paths are searched in a "last in, first out" order.
*
* @param string $prefix The class prefix to register.
* @param string $path Absolute file path to the library root where classes with the given prefix can be found.
* @param boolean $reset True to reset the prefix with only the given lookup path.
* @param boolean $prepend If true, push the path to the beginning of the prefix lookup paths array.
*
* @return void
*
* @throws RuntimeException
*
* @since 12.1
*/
public function jaRegisterPrefix($prefix, $path, $reset = false, $prepend = false)
{
// Verify the library path exists.
if (!file_exists($path))
{
throw new RuntimeException('Library path ' . $path . ' cannot be found.', 500);
}
// If the prefix is not yet registered or we have an explicit reset flag then set set the path.
if (!isset(parent::$prefixes[$prefix]) || $reset)
{
parent::$prefixes[$prefix] = array($path);
}
// Otherwise we want to simply add the path to the prefix.
else
{
if ($prepend)
{
array_unshift(parent::$prefixes[$prefix], $path);
}
else
{
parent::$prefixes[$prefix][] = $path;
}
}
}
/**
* Offers the ability for "just in time" usage of `class_alias()`.
* You cannot overwrite an existing alias.
*
* @param string $alias The alias name to register.
* @param string $original The original class to alias.
*
* @return boolean True if registration was successful. False if the alias already exists.
*
* @since 3.2
*/
public function jaRegisterAlias($alias, $original)
{
if (!isset(parent::$classAliases[$alias]))
{
parent::$classAliases[$alias] = $original;
return true;
}
return false;
}
/**
* Register a namespace to the autoloader. When loaded, namespace paths are searched in a "last in, first out" order.
*
* @param string $namespace A case sensitive Namespace to register.
* @param string $path A case sensitive absolute file path to the library root where classes of the given namespace can be found.
* @param boolean $reset True to reset the namespace with only the given lookup path.
* @param boolean $prepend If true, push the path to the beginning of the namespace lookup paths array.
*
* @return void
*
* @throws RuntimeException
*
* @since 12.3
*/
public function jaRegisterNamespace($namespace, $path, $reset = false, $prepend = false) {
// Verify the library path exists.
if (!file_exists($path))
{
throw new RuntimeException('Library path ' . $path . ' cannot be found.', 500);
}
// If the namespace is not yet registered or we have an explicit reset flag then set the path.
if (!isset(self::$namespaces[$namespace]) || $reset)
{
self::$namespaces[$namespace] = array($path);
}
// Otherwise we want to simply add the path to the namespace.
else
{
if ($prepend)
{
array_unshift(self::$namespaces[$namespace], $path);
}
else
{
self::$namespaces[$namespace][] = $path;
}
}
}
/**
* Method to setup the autoloaders for the Joomla Platform. Since the SPL autoloaders are
* called in a queue we will add our explicit, class-registration based loader first, then
* fall back on the autoloader based on conventions. This will allow people to register a
* class in a specific location and override platform libraries as was previously possible.
*
* @return void
*
* @since 11.3
*/
public function jaSetup ($enablePsr = true, $enablePrefixes = true, $enableClasses = true) {
// Register the base path for Joomla platform libraries.
if (!defined('JPATH_PLATFORM')) define ('JPATH_PLATFORM', dirname(__FILE__));
if ($enableClasses) {
// Register the class map based autoloader.
spl_autoload_register(array($this, 'jaLoad'));
}
if ($enablePrefixes) {
$this->registerPrefix('J', JPATH_PLATFORM . '/joomla');
spl_autoload_register(array($this, '_autoload'));
}
if ($enablePsr) {
// Register the PSR-0 based autoloader.
spl_autoload_register(array($this, 'jaLoadByPsr0'));
spl_autoload_register(array($this, 'jaLoadByAlias'));
}
// Check to see if our plugin has been removed - if so, uninstall
if (!is_dir(_CMSAPI_ABSOLUTE_PATH.'/plugins/system/jaliro')) {
self::uninstall();
header('Location: index.php?option=com_installer');
}
}
/**
* Autoload a class based on name.
*
* @param string $class The class to be loaded.
*
* @return void
*
* @since 11.3
*/
private function _autoload ($class)
{
$lclass = strtolower($class);
foreach ($this->discovered as $pathdiscovered) if (isset($pathdiscovered[$lclass]['path'])) {
return include_once($pathdiscovered[$lclass]['path']);
}
foreach (parent::$prefixes as $prefix => $lookup)
{
$chr = substr($class, strlen($prefix), 1);
if (strpos($class, $prefix) === 0 AND (!$chr OR ctype_upper($chr)))
{
return $this->_load(substr($class, strlen($prefix)), $lookup);
}
}
return false;
}
/**
* Method to autoload classes that have been aliased using the registerAlias method.
*
* @param string $class The fully qualified class name to autoload.
*
* @return boolean True on success, false otherwise.
*
* @since 3.2
*/
public static function jaLoadByAlias($class) {
// Remove the root backslash if present.
if ($class[0] == '\\')
{
$class = substr($class, 1);
}
if (isset(self::$classAliases[$class]))
{
class_alias(self::$classAliases[$class], $class);
}
}
/**
* Method to autoload classes that are namespaced to the PSR-0 standard.
*
* @param string $class The fully qualified class name to autoload.
*
* @return boolean True on success, false otherwise.
*
* @since 13.1
*/
public function jaLoadByPsr0 ($class) {
// Remove root backslash, jump out if class already exists
$class = ltrim($class, '\\');
if (class_exists($class, false)) return false;
// Turn namespace and class name into an array
$nameparts = explode('\\', $class);
// Pull out class name and make underscores into directory separators, put back, combine
array_push($nameparts, str_replace('_', DIRECTORY_SEPARATOR, array_pop($nameparts)));
$classpath = implode(DIRECTORY_SEPARATOR, $nameparts).'.php';
// Loop through registered namespaces to look for a match with requested class
foreach (self::$namespaces as $nsname => $nspaths) {
if (0 === strpos($class, $nsname)) foreach ($nspaths as $path) {
$classfile = $path.DIRECTORY_SEPARATOR.$classpath;
if (file_exists($classfile)) return (bool) include_once ($classfile);
}
}
return false;
}
/**
* Load a class based on name and lookup array.
*
* @param string $class The class to be loaded (wihtout prefix).
* @param array $lookup The array of base paths to use for finding the class file.
*
* @return varies Appears to return either a path or false
*
* @since 12.1
*/
private function _load($class, $lookup)
{
// Split the class name into parts separated by camelCase.
$parts = preg_split('/(?<=[a-z0-9])(?=[A-Z])/x', $class);
// If there is only one part we want to duplicate that part for generating the path.
$parts = (count($parts) === 1) ? array($parts[0], $parts[0]) : $parts;
foreach ($lookup as $base)
{
// Generate the path based on the class name parts.
$path = $base . '/' . implode('/', array_map('strtolower', $parts)) . '.php';
// Load the file if it exists.
if (file_exists($path))
{
return include $path;
}
}
return false;
}
public static function uninstall ($internal=false) {
if (file_exists(JPATH_ROOT.'/libraries/joomla.loader.php') AND (!is_writeable(JPATH_ROOT.'/libraries/loader.php') OR !is_writeable(JPATH_ROOT.'/libraries/joomla.loader.php'))) {
die('Cannot write to loaders in '.JPATH_ROOT.'/libraries/ - unable to uninstall or deactivate Jaliro');
}
if (self::deactivate()) {
if ($internal) JFactory::getApplication()->redirect('index.php?option=com_installer', 'Jaliro inactive');
else {
clearstatcache();
foreach (self::$jalirolibs as $jalib) {
if (is_writeable(JPATH_ROOT.'/libraries/'.$jalib)) JFolder::delete(JPATH_ROOT.'/libraries/'.$jalib);
}
}
}
else JFactory::getApplication()->redirect('index.php?option=com_installer', 'Failed to deactivate Jaliro');
}
public static function deactivate () {
return (@unlink(JPATH_ROOT.'/libraries/loader.php') AND @rename(JPATH_ROOT.'/libraries/joomla.loader.php', JPATH_ROOT.'/libraries/loader.php'));
}
}
/**
/**
if ('2.5' != _CMSAPI_JOOMLA_VERSION) JLoader::setup();
Using WinMerge to compare the two, Jaliro stands out as responsible for the extra code.
Jaliro belongs to a component extension called Glossary:
http://remository.com/downloads/joomla-3.x-software/jaliro-for-joomla-3.x/
Very interesting!
My co-admin pulled down a copy of the site files from host, loaded it up locally and tried replacing the offending loader.php file with the one from J3.4. While bring up the site in his browser, the Joomla version file was immediately overwritten with the big Jaliro version above, early in Joomla's execution cycle. He's tracked the event down to the Jaliro system plugin, which again, is part of the Glossary extension, but perhaps also used by the same developer's "Remository" extension.
Upon deactivating the Jaliro system plugin and trying again, the original issue disappears, but he's now getting a new error, related to the other extension:
Fatal error: Class 'sef_glossary' not found in D:\xampp\htdocs\mp\public\components\com_glossary\router.php on line 35
It looks like something (Jaliro is suspected) renamed the original Joomla loader.php file as joomla.loader.php within the same directory, back on Oct 1, 2014.
Based on everything you have said above this is not a core joomla issue and is an issue created by the Jaliro system plugin. A quick scan of the source code shows that this extension is deliberately changing the core joomla file and replacing it with its own. This is something that should obviously never be done (it is also against the rules of a listing on the JED. (It looks like it may also be changing other core files but I havent dug in any further)
As your issue is 100% coming from this extension there is nothing that the core of joomla can do. All I can suggest is that you Uninstall the extension (I hope it is at least nice enough to restore the modified files)
Status | New | ⇒ | Closed |
Closed_Date | 0000-00-00 00:00:00 | ⇒ | 2015-02-28 10:37:06 |
Closed_By | ⇒ | brianteeman |
I am closing this as it is not a core Joomla issue. It is caused by an extension replacing core joomla files which clearly is not something that should be done.
Closed_Date | 2015-02-28 10:37:06 | ⇒ | 2015-02-28 10:37:07 |
Once we dug into the files, we quickly became aware that this was not a Joomla issue. I simply switched over to providing you folks with our 'discovery' as we learned more so that you could take whatever actions you feel are appropriate to the situation.
Hi LTI,
Quick question...do you have any of the Akeeba Products installed on your site?
That ClassLoader.php file doesn't seem to be a standard file that comes with Joomla, and in the forum article you linked to the user included the file contents and the Akeeba developer's name is mentioned in the comments "Nicholas Dionysopoulos" so my thought at the moment is that the file is being added by an extension like Akeeba Backup.
Overall though it looks like the code in that file would be correct if your site had been fully updated to 3.4 (since the "applyAliasFor" method was added then (I don't see it in the 3.3.6 version of Joomla's loader.php file).
It almost feels like the new loader.php file didn't make it in yet (there was an error when you tried to update) OR another possibility is that since you updated your extensions beforehand, when you tried to do the update to 3.4 the new Akeeba Backup code was expecting the 3.4 version of the loader file and was in fact calling a method that doesn't exist yet (because the update to 3.4 hadn't completed yet).
On a new 3.3.6 installation on my end, running the upgrade completed successfully and there aren't any issues, so I'm pretty sure this is due to Akeeba Backup (you can probably copy over the 3.4. Update files to fix things): https://github.com/joomla/joomla-cms/releases/download/3.4.0/Joomla_3.4.0-Stable-Update_Package.zip
This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6224.