21
lubdub
Re: Xoops 2.1 Module development Roadmap
  • 2003/11/7 9:28

  • lubdub

  • Just popping in

  • Posts: 64

  • Since: 2002/2/28


There are popular hacks that should be looked at. For my own selfish pleasure, I'd like to have:
Newbb:
- more code shared between newbb and comments system
- nested view in newbb
- default behaviour: Group access to forums and private forums, user-wise access being an exception
- ability to move, duplicate and delete posts individually or with branches
- ability to delete a post without deleting children

Best regards,



22
lubdub
A suggested refactoring in core Xoops classes and XoopsObject
  • 2003/11/1 15:55

  • lubdub

  • Just popping in

  • Posts: 64

  • Since: 2002/2/28


When porting a module of my site from XOOPS to Xoops², I crawled through the classes and it occured to me that some db/object accessing code is replicated throughout many classes. I wrote my own WhoswhoItem class (my module is a Who's who module for my student association), which extends XoopsObject and is the base class for all my other objects.

I think the following code is something that could (should? ) be included in the next RC/release inside the core XoopsObject class itself.

The base principle is that it uses the java-reflection-like capability of php and assumes proper naming conventions to create the concrete class instances. If this becomes a performance bottleneck, the createInstance method can be made abstract or overriden.

(forgive my typos, my own coding conventions, and so on)
/**
 * @abstract
 */
class WhoswhoItem extends XoopsObject
{

    function 
WhoswhoItem()
    {
        
$this->XoopsObject();
    }
}

/**
 * @abstract
 */
class WhoswhoItemHandler extends XoopsObjectHandler 
{

    var 
$concreteClassName;

    function 
WhoswhoItemHandler(&$db)
    {
        
$this->XoopsObjectHandler($db);
        
// Of course, it assumes a correct implementation 
        // enforcing the naming conventions
        
$handlerClassName get_class($this);
        
$this->concreteClassName substr($handlerClassName0, -7); // 7 is the length of 'Handler'
    
}


    
/**
    * Returns the table used for persistance.
    * @abstract
    */
    
function getTableName()
    {
    }

    
/**
    * Returns the complete Sql request for an Insert operation op the concrete handled subclass.
    * @abstract
    * @param    int        $id the id generated for this instance.
    * @param    object    &$toStore the instance to store.
    */
    
function getInsertRequest($id$toStore)
    {
    }

    
/**
    * Returns the complete Sql request for an Update operation op the concrete handled subclass.
    * @param    object    &$toStore the instance to store.
    * @abstract
    */
    
function getUpdateRequest($toStore)
    {
    }

    
/*
    * Returns the column name of the primary key used to
    * retrieve instances from the table. Usuall 'id', or  'uid', ....
    * @abstract
    */
    
function getPKName()
    {
    }


    
/**
    * Creates an instance of the concrete handled class.
    * @access    protected
    */
    
function &createInstance()
    {
        
$className $this->concreteClassName;
        
$value = new $className();
        return 
$value;
    }


    
/**
    * Creates a new instance of the concrete handled subclass. 
    * @return    bool    $isNew  Flag the object as "new"?
    * @access    public
    */
    
function &create($isNew true)
    {
        
$value =& $this->createInstance();
        if (
$isNew
        {
            
$value->setNew();
        }
        return 
$value;
    }


    
/*
    * Retrieves data from DB and fills a new instance the concrete handled subclass with it.
    * Assumes the PK id is an int.
    * @access private
    * @param    int $id ID 
    * @return    object instance, FALSE on fail
    */
    
function &get($id)
    {
        
$sql sprintf"SELECT * FROM %s WHERE %s = %d "
        
$this->db->prefix($this->getTableName()), $this->getPKName(), intval($id));
        if ( !
$result $this->db->query($sql) ) 
        {
            return 
false;
        }
        
$numrows $this->db->getRowsNum($result);
        if ( 
$numrows == 
        {
            
$value =& $this->createInstance();
            
$value->assignVars($this->db->fetchArray($result));
            return 
$value;
        }
        return 
false;
    }


    
/**
    * Stores a the concrete handled subclass. 
    * @param    object  &$toStore an instance the concrete handled subclass. 
    * @return    bool    TRUE on success
    */
    
function insert(&$toStore)
    {
        if ( 
get_class($toStore) != $this->concreteClassName 
        {
            return 
false;
        }
        if ( !
$toStore->isDirty() ) 
        {
            return 
true;
        }
        if (!
$toStore->cleanVars()) 
        {
            return 
false;
        }
        if (
$toStore->isNew()) 
        {
            
$generated_id $this->db->genId$this->getTableName());
            
$sql $this->getInsertRequest($generated_id$toStore);
        } 
        else 
        {
            
$sql $this->getUpdateRequest($toStore);
        }
        if (!
$result $this->db->query($sql)) 
        {
            return 
false;
        }
        if (empty(
$generated_id)) 
        {
            
$generated_id $this->db->getInsertId();
        }
        
$toStore->assignVar$this->getPKName(), $generated_id);
        return 
true;
    }

    
/**
    * Deletes an instance the concrete handled subclass.
    * @param    object  &$toDelete
    * @return    bool    TRUE on success
    */
    
function delete(&$toDelete)
    {
        if (
get_class($toDelete) != $this->concreteClassName
        {
            return 
false;
        }
        
$sql sprintf("DELETE FROM %s WHERE %s = '%s'"
            
$this->db->prefix($this->getTableName()), $this->getPKName(), 
            
$toDelete->getVar($this->getPKName()));
        if (!
$result $this->db->query($sql)) 
        {
            return 
false;

        }
        return 
true;
    }

    
/**
    * Deletes all instances matching a set of conditions
    * @param object $criteria {@link CriteriaElement} 
    * @return bool FALSE if deletion failed
    */
    
function deleteAll($criteria null)
    {
        
$sql 'DELETE FROM '.$this->db->prefix($this->getTableName());
        if (isset(
$criteria) && is_subclass_of($criteria'criteriaelement')) 
        {
            
$sql .= ' '.$criteria->renderWhere();
        }
        if (!
$result $this->db->query($sql)) 
        {
            
$this->notifyUpdate($sql'failed_update');
            return 
false;
        }
        return 
true;
    }

    
/**
    * Retrieves multiple instance of the concrete handled subclass.
    * @param    object  $criteria   {@link CriteriaElement}
    * @param    bool    $id_as_key  Use IDs as array keys?
    * 
    * @return    array   Array of {@link XoopsGroupPerm}s 
    */
    
function &getObjects($criteria null$id_as_key false)
    {
        
$ret = array();
        
$limit $start 0;
        
$sql 'SELECT * FROM '.$this->db->prefix($this->getTableName());
        if (isset(
$criteria) && is_subclass_of($criteria'criteriaelement')) 
        {
            
$sql .= ' '.$criteria->renderWhere();
            if ( 
'' != $criteria->getSort() ) {
                
$sql .= ' ORDER BY '.$criteria->getSort().' '.$criteria->getOrder();
            }
            
$limit $criteria->getLimit();
            
$start $criteria->getStart();
        }
        
$result $this->db->query($sql$limit$start);
        if (!
$result
        {
            return 
$ret;
        }
        while (
$myrow $this->db->fetchArray($result)) 
        {
            
$value =& $this->createInstance();
            
$value->assignVars($myrow);
            if (!
$id_as_key
            {
                
$ret[] =& $value;
            } else 
            {
                
$ret[$myrow[$this->getPKName()]] =& $value;
            }
            unset(
$value);
        }
        return 
$ret;
    }

    
/**
    * Obtains the "db-quoted" version of the variables contents, to be able to store them directly. Just a helper method, not mandatory.
    * @access    protected
    */
    
function &quotedCleanVars(&$object)
    {
        
$toReturn = array();
        foreach (
$object->cleanVars as $k => $v
        {
            
$toReturn[$k] = $this->db->quoteString($v);
        }
        return 
$toReturn;
    }

}


With this, in subclasses, you don't need the write the typical "get", "getObjects", "delete", ... methods. You only need to write:
o a Constructor
o the concrete implementation of getTableName()
o the concrete implementation of getInsertRequest()
o the concrete implementation of getUpdateRequest()
o the concrete implementation of getPKName()

All of which are quite simple and quite short methods. This makes your classes shorter to write and easier to maintain.



23
lubdub
Re: Flood Control in Bulletin Board
  • 2003/10/28 21:35

  • lubdub

  • Just popping in

  • Posts: 64

  • Since: 2002/2/28


Ban his ip and change his password. That will annoy him more... (though flood control would be better )



24
lubdub
Re: Criteria class for SQL 'OR' - solved
  • 2003/10/28 21:31

  • lubdub

  • Just popping in

  • Posts: 64

  • Since: 2002/2/28


You don't need to create a subclass, just order and create your instance properly (CriteriaCompo renders hierachically)

Quick and Dirty Example:
$criteria1 = new Criteria('interest1''Camping');
$criteria2 = new Criteria('interest2''Camping');
$criteria3 = new Criteria('interest3''Camping');
$criteria4 = new Criteria('interest4''Camping');

$compo1 = new CriteriaCompo($criteria1);
$compo1->add($criteria2'OR');
$compo1->add($criteria3'OR');
$compo1->add($criteria4'OR');

$criteria5 = new Criteria('location''Andorra');
$criteria6 = new Criteria('level'0'>');
$compo2 = new CriteriaCompo($criteria5);
$compo2->add($criteria6'AND');

$compo3 = new CriteriaCompo($compo1)
$compo3->add($compo2'AND');


$compo3 should, with the syntax errors corrected, render roughly your WHERE clause...



25
lubdub
Re: Slashes in my form preview
  • 2003/10/27 12:28

  • lubdub

  • Just popping in

  • Posts: 64

  • Since: 2002/2/28


Well, from my own experience, I'd say there's already something like that.
Correct me if I'm wrong, but if you need to use Text input from the client, you're likely to store it somewhere. If you store it in an Object class instance, extending XoopsObject, you can use the setVar() getVar() methods to have this clean up made for you, somehow.

Otherwise, depending on your usage, you can have a look at the TextSanitizer class.



26
lubdub
Re: $xoopsTpl - unexpected value for module name
  • 2003/10/27 12:24

  • lubdub

  • Just popping in

  • Posts: 64

  • Since: 2002/2/28


Quote:

Venezia wrote:
But if we shouldn't use _tpl_vars, what is the correct way to access values that have been stored in $xoopsTpl? (from a php file, not from an html template).
I'm more interested in the values passed by the current module to $xoopsTpl rather than the values stored by the xoopsModule object.

Good question. I'm not (yet ) Smarty-savvy enough to answer that, but I'd say:
* if you reference them from a script invoked from your Smarty template, you probably can just reference them (or check the Smarty site)
* if you have filled data into the template in one script and want to retrieve in from another script, your design has a serious flaw. The xoopsTpl is a variable-container for inter-script data transfer.
(furthermore, the variables in the xoopsTpl don't come only from 'the current module', but from all module-blocks, ...)



27
lubdub
Limiting search ability
  • 2003/10/26 21:53

  • lubdub

  • Just popping in

  • Posts: 64

  • Since: 2002/2/28


A suggestion for the feature you might want to add to the next version:
if member X is not allowed to access module Y, XOOPS shouldn't bother running the search function for Y when X makes a request (this would display results, even if those results are not accessible, the fact that the information is partially shown is already something that should be hidden))

Well...

Reading this afterwards, it seems oddly written...



28
lubdub
Re: 2.1.0
  • 2003/10/23 10:30

  • lubdub

  • Just popping in

  • Posts: 64

  • Since: 2002/2/28


May we bribe you to have group permissions on forum access? ;o)



29
lubdub
Xhtml compliance
  • 2003/10/22 14:32

  • lubdub

  • Just popping in

  • Posts: 64

  • Since: 2002/2/28


Is Xhtml compliance still a goal for Xoops?

It looks like the frontpage is Xhtml compliant, which is good. But when I submit my own internal development page, I run into problem for an admin block: the waiting contents (ok, this block is not supposed to be visible).

Here is the message from the W3C Validator:
Quote:

“unknown entity ‘FOO’”

The validator has found an entity (something like &this;) that it doesn't recognize. There are a few possibilities:

*

A reference to a URI that uses & as a separator between parameters, such as "http://example.org/prog?x=1&y=2".

To solve this problem, simply replace all the &'s in attribute values with & (user agents will convert them back before following the links.)


The problem is the
index.php?op=..&...
which should , in the source code, be
index.php?op= .. &..


... if I'm not wrong ...



30
lubdub
Re: Adding the group permission feature to your module
  • 2003/9/21 16:34

  • lubdub

  • Just popping in

  • Posts: 64

  • Since: 2002/2/28


Excellent feature, and very clear explanations, what could we ask more?

(oh, maybe my holy grail? Do you plan to use it for newbb? Ooooh, yeah group permissions for forums!! Pleaaaaaase )




TopTop
« 1 2 (3) 4 »



Login

Who's Online

63 user(s) are online (34 user(s) are browsing Support Forums)


Members: 0


Guests: 63


more...

Donat-O-Meter

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

Latest GitHub Commits