21
irmtfan
Re: How to write an standard module for xoops (div table, pagination , sort, order)
  • 2013/5/29 10:53

  • irmtfan

  • Module Developer

  • Posts: 3419

  • Since: 2003/12/7


Yes. I knew your intention for adding a fake var (category_name) to article object.
But i dont think it is good for you because:
1- As i said before it will not help you to reduce query.
2- You should overwrite all functions in the parent object (XoopsPersistableObjectHandler) to avoid issues.

for example assume you want to store those objects like this:
$articles $article_handler->getObjects$criteria ); 
foreach (
$articles as $art) { 
  if(!empty(
$_POST["article_title"]) $art->setVar('title'$_POST["article_title"]); 
  
// echo $art->getVar('category_name');
  
$article_handler->insert($arttrue); // error because category_name is not exist.
}

so you have to write insert function too.
then you have to write many other functions. It would not be good for you !!!

based on my experiences using fake vars in a class is only good and acceptable if those tables stick together very tightly and developer dont need to write a handler for one of them.
for example in newbb there is bb_posts and bb_posts_text but there is only one handler NewbbPostHandler extends ArtObjectHandler
Then developer overwritten all needed functions like get, insert, ... by using JOIN.
So in newbb developer dont write any handler for posts text.


side note: it is better to use getAll instead of getObjects because getObjects will be deprecated in next versions.

If you really want to reduce query for category_name the best way is creating a cache file and store all $catNames[$cat_id] = "category_name";
then you have them available any time without any query.

22
bumciach
Re: How to write an standard module for xoops (div table, pagination , sort, order)
  • 2013/5/29 12:58

  • bumciach

  • Not too shy to talk

  • Posts: 153

  • Since: 2007/6/25


Quote:

irmtfan wrote:
for example assume you want to store those objects like this:
$articles $article_handler->getObjects$criteria ); 
foreach (
$articles as $art) { 
  if(!empty(
$_POST["article_title"]) $art->setVar('title'$_POST["article_title"]); 
  
// echo $art->getVar('category_name');
  
$article_handler->insert($arttrue); // error because category_name is not exist.
}

so you have to write insert function too.


No. Only if I use explicitly:
$art->setVar('category_name'$_POST["category_name"])


then the insert() method return error.

Do print_r($art) after every $art->setVar() method (or $art->setFormVars)
and you will see that only those fields in $art object are flagged '[changed]=>1'
Only flaged values pass through insert() method.
Unless something has changed above xoops 3.5.4.

Quote:

side note: it is better to use getAll instead of getObjects because getObjects will be deprecated in next versions.


Good to know.

23
irmtfan
Re: How to write an standard module for xoops (div table, pagination , sort, order)
  • 2013/5/30 2:22

  • irmtfan

  • Module Developer

  • Posts: 3419

  • Since: 2003/12/7


Yes you are right.
Anyway IMO It is efficient to not waste many times on this. write the first version of your module with the most simple codes and try to releasse the first stable version. It is not important if you have to use more queries. then in the next versions you can focus on performances.

24
Mamba
Re: How to write an standard module for xoops (div table, pagination , sort, order)
  • 2013/6/22 0:12

  • Mamba

  • Moderator

  • Posts: 11245

  • Since: 2004/4/23


Irmtfan, I don't use this kind of scheme as you suggest in xoops_version.php:

$modversion['icons16']          = 'Frameworks/moduleclasses/icons/16'
$modversion['icons32']          = 'Frameworks/moduleclasses/icons/32';

because it results later on in code that is harder to read:

$pathIcon32 $module->getInfo('icons32');
$adminmenu[$i]["icon"] = '../../' $pathIcon32 '/home.png';

I prefer to avoid the extra slashes in the code:

Quote:
$adminmenu[$i]["icon"] = '../../' . $pathIcon32 . '/home.png';

I prefer to define the path only once, but with the correct location,

$modversion['icons16']        = '../../Frameworks/moduleclasses/icons/16';
$modversion['icons32']        = '../../Frameworks/moduleclasses/icons/32';

so later on I don't have to deal with extra "/":

$pathIcon32      $module->getInfo('icons32');
$adminmenu[$i]["icon"]  = $pathIcon32 '/home.png';

This code above is much easier to read and less prone to break.

If the location of these icons changes, I just need to adjust it in only one location, and the code will still work.

In your case, if I change the level of icon folder, I'll need to add or remove slashes in several locations, otherwise it won't work.

I think, the rule is that we need to define path variables only in one location and then reuse consistently across the whole module.

For example, I like the idea of defining some common path constants in the /include/common.php that you've shown from Publisher:

Quote:
define("PUBLISHER_DIRNAME", basename(dirname(dirname(__FILE__))));
define("PUBLISHER_URL", XOOPS_URL . '/modules/' . PUBLISHER_DIRNAME);
define("PUBLISHER_IMAGES_URL", PUBLISHER_URL . '/images');
define("PUBLISHER_ADMIN_URL", PUBLISHER_URL . '/admin');

Although, I think that we should go away from hardcoded Uploads directories located in the /uploads:

Quote:
define("PUBLISHER_UPLOADS_URL", XOOPS_URL . '/uploads/' . PUBLISHER_DIRNAME);
define("PUBLISHER_UPLOADS_PATH", XOOPS_ROOT_PATH . '/uploads/' . PUBLISHER_DIRNAME);

and instead let the user decide where they want to save their files by having an option in Preferences. Of course, the above settings could be used as defaults for the option in xoops_version.org

This however opens another question: where should we place uploads as default?

Up to now the thinking from the Core Team was that it should be in the /uploads folder. But this makes copying of modules very difficult, because then I have to think about coping the module itself, and then go to /uploads folder and look for right folder to copy it as well.

Personally, I think, it's better to:
a) make Uploads folder location an option for the user that he can change in Preferences
b) as a default, set it up in the module itself.

The benefits of this:

a) the module is self-contained, and when we copy it to another server, nothing will be missed or lost
b) we don't have to deal with missing upload folders, or with placing in each folder a routine to create the /upload folders during installation.

What do you think?
Support XOOPS => DONATE
Use 2.5.10 | Docs | Modules | Bugs

25
Mamba
Re: How to write an standard module for xoops (div table, pagination , sort, order)
  • 2013/6/23 14:54

  • Mamba

  • Moderator

  • Posts: 11245

  • Since: 2004/4/23


Can you also add the correct procedure to create and use forms in Objects? Currently most modules are adding a code for form creation directly in the Object, which then will look like this: Quote:
class XXX_xxx extends XoopsObject { // constructor function __construct() { .... } function getForm($donnee = array(), $erreur = false, $action = false) { global $xoopsDB, $xoopsModule, $xoopsModuleConfig, $xoopsUser; ..... //création du formulaire $form = new XoopsThemeForm($title, 'form', $action, 'post', true); $form->addElement(new XoopsFormText(_AM_XXX_FORMTITLE, 'title', 50, 255, $this->getVar('title')), true); // fichier $fichier = new XoopsFormElementTray(_AM_XXX_FORMFILE,'

'); $url = $this->isNew() ? 'http://' : $this->getVar('url'); $formurl = new XoopsFormText(_AM_XXXS_FORMURL, 'url', 75, 255, $url); $fichier->addElement($formurl,false); $form->addElement($fichier); ...
} }
Skalpa's recommendation was to create the Form as needed (see this discussion): Quote:
Items are displayed a lot more often than they are edited. If you do like that, then the form generation code will be loaded every time your item is viewed, which will slow everything down (PHP is an interpreted language, so even if your code is not executed it will be loaded, and parsed each time). You'd achieve really better results by inverting the way you work: instead of adding some kind of "createForm" method to your SmartDownload_Download class (well, I don't know what your class is called), you'd better create a XoopsForm child class made to edit downloads:
class SmartDownload_DownloadForm extends XoopsThemeForm {
// Pointer to the object being edited
var $target;
function 
createElements() {
// Do this for all properties, just an example here
$elt = new XoopsFormText'''title'$this->target->getVar'title' ) );
$this->addElement$elt );
}
}
and use your class by doing something like this:
if ( $we_have_to_show_form ) {
include 
'/path/to/form_class.php';
$form = new SmartDownload_DownloadForm();
$form->target =& $my_dload_object;
$form->createElements();
}
Trabis is doing it in Publisher, i.e. all forms are in class mode, receiving an object as parameter, which keeps the object itself smaller: You first define the Form class: Quote:
class PublisherFileForm extends XoopsThemeForm { /** * @var PublisherPublisher * @access public */ var $publisher = null; var $targetObject = null; function __construct(&$target) { $this->publisher = PublisherPublisher::getInstance(); $this->targetObject = $target; parent::__construct(_AM_PUBLISHER_UPLOAD_FILE, "form", xoops_getenv('PHP_SELF')); $this->setExtra('enctype="multipart/form-data"'); $this->createElements(); $this->createButtons(); } ... }
and then use it in the PublisherFile: Quote:
class PublisherFile extends XoopsObject { /** * @var PublisherPublisher * @access public */ public $publisher = null; /** * @param null|int $id */ public function __construct($id = null) { $this->publisher = PublisherPublisher::getInstance(); $this->db = XoopsDatabaseFactory::getDatabaseConnection(); $this->initVar("fileid", XOBJ_DTYPE_INT, 0, false); $this->initVar("itemid", XOBJ_DTYPE_INT, null, true); $this->initVar("name", XOBJ_DTYPE_TXTBOX, null, true, 255); $this->initVar("description", XOBJ_DTYPE_TXTBOX, null, false, 255); $this->initVar("filename", XOBJ_DTYPE_TXTBOX, null, true, 255); $this->initVar("mimetype", XOBJ_DTYPE_TXTBOX, null, true, 64); $this->initVar("uid", XOBJ_DTYPE_INT, 0, false); $this->initVar("datesub", XOBJ_DTYPE_INT, null, false); $this->initVar("status", XOBJ_DTYPE_INT, 1, false); $this->initVar("notifypub", XOBJ_DTYPE_INT, 0, false); $this->initVar("counter", XOBJ_DTYPE_INT, null, false); if (isset($id)) { $file = $this->publisher->getHandler('file')->get($id); foreach ($file->vars as $k => $v) { $this->assignVar($k, $v['value']); } } } public function getForm() { include_once XOOPS_ROOT_PATH . '/modules/publisher/class/form/file.php'; $form = new PublisherFileForm($this); return $form; }
and you use it only when you needed, like this: Quote:
$fileObj = $publisher->getHandler('file')->get($fileid); switch ($op) { case "default": case "mod": include_once XOOPS_ROOT_PATH . '/header.php'; include_once XOOPS_ROOT_PATH . '/class/xoopsformloader.php'; // FILES UPLOAD FORM $files_form = $fileObj->getForm(); $files_form->display(); break;
Support XOOPS => DONATE
Use 2.5.10 | Docs | Modules | Bugs

26
irmtfan
Re: How to write an standard module for xoops (div table, pagination , sort, order)
  • 2013/6/24 5:40

  • irmtfan

  • Module Developer

  • Posts: 3419

  • Since: 2003/12/7


good suggestions Mamba.
Im totally agree with using this:
$modversion['icons16']        = '../../Frameworks/moduleclasses/icons/16';
$modversion['icons32']        = '../../Frameworks/moduleclasses/icons/32';


About hard-coded uploads folder in modules:
IMO when xoops core using a hard-coded uploads folder you should not expect module developer to not use a hard-coded folder
IMO a professional content (news, gallery, download, ...) module should use an optional upload folder but a simple module can follow core ways


About forms:
IMO it is just a coding style. somebody may prefer to have all functions in the class (here: PublisherFile) while others may prefer to move some other functions (here: forms) to another file (here: PublisherFileForm).
there are other forms like block forms that a module developer may prefer to move to another file.

IMO adding one or two more function to a class is not important regarding loading performance (Im against Skalpa LOOL) because in most times we use a few functions from a class after loading all functions

27
Mamba
Re: How to write an standard module for xoops (div table, pagination , sort, order)
  • 2013/6/24 5:55

  • Mamba

  • Moderator

  • Posts: 11245

  • Since: 2004/4/23


Quote:
good suggestions Mamba.
Im totally agree with using this:
$modversion['icons16']        = '../../Frameworks/moduleclasses/icons/16';
$modversion['icons32']        = '../../Frameworks/moduleclasses/icons/32';

But ultimately, these values should come from XOOPS Core directly, so the modules wouldn't have to deal with it manually.

Quote:
IMO it is just a coding style. somebody may prefer to have all functions in the class (here: PublisherFile) while others may prefer to move some other functions (here: forms) to another file (here: PublisherFileForm).
there are other forms like block forms that a module developer may prefer to move to another file.

This is more than just a question of "style" - I talked to Trabis few months back about it, and his recommendation was pretty clear:

Quote:
Trabis: "About the skalpa form, that is what we are supporting in 2.6.0, Look into $xoops->getModuleForm()
Were are using several classes that extend xoopsThemeForm and that receive an object.
SystemPreferencesForm is one of them.
In Publisher, all forms are in class mode receiving an object as param. Yes, it keeps the object itself smaller, skalpa is right. Keep XoopsObject small!"

We all know Trabis - he is always for good programming habits - keeping things small and fast
Support XOOPS => DONATE
Use 2.5.10 | Docs | Modules | Bugs

28
Mamba
Re: How to write an standard module for xoops (div table, pagination , sort, order)
  • 2013/9/29 1:00

  • Mamba

  • Moderator

  • Posts: 11245

  • Since: 2004/4/23


Few suggestions that resulted from my recent experiences:

1) Modules should provide their own plugins for the Tag module called:
"plugin.tag.php" and located in /include folder

The Tag module checks first in this folder for that file, before going to its own folder /plugin:

foreach (array_keys($modules_obj) as $mid) {
        
$dirname $modules_obj[$mid]->getVar("dirname");
        if (!@include_once 
XOOPS_ROOT_PATH "/modules/{$dirname}/include/plugin.tag.php") {
            if (!@include_once 
XOOPS_ROOT_PATH "/modules/tag/plugin/{$dirname}.php") {
                continue;
            }
        }
        
$func_tag "{$dirname}_tag_synchronization";
        if (!
function_exists($func_tag)) {
            continue;
        }
        
$res $func_tag($mid);
    }


We have recently changed the names of the tables in News, and the "news.php" plugin included with the Tag module was automatically outdated. By having the plugin as part of the News module, and keeping it in synch with any changes to the News module, we can guarantee that any updates to an individual module won't break the Tag module.

So in the next release of Tag module, I would suggest to remove all plugins, and include them directly in their respective modules.

I think, the same scheme should be for all other modules utilizing any plugins - this way they won't get outdated.

2) Now that Richard included "XoopsFilterInput" class as part of the Security patch, i.e. it is now officially in XOOPS 2.5.6, going forward we should start utilizing it in the modules.

To learn how to use it, just check out the modified "register.php" file, where we are cleaning input vairable like this:

string:
$uname trim(XoopsFilterInput::clean($myts->stripSlashesGPC($_POST['uname']), 'STRING'));

URL:
$url trim(XoopsFilterInput::clean($myts->stripSlashesGPC($_POST['url']), 'WEBURL'));

By using these filters consistently across all XOOPS modules, we'll ensure that the inputs are properly sanitized, and the code itself easier to read.

Comments?
Support XOOPS => DONATE
Use 2.5.10 | Docs | Modules | Bugs

29
alain01
Re: How to write an standard module for xoops (div table, pagination , sort, order)
  • 2013/9/29 23:09

  • alain01

  • Just can't stay away

  • Posts: 516

  • Since: 2003/6/20


Quote:

Mamba wrote:
We have recently changed the names of the tables in News

Yesssss ^^
Quote:

So in the next release of Tag module, I would suggest to remove all plugins, and include them directly in their respective modules.

I think, the same scheme should be for all other modules utilizing any plugins - this way they won't get outdated.

yes, great idea, like a third party...

30
irmtfan
Re: How to write an standard module for xoops (div table, pagination , sort, order)
  • 2013/10/4 4:29

  • irmtfan

  • Module Developer

  • Posts: 3419

  • Since: 2003/12/7


@Mamba:
1- About plugins:
IMO 2.5.x modules should (or at least can) follow 2.6 plugin structure.
If we think and we accept 2.6 is the future of xoops we should follow its ways for anything (here plugins)

Then modules will be more ready for 2.6+ versions.
plz see Userlog as the only example.

2- About using XoopsFilterInput:
As the name of this class tell us XoopsFilterInput is the security layer for any input variable like $_GET, $_POST, $_REQUEST, $_COOKIE, ... to sanitized them.

sometimes ago every module developer had to struggle with input variables but Trabis introduced request class in Publisher module to make us:
1- free from security issues.
2- handle inputs easier.
XoopsFilterInput answer the first one.

In 2.6.0 Trabis introduced a request class to handle all inputs.
If this class still cannot protect us we should solve the security issues.
So IMO security layers like XoopsFilterInput can be hide inside the request class.

Why I as a basic programmer should know what happens inside xoops core to protect my inputs in my modules?

The usage of request class should be promoted as I recommended in this topic.

Then module developers have the right to use XoopsRequest or XoopsFilterInput.
So again we should follow 2.6 ways in 2.5.x.
we can add request class in 2.5.7 release.
So finally I hope someday we dont see any inputs like $_POST (which increase the risk of attacks) inside any module code.

Login

Username:
Password:

Lost Password? Register now!

Who's Online

65 user(s) are online (32 user(s) are browsing Support Forums)


Members: 0


Guests: 65


more...

Donat-O-Meter

Stats
Goal: $100.00
Due Date: May 31
Gross Amount: $0.00
Net Balance: $0.00
Left to go: $100.00
Make donations with PayPal!

Latest GitHub Commits