-
Tomaselli
-
-
Offline
-
Elite Member
-
- Posts: 293
- Thank you received: 87
-
Karma: 46
-
|
Yesterday I had the pleasure to meet this fabulous bug . It was always there, apparently, but it never showed up to me until yesterday, when I tried a generated component on a J2.5 (I'm recently using only J3).
Basically some PHP classes were not loaded or randomly loaded and this is also the cause of the famous comment:
// Register all Models because of unsolved random JLoader issue.
// Cook offers 3 months subscribtion for the person who solve this issue.
This great B$£#%&D bug took me few hours to fix, because I was assuming JOOMLA always have good coded functions so I was looking for a bug inside the generated component, without taking care much about how really the "crappy" JLoader::discover works, so at the end I realize I was wrong! (I'm pretty much sure the Admin didn't solve the bug yet for the same reason).
By the way.....file:
ROOT\administrator\components\com_mycomponent\helpers\loader.php
the problems come on the registerPrefix and discover functions. the way they work and the way the jcook generated component are do not match.
so there are 2 solutions:
1) adapt the code and the file names of the generated component to the JOOMLA standards. JOOMLA wants the files named in a way that the filename has part of the php class name, so for example:
the class "MycomponentCkClassModelItem" should have a filename "ModelItem.php" when I call: CkJLoader::discover('MycomponentCkClass', JPATH_ADMIN_MYCOMPONENT .DS.'classes');
OR for example (just to make clear how it works):
the same class should have a filename "ClassModelItem.php" when I call: CkJLoader::discover('MycomponentCk', JPATH_ADMIN_MYCOMPONENT .DS.'classes'); otherwise the JLoader::discover function doesn't correclty work.
this has a limitation, the case when you have more than 1 class on a file, only one class will be registered as loaded in JLoader.
2) my dirty solution, add the following two functions to the Ckloader (and therefore JLoader) on ANY joomla versions cases: class CkJLoader extends JLoader{
public static function get_php_classes($php_code) {
$classes = array();
$tokens = token_get_all($php_code);
$count = count($tokens);
for ($i = 2; $i < $count; $i++) {
if ( $tokens[$i - 2][0] == T_CLASS
&& $tokens[$i - 1][0] == T_WHITESPACE
&& $tokens[$i][0] == T_STRING) {
$class_name = $tokens[$i][1];
$classes[] = $class_name;
}
}
return $classes;
}
/**
* 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 static function Ckdiscover($classPrefix = '', $parentPath, $force = true, $recurse = false)
{
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')
{
$filepath = $file->getPath() . '/' . $fileName;
$php_code = file_get_contents($filepath);
$cls = self::get_php_classes($php_code);
foreach($cls as $cl){
if(strpos($cl, $classPrefix) === false AND $classPrefix != ''){
continue;
}
// Register the class with the autoloader if not already registered or the force flag is set.
if (empty(self::$classes[$cl]) || $force)
{
self::register($cl, $filepath);
}
}
}
}
}
catch (UnexpectedValueException $e)
{
// Exception will be thrown if the path is not a directory. Ignore it.
}
}
} this solution is not fast as the joomla core "discover" function, probably we are talking about milliseconds but surely this solution is more powerful and solid because the functions will scan for classes INSIDE the file content so any classes found will be added if they match the prefix (if used).
so for the 2nd solution, the original loader.php: // no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );
// Some usefull constants
if(!defined('DS')) define('DS',DIRECTORY_SEPARATOR);
if(!defined('BR')) define("BR", "<br />");
if(!defined('LN')) define("LN", "\n");
//Joomla 1.6 only
if (!defined('JPATH_PLATFORM')) define('JPATH_PLATFORM', JPATH_SITE .DS. 'libraries');
// Main component aliases
if (!defined('COM_MYCOMPONENT')) define('COM_MYCOMPONENT', 'com_mycomponent');
if (!defined('MYCOMPONENT_CLASS')) define('MYCOMPONENT_CLASS', 'Mycomponent');
// Component paths constants
if (!defined('JPATH_ADMIN_MYCOMPONENT')) define('JPATH_ADMIN_MYCOMPONENT', JPATH_ADMINISTRATOR . DS . 'components' . DS . COM_MYCOMPONENT);
if (!defined('JPATH_SITE_MYCOMPONENT')) define('JPATH_SITE_MYCOMPONENT', JPATH_SITE . DS . 'components' . DS . COM_MYCOMPONENT);
// JQuery use
if(!defined('JQUERY_VERSION')) define('JQUERY_VERSION', '1.8.2');
$app = JFactory::getApplication();
jimport('joomla.version');
$version = new JVersion();
if (!class_exists('CkJLoader'))
{
// Joomla! 1.6 - 1.7
if (version_compare($version->RELEASE, '2.5', '<'))
{
// Load the missing class file
require_once(JPATH_ADMIN_MYCOMPONENT .DS. 'legacy' .DS. 'loader.php');
// Register the autoloader functions.
CkJLoader::setup();
}
//Joomla! 2.5 and later
else
{
class CkJLoader extends JLoader{}
}
}
// Automatically find the class files (Platform 12.1)
CkJLoader::registerPrefix('MycomponentClass', JPATH_ADMIN_MYCOMPONENT .DS.'classes');
CkJLoader::registerPrefix('MycomponentHelper', JPATH_ADMIN_MYCOMPONENT .DS.'helpers');
// Find Legacy Files (class files missing in previous versions)
CkJLoader::registerPrefix('MycomponentLegacy', JPATH_ADMIN_MYCOMPONENT .DS.'legacy');
CkJLoader::discover('MycomponentClass', JPATH_ADMIN_MYCOMPONENT .DS.'classes');
CkJLoader::discover('MycomponentHelper', JPATH_ADMIN_MYCOMPONENT .DS.'helpers');
// Some helpers
CkJLoader::register('JToolBarHelper', JPATH_ADMINISTRATOR .DS. "includes" .DS. "toolbar.php", true);
CkJLoader::register('JSubMenuHelper', JPATH_ADMINISTRATOR .DS. "includes" .DS. "toolbar.php", true);
// Register all Models because of unsolved random JLoader issue.
// Cook offers 3 months subscribtion for the person who solve this issue.
JLoader::register('MycomponentModelMyitems', JPATH_COMPONENT .DS. 'models' .DS. 'myitems.php');
JLoader::register('MycomponentModelMyitem', JPATH_COMPONENT .DS. 'models' .DS. 'myitem.php');
JLoader::register('MycomponentModelCpanel', JPATH_COMPONENT .DS. 'models' .DS. 'cpanel.php');
JLoader::register('MycomponentModelCpanelbutton', JPATH_COMPONENT .DS. 'models' .DS. 'cpanelbutton.php');
JLoader::register('MycomponentModelThirdusers', JPATH_COMPONENT .DS. 'models' .DS. 'thirdusers.php');
JLoader::register('MycomponentModelThirduser', JPATH_COMPONENT .DS. 'models' .DS. 'thirduser.php');
JLoader::register('MycomponentModelThirdviewlevels', JPATH_COMPONENT .DS. 'models' .DS. 'thirdviewlevels.php');
JLoader::register('MycomponentModelThirdviewlevel', JPATH_COMPONENT .DS. 'models' .DS. 'thirdviewlevel.php');
JLoader::register('MycomponentModelThirdusergroups', JPATH_COMPONENT .DS. 'models' .DS. 'thirdusergroups.php');
JLoader::register('MycomponentModelThirdusergroup', JPATH_COMPONENT .DS. 'models' .DS. 'thirdusergroup.php');
JLoader::register('MycomponentModelThirdcategories', JPATH_COMPONENT .DS. 'models' .DS. 'thirdcategories.php');
JLoader::register('MycomponentModelThirdcategory', JPATH_COMPONENT .DS. 'models' .DS. 'thirdcategory.php');
JLoader::register('MycomponentModelThirdcontents', JPATH_COMPONENT .DS. 'models' .DS. 'thirdcontents.php');
JLoader::register('MycomponentModelThirdcontent', JPATH_COMPONENT .DS. 'models' .DS. 'thirdcontent.php');
// Handle cross compatibilities
require_once(dirname(__FILE__) .DS. 'mvc.php');
// Load the component Dependencies
require_once(dirname(__FILE__) .DS. 'helper.php');
// Always use the Javascript framework for UI
JHTML::_("behavior.framework");
// Configure paths
$lang = JFactory::getLanguage();
if ($app->isSite())
{
$lang->load('com_mycomponent', JPATH_SITE);
CkJController::addModelPath(JPATH_SITE_MYCOMPONENT .DS.'models');
}
else
{
$lang->load('com_mycomponent', JPATH_ADMINISTRATOR);
CkJController::addModelPath(JPATH_ADMIN_MYCOMPONENT .DS.'models');
}
// Set the table directory
JTable::addIncludePath(JPATH_ADMIN_MYCOMPONENT . DS . 'tables');
//Instance JDom
if (!isset($app->dom))
{
jimport('jdom.dom');
if (!class_exists('JDom'))
JError::raiseError(null, 'JDom plugin is required');
JDom::getInstance();
}
would be: // no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );
// Some usefull constants
if(!defined('DS')) define('DS',DIRECTORY_SEPARATOR);
if(!defined('BR')) define("BR", "<br />");
if(!defined('LN')) define("LN", "\n");
//Joomla 1.6 only
if (!defined('JPATH_PLATFORM')) define('JPATH_PLATFORM', JPATH_SITE .DS. 'libraries');
// Main component aliases
if (!defined('COM_MYCOMPONENT')) define('COM_MYCOMPONENT', 'com_mycomponent');
if (!defined('MYCOMPONENT_CLASS')) define('MYCOMPONENT_CLASS', 'Mycomponent');
// Component paths constants
if (!defined('JPATH_ADMIN_MYCOMPONENT')) define('JPATH_ADMIN_MYCOMPONENT', JPATH_ADMINISTRATOR . DS . 'components' . DS . COM_MYCOMPONENT);
if (!defined('JPATH_SITE_MYCOMPONENT')) define('JPATH_SITE_MYCOMPONENT', JPATH_SITE . DS . 'components' . DS . COM_MYCOMPONENT);
// JQuery use
if(!defined('JQUERY_VERSION')) define('JQUERY_VERSION', '1.8.2');
$app = JFactory::getApplication();
jimport('joomla.version');
$version = new JVersion();
if (!class_exists('CkJLoader'))
{
// Joomla! 1.6 - 1.7
if (version_compare($version->RELEASE, '2.5', '<'))
{
// Load the missing class file
require_once(JPATH_ADMIN_MYCOMPONENT .DS. 'legacy' .DS. 'loader.php');
// Register the autoloader functions.
CkJLoader::setup();
}
//Joomla! 2.5 and later
else
{
class CkJLoader extends JLoader{
public static function get_php_classes($php_code) {
$classes = array();
$tokens = token_get_all($php_code);
$count = count($tokens);
for ($i = 2; $i < $count; $i++) {
if ( $tokens[$i - 2][0] == T_CLASS
&& $tokens[$i - 1][0] == T_WHITESPACE
&& $tokens[$i][0] == T_STRING) {
$class_name = $tokens[$i][1];
$classes[] = $class_name;
}
}
return $classes;
}
/**
* 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 static function Ckdiscover($classPrefix = '', $parentPath, $force = true, $recurse = false)
{
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')
{
$filepath = $file->getPath() . '/' . $fileName;
$php_code = file_get_contents($filepath);
$cls = self::get_php_classes($php_code);
foreach($cls as $cl){
if(strpos($cl, $classPrefix) === false AND $classPrefix != ''){
continue;
}
// Register the class with the autoloader if not already registered or the force flag is set.
if (empty(self::$classes[$cl]) || $force)
{
self::register($cl, $filepath);
}
}
}
}
}
catch (UnexpectedValueException $e)
{
// Exception will be thrown if the path is not a directory. Ignore it.
}
}
}
}
}
// Find Legacy Files (class files missing in previous versions)
CkJLoader::Ckdiscover('MycomponentLegacy', JPATH_ADMIN_MYCOMPONENT .DS .'legacy', false, true);
CkJLoader::Ckdiscover('MycomponentClass', JPATH_ADMIN_MYCOMPONENT .DS .'classes', false, true);
CkJLoader::Ckdiscover('MycomponentHelper', JPATH_ADMIN_MYCOMPONENT . DS .'helpers', false, true);
// Some helpers
CkJLoader::register('JToolBarHelper', JPATH_ADMINISTRATOR .DS. "includes" .DS. "toolbar.php", true);
CkJLoader::register('JSubMenuHelper', JPATH_ADMINISTRATOR .DS. "includes" .DS. "toolbar.php", true);
// Handle cross compatibilities
require_once(dirname(__FILE__) .DS. 'mvc.php');
// Always use the Javascript framework for UI
JHTML::_("behavior.framework");
// Configure paths
$lang = JFactory::getLanguage();
if ($app->isSite())
{
$lang->load('com_mycomponent', JPATH_SITE);
CkJController::addModelPath(JPATH_SITE_MYCOMPONENT .DS.'models');
}
else
{
$lang->load('com_mycomponent', JPATH_ADMINISTRATOR);
CkJController::addModelPath(JPATH_ADMIN_MYCOMPONENT .DS.'models');
}
// Set the table directory
JTable::addIncludePath(JPATH_ADMIN_MYCOMPONENT . DS . 'tables');
//Instance JDom
if (!isset($app->dom))
{
jimport('jdom.dom');
if (!class_exists('JDom'))
JError::raiseError(null, 'JDom plugin is required');
JDom::getInstance();
} remember also to add those two functions into the file:
JPATH_ADMIN_MYCOMPONENT .DS. 'legacy' .DS. 'loader.php'
|
|
-
JoomGuy
-
-
Offline
-
Moderator
-
-
Joomla Enthusiast, Lover of Cooking
- Posts: 1115
- Thank you received: 195
-
Karma: 64
-
|
Hi @Tomaselli,
I haven't run into this issue in Cook myself however, it did come up in a conversation with Jocelyn when I mentioned some issues I'd managed to resolve migrating a custom library to J!3.2.
My circumstances were such that I could load my base class by prefix - NO PROBLEM. However, any subsequent classes were not ...
If the issue is the same as the one that I faced, the behaviour is not the fault of JLoader but a lack of precise documentation over at joomla.org. My issues were resolved by following the initial registerPrefix() with the discover() like; // Register MYBO prefix
JLoader::registerPrefix('MYBO', JPATH_LIBRARIES . '/mybo', false, true);
// Load other classes prefixed with MYBO
JLoader::discover('MYBO', JPATH_LIBRARIES . '/mybo', false, true); PLEASE NOTE: The docs are a little bit imprecise on this matter in that they show the 'ingredients' but don't detail how to use them so, please take note that, you will probably need to pass false, true as the 3rd/4th arguments in the registerPrefix('MyPrefix', '/my/path', false true). Although the arguments for discover are different, we also need to pass false, true as the 3rd/4th arguments here too.
Explanation of the arguments:
registerPrefix(1, 2, 3, 4)
- Class Prefix String
- Path String
- Reset Boolean: True to reset the prefix with only the given lookup path.
- Prepend Boolean: If true, push the path to the beginning of the prefix lookup paths array.
discover(1, 2, 3, 4)
- Class Prefix String
- Parent Path String
- Force Boolean: True to overwrite the autoload path value for the class if it already exists.
- Recurse Boolean: Recurse through all child directories as well as the parent path.
Anyway, as I said, I'm not 100% that this is the issue but, if I were a betting man I think I might take my chances on it
Hope it helps!
Gez
|
Need help with your Cook/Joomla Project? . PM me to find out what I can help with. NO time wasters please!!!
|
-
Tomaselli
-
-
Offline
-
Elite Member
-
- Posts: 293
- Thank you received: 87
-
Karma: 46
-
|
thanks @audibleid for the reply and your opinion, you are right, there is a missing documentation about the JLoader (and many other classes in joomla), but it's not only that. In my opinion the JLoader::discover function should work in a different way.
I firstly took a look on the available documentation I found on the web, this something useful.
then I took a look on the source code of the JLoader class.
In my opinion the "discover" function should discover classes inside a folder, and not just what I already know I may find.
Right now it only discovers classes based on the naming rules of the files, what would be a limitation and in some case even wrong.
Moreover the code in loader.php doesn't consider the real functionality of the mentioned JLoader functions, and this cause the random bug. the classes are loaded somewhere else and not in the loader.php.
|
|
-
Tomaselli
-
-
Offline
-
Elite Member
-
- Posts: 293
- Thank you received: 87
-
Karma: 46
-
|
....by the way....the subject: "....B$£#%&D bug!" is due to the unexpected bug (with no parents) and the time lost to find it
|
|
-
JoomGuy
-
-
Offline
-
Moderator
-
-
Joomla Enthusiast, Lover of Cooking
- Posts: 1115
- Thank you received: 195
-
Karma: 64
-
|
Tomaselli wrote:
....by the way....the subject... LMAO!!!
I've posted to @admin so I'm sure he'll take a look at it asap. Personally, I really like JLoader, it works well for me... Tomaselli wrote:
In my opinion the "discover" function should discover classes inside a folder, and not just what I already know I may find.
Right now it only discovers classes based on the naming rules of the files, what would be a limitation and in some case even wrong.
Moreover the code in loader.php doesn't consider the real functionality of the mentioned JLoader functions, and this cause the random bug. Like so many conventions/mechanisms in an MVC/HMVC, a class/file naming pattern must exist to automate things more easily. If you want to recursively grab any classes from a given directory regardless of their name/filename then I suppose you could override it.
You could even use JLoader to load your own override of it I suppose The irony!! LOL
When you said: Tomaselli wrote:
.the classes are loaded somewhere else and not in the loader.php. What did you mean exactly?
|
Need help with your Cook/Joomla Project? . PM me to find out what I can help with. NO time wasters please!!!
|
-
Tomaselli
-
-
Offline
-
Elite Member
-
- Posts: 293
- Thank you received: 87
-
Karma: 46
-
|
.the classes are loaded somewhere else and not in th"e loader.php. if you debug the loader.php file, you'll notice that some classes are not loaded there, even if the code would be written to load those missing classes.
At this point, later in the running application, the missing libraries are loaded, so for sure those libraries are not loaded with the file loader.php.
Moreover if you take a look on the classeslist variable (getting it using the JLoader::getClassesList() or CkJLoader::getClassesList(), it's the same) you'll also notice thar there are some classes WRONGLY named but still loaded, this may causes bugs if later we try to load those classes naming them in the correct way in the classes list, because they are not recognized in the classes list so in the best case you'll load twice, if you are not pushed out from the running application by the fatal error: "Cannot redeclare class".
|
|
-
Tomaselli
-
-
Offline
-
Elite Member
-
- Posts: 293
- Thank you received: 87
-
Karma: 46
-
|
I like the JLoader class, I don't like how the discover method works
|
|
-
JoomGuy
-
-
Offline
-
Moderator
-
-
Joomla Enthusiast, Lover of Cooking
- Posts: 1115
- Thank you received: 195
-
Karma: 64
-
|
Ah, OK... I see.
I haven't got time to look into this now but have posted this to @admin to take a look. Are you absolutely certain that CKJLoader is correctly passing arguments 3 & 4 into both discover() and registerPrefix() methods though? I'm sure that when I spoke to J about this, he'd been unclear about that just as I was.
ADD Is there an updated document equivalent to the docs you linked to because, it looks as though that may be for platform 11.3?
|
Need help with your Cook/Joomla Project? . PM me to find out what I can help with. NO time wasters please!!!
Last Edit: 09 Jan 2014 11:05 by JoomGuy. Reason: ADD
|
-
Tomaselli
-
-
Offline
-
Elite Member
-
- Posts: 293
- Thank you received: 87
-
Karma: 46
-
|
the CkLoader is just a copy of the JLoader class when you are in J2.5 and it's just an empty class when your J > J2.5, so the arguments are surely passed. about the docs.....I found only that....and then I went directly to the source code of JLoader. the code is always the most updated "documentation" .
|
|
-
Tomaselli
-
-
Offline
-
Elite Member
-
- Posts: 293
- Thank you received: 87
-
Karma: 46
-
|
errata corrige:
the methods:
JLoader::getClassesList()
CkJLoader::getClassesList()
are:
JLoader::getClassList()
CkJLoader::getClassList()
|
|
-
JoomGuy
-
-
Offline
-
Moderator
-
-
Joomla Enthusiast, Lover of Cooking
- Posts: 1115
- Thank you received: 195
-
Karma: 64
-
|
Tomaselli wrote:
the CkLoader is just a copy of the JLoader class when you are in J2.5 and it's just an empty class when your J > J2.5, so the arguments are surely passed. Sure, but the reason I asked was because I know that @admin was having issues with this and I'm almost certain that it was because he was missing the $force & $recursive args in the discover() method... It may be worth checking it... I don't remember seeing them in some of the code that you pasted from your component. Tomaselli wrote:
about the docs.....I found only that....and then I went directly to the source code of JLoader. the code is always the most updated "documentation" . Indeed it is
|
Need help with your Cook/Joomla Project? . PM me to find out what I can help with. NO time wasters please!!!
|
-
Tomaselli
-
-
Offline
-
Elite Member
-
- Posts: 293
- Thank you received: 87
-
Karma: 46
-
|
I agree with you. triple check and more heads on the same code are alwaye the fastest solution for a bug.
by the way I used $force and $recursive
|
The following user(s) said Thank You: JoomGuy
|
-
JoomGuy
-
-
Offline
-
Moderator
-
-
Joomla Enthusiast, Lover of Cooking
- Posts: 1115
- Thank you received: 195
-
Karma: 64
-
|
@Tomaselli,
triple check and more heads on the same code are alwaye the fastest solution for a bug. Indeed, especially a B$£#%&D bug LOL
Thanks for the update! We'll have to wait to see what our head chef has to say on the matter for the moment I think!
Cheers,
Gez
|
Need help with your Cook/Joomla Project? . PM me to find out what I can help with. NO time wasters please!!!
Last Edit: 09 Jan 2014 11:29 by JoomGuy.
The following user(s) said Thank You: Tomaselli
|
-
JoomGuy
-
-
Offline
-
Moderator
-
-
Joomla Enthusiast, Lover of Cooking
- Posts: 1115
- Thank you received: 195
-
Karma: 64
-
|
When you say you've added the $recursive & $force, where have you added them - in the helpers/loader.php or in the call to that method from one of your models???
The reason I ask is that I just loaded that file and I don't see them in the standard file.
|
Need help with your Cook/Joomla Project? . PM me to find out what I can help with. NO time wasters please!!!
|
-
Tomaselli
-
-
Offline
-
Elite Member
-
- Posts: 293
- Thank you received: 87
-
Karma: 46
-
|
I firstly tried to use the default joomla mthod CkJLoader::discover , I used the all the args available to see what it loads and why, then after few combinations and tests I wrote the Ckdiscover method and it just replace the discover method, but it loads all the classes it finds, adding them correclty to the classes list:
in my version of the loader.php there are these lines to recursively load all the classes:
CkJLoader::Ckdiscover('MycomponentLegacy', JPATH_ADMIN_MYCOMPONENT .DS .'legacy', false, true);
CkJLoader::Ckdiscover('MycomponentClass', JPATH_ADMIN_MYCOMPONENT .DS .'classes', false, true);
CkJLoader::Ckdiscover('MycomponentHelper', JPATH_ADMIN_MYCOMPONENT . DS .'helpers', false, true); I just saw now....the last line of this snippet could be more wide, because in this way it just load the MyComponentHelper, so I would write it like this: CkJLoader::Ckdiscover('Mycomponent', JPATH_ADMIN_MYCOMPONENT . DS .'helpers', false, true);
|
|
|