Subversion Repositories Sites.tela-botanica.org

Rev

Blame | Last modification | View Log | RSS feed

<?php

/***************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2005                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/


//
// Ce fichier ne sera execute qu'une fois
if (defined("_ECRIRE_INC_OBJET_BASE")) return;
define("_ECRIRE_INC_OBJET_BASE", "1");


class _Abstract {
        function abstract_error($str) {
                die ("<h4>".$str."<br>"._T('info_contact_developpeur')."</h4>");
        }
        function abstract_func() {
                $this->abstract_error(_T('avis_erreur_fonction_contexte'));
        }
        function _Abstract() { $this->abstract_func(); }
}


class ObjectCacheInstance extends _Abstract {
        // Variable values (array)
        var $fast_vars;
        var $slow_vars;

        // Variable status
        var $fast_vars_loaded = false;
        var $slow_vars_loaded = false;

        // Is modified ?
        var $dirty = false;

        function ObjectCacheInstance()  {
                $this->fast_vars = array();
                $this->slow_vars = array();
        }
}


class _ObjectFactory extends _Abstract {
        // Factory ID
        var $id_factory;

        // Object class name (for instantiation)
        var $object_class;

        // SQL table name/pattern
        var $sql_table;
        var $sql_id;

        // Plain array
        var $fast_vars_list, $nb_fast_vars;
        var $slow_vars_list, $nb_slow_vars;

        // Associative array
        var $fast_vars_array;
        var $slow_vars_array;

        // SQL field names
        var $fast_vars_sql;
        var $slow_vars_sql;

        // Object cache
        var $cache;

        // ---------------------------------------------------------

        //
        // Init factory helper variables and constants
        //
        function init_factory($id_factory) {
                $this->id_factory = $id_factory;

                // Store different representations of fast vars
                if (is_array($this->fast_vars_list)) {
                        reset($this->fast_vars_list);
                        while (list($key, $val) = each($this->fast_vars_list)) {
                                $this->fast_vars_array[$val] = $val;
                                $this->fast_vars_sql[] = $this->sql_table.'.'.$val;
                        }
                        $this->fast_vars_sql = join(', ', $this->fast_vars_sql);
                        $this->nb_fast_vars = count($this->fast_vars_list);
                }
                else $this->nb_fast_vars = 0;

                // Store different representations of slow vars
                if (is_array($this->slow_vars_list)) {
                        reset($this->slow_vars_list);
                        while (list($key, $val) = each($this->slow_vars_list)) {
                                $this->slow_vars_array[$val] = $val;
                                $this->slow_vars_sql[] = $this->sql_table.'.'.$val;
                        }
                        $this->slow_vars_sql = join(', ', $this->slow_vars_sql);
                        $this->nb_slow_vars = count($this->slow_vars_list);
                }
                else $this->nb_slow_vars = 0;

                // Default value for object id in database
                if (!$this->sql_id) {
                        $this->sql_id = 'id_'.strtolower($this->object_class);
                }
        }


        //
        // Object management methods
        //

        function new_object($id) { $this->abstract(); }

        function create_object_cache_instance($id) {
                if (!($g = $this->cache[$id])) {
                        $g = '_'.$this->object_class.'_'.$id;
                        $GLOBALS[$g] = new ObjectCacheInstance;
                        $this->cache[$id] = $g;
                }
                return $g;
        }

        // Create a new alias for an object
        // (aliases are the only way by which user code sees an object)
        function create_object_alias($id) {
                $class = $this->object_class;
                $alias = new $class;
                $alias->init_object($this->id_factory, $id);
                return $alias;
        }

        // Get field of an object (by ID)
        function get_object_field($id, $name) {
                $g = $this->cache[$id];
                if ($v = $this->fast_vars_array[$name]) {
                        if (!$GLOBALS[$g]->fast_vars_loaded)
                                $this->load_object_id($id, true);
                        return $GLOBALS[$g]->fast_vars[$v];
                }
                else if ($v = $this->slow_vars_array[$name]) {
                        if (!$GLOBALS[$g]->slow_vars_loaded)
                                $this->load_object_id($id, false);
                        return $GLOBALS[$g]->slow_vars[$v];
                }
                else {
                        $this->abstract_error(_T('avis_champ_incorrect_type_objet', array('name' => $name, 'type' => $this->object_class)));
                }
        }

        // Set field of an object (by ID)
        function set_object_field($id, $name, $value) {
                $g = $this->cache[$id];
                if ($v = $this->fast_vars_array[$name]) {
                        if (!$GLOBALS[$g]->fast_vars_loaded)
                                $this->load_object_id($id, true);
                        $GLOBALS[$g]->fast_vars[$v] = $value;
                        $GLOBALS[$g]->dirty = true;
                }
                else if ($v = $this->slow_vars_array[$name]) {
                        if (!$GLOBALS[$g]->slow_vars_loaded)
                                $this->load_object_id($id, false);
                        $GLOBALS[$g]->slow_vars[$v] = $value;
                        $GLOBALS[$g]->dirty = true;
                }
                else {
                        $this->abstract_error(_T('avis_champ_incorrect_type_objet', array('name' => $name)).$this->object_class);
                }
        }


        //
        // Load object by SQL query
        //
        function load_object_sql($query, $fast, $multiple = false) {
                $cols = $this->fast_vars_sql;
                if (!$fast && $this->slow_vars_sql) {
                        if ($cols) $cols .= ', ';
                        $cols .= $this->slow_vars_sql;
                }
                // Replace generic names by actual ones
                $query = ereg_replace('#cols', $cols, $query);
                $query = ereg_replace('#table', $this->sql_table, $query);
                $query = ereg_replace('#id', $this->sql_table.'.'.$this->sql_id, $query);
                $result = spip_query($query);
                // If multiple results expected, create a result array
                if ($multiple) $r = array();
                if ($result) while ($row = spip_fetch_array($result)) {
                        $id = $row[$this->sql_id];
                        $g = $this->create_object_cache_instance($id);
                        // Read fast vars
                        for ($i = 0; $i < $this->nb_fast_vars; $i++) {
                                $var = $this->fast_vars_list[$i];
                                $GLOBALS[$g]->fast_vars[$var] = $row[$var];
                        }
                        $GLOBALS[$g]->fast_vars_loaded = true;
                        if (!$fast) {
                                // Read slow vars
                                for ($i = 0; $i < $this->nb_slow_vars; $i++) {
                                        $var = $this->slow_vars_list[$i];
                                        $GLOBALS[$g]->slow_vars[$var] = $row[$var];
                                }
                                $GLOBALS[$g]->slow_vars_loaded = true;
                        }
                        if ($multiple) $r[$id] = $id;
                        else break;
                }
                if ($multiple) return $r;
        }

        //
        // Load object by ID
        //
        function load_object_id($id, $fast = true) {
                $query = "SELECT #cols FROM #table WHERE #id=$id";
                $this->load_object_sql($query, $fast);
        }

        //
        // Fetch object only if not in cache
        //
        function fetch_object_id($id, $fast = true) {
                if ($g = $this->cache[$id]) {
                        if (!$GLOBALS[$g]->dirty) return;
                }
                else {
                        $g = $this->create_object_cache_instance($id);
                }
                $this->load_object_id($id, $fast);
        }

        //
        // Create new object
        //
        function create_object() {
                static $new_id = 0;
                $id = 'new_'.(++$new_id);
                $g = $this->create_object_cache_instance($id);
                $GLOBALS[$g]->dirty = true;
                $GLOBALS[$g]->fast_vars_loaded = true;
                $GLOBALS[$g]->slow_vars_loaded = true;
                $this->new_object($id);
                return $id;
        }

        //
        // Main load function : fetch object by generic criterium
        //
        function fetch_object($critere, $fast = true) {
                if ($critere == 'new') {
                        // create object
                        $id = $this->create_object();
                }
                else if ($critere > 0) {
                        // get object by id
                        $id = intval($critere);
                        $this->fetch_object_id($id, $fast);
                }
                else {
                        // get object list by sql
                        return $this->load_object_sql($critere, $fast, true);
                }
                return $this->create_object_alias($id);
        }

        //
        // Main save function : update object by ID
        //
        function update_object($id) {
                $g = $this->cache[$id];
                if ($GLOBALS[$g]->dirty) {
                        // generate INSERT query (penser au addslashes)
                }
        }
}


class _Object extends _Abstract {
        // Factory ID
        var $id_factory;

        // Object ID
        var $id = 0;

        function init_object($id_factory, $id = 0) {
                $this->id_factory = $id_factory;
                if ($id) $this->id = $id;
        }

        function get($var) {
                return $GLOBALS[$this->id_factory]->get_object_field($this->id, $var);
        }

        function set($var, $value) {
                return $GLOBALS[$this->id_factory]->set_object_field($this->id, $var, $value);
        }

        function commit() {
                return $GLOBALS[$this->id_factory]->update_object($this->id);
        }
}


//
// Create a factory of a given type, and register it
//

function add_factory($type) {
        global $factories;
        $class = ucfirst($type).'Factory';
        $id_factory = $type.'_factory';
        $GLOBALS[$id_factory] = new $class;
        $GLOBALS[$id_factory]->init_factory($id_factory);
        return $id_factory;
}



?>