Indefero

Indefero Git Source Tree

Root/src/IDF/Gconf.php

1<?php
2/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3/*
4# ***** BEGIN LICENSE BLOCK *****
5# This file is part of InDefero, an open source project management application.
6# Copyright (C) 2008-2011 Céondo Ltd and contributors.
7#
8# InDefero is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2 of the License, or
11# (at your option) any later version.
12#
13# InDefero is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21#
22# ***** END LICENSE BLOCK ***** */
23
24/**
25 * Configuration of the objects.
26 *
27 * It is just storing a list of key/value pairs associated to
28 * different objects. If you use this table for your model, do not
29 * forget to drop the corresponding keys in your preDelete call.
30 */
31class IDF_Gconf extends Pluf_Model
32{
33 public $_model = __CLASS__;
34 public $datacache = null;
35 public $dirty = array();
36 public $f = null;
37 protected $_mod = null;
38 /**
39 * Do we (un)serialize the data when getting/setting them.
40 */
41 public $serialize = false;
42
43 function init()
44 {
45 $this->_a['table'] = 'idf_gconf';
46 $this->_a['model'] = __CLASS__;
47 $this->_a['cols'] = array(
48 // It is mandatory to have an "id" column.
49 'id' =>
50 array(
51 'type' => 'Pluf_DB_Field_Sequence',
52 //It is automatically added.
53 'blank' => true,
54 ),
55 'model_class' =>
56 array(
57 'type' => 'Pluf_DB_Field_Varchar',
58 'blank' => false,
59 'size' => 150,
60 'verbose' => __('model class'),
61 ),
62 'model_id' =>
63 array(
64 'type' => 'Pluf_DB_Field_Integer',
65 'blank' => false,
66 'verbose' => __('model id'),
67 ),
68 'vkey' =>
69 array(
70 'type' => 'Pluf_DB_Field_Varchar',
71 'blank' => false,
72 'size' => 50,
73 'verbose' => __('key'),
74 ),
75 'vdesc' =>
76 array(
77 'type' => 'Pluf_DB_Field_Text',
78 'blank' => false,
79 'verbose' => __('value'),
80 ),
81 );
82 $this->_a['idx'] = array('model_vkey_idx' =>
83 array(
84 'col' => 'model_class, model_id, vkey',
85 'type' => 'unique',
86 ),
87 );
88 $this->f = new IDF_Config_DataProxy($this);
89 }
90
91 function setModel($model)
92 {
93 $this->datacache = null;
94 $this->_mod = $model;
95 }
96
97 function initCache()
98 {
99 $this->datacache = array();
100 $this->dirty = array();
101 $sql = new Pluf_SQL('model_class=%s AND model_id=%s',
102 array($this->_mod->_model, $this->_mod->id));
103 foreach ($this->getList(array('filter' => $sql->gen())) as $val) {
104 $this->datacache[$val->vkey] = ($this->serialize) ? unserialize($val->vdesc) : $val->vdesc;
105 $this->dirty[$val->vkey] = $val->id;
106 }
107 }
108
109 /**
110 * FIXME: This is not efficient when setting a large number of
111 * values in a loop.
112 */
113 function setVal($key, $value)
114 {
115 if (!is_null($this->getVal($key, null))
116 and $value == $this->getVal($key)) {
117 return;
118 }
119 $svalue = ($this->serialize) ? serialize($value) : $value;
120 if (isset($this->dirty[$key])) {
121 // we get to check if deleted by other process + update
122 $conf = new IDF_Gconf($this->dirty[$key]);
123 if ($conf->id == $this->dirty[$key]) {
124 $conf->vdesc = $svalue;
125 $conf->update();
126 $this->datacache[$key] = $value;
127 return;
128 }
129 }
130 // we insert
131 $conf = new IDF_Gconf();
132 $conf->model_class = $this->_mod->_model;
133 $conf->model_id = $this->_mod->id;
134 $conf->vkey = $key;
135 $conf->vdesc = $svalue;
136 $conf->create();
137 $this->datacache[$key] = $value;
138 $this->dirty[$key] = $conf->id;
139 }
140
141 function getVal($key, $default='')
142 {
143 if ($this->datacache === null) {
144 $this->initCache();
145 }
146 return (isset($this->datacache[$key])) ? $this->datacache[$key] : $default;
147 }
148
149 function delVal($key, $initcache=true)
150 {
151 $gconf = new IDF_Gconf();
152 $sql = new Pluf_SQL('vkey=%s AND model_class=%s AND model_id=%s', array($key, $this->_mod->_model, $this->_mod->id));
153 foreach ($gconf->getList(array('filter' => $sql->gen())) as $c) {
154 $c->delete();
155 }
156 if ($initcache) {
157 $this->initCache();
158 }
159 }
160
161 /**
162 * Collection selection.
163 *
164 * Suppose you have 5 objects with associated meta data in the
165 * Gconf storage, if you load the data independently for each
166 * object, you end up with 5 SELECT queries. With 25 objects, 25
167 * SELECT. You can select with one query all the data and merge in
168 * the code. It is faster. The collection selection get a
169 * model_class and a list of ids and returns an id indexed array
170 * of associative array data. This is for read only access as you
171 * do not get a series of Gconf objects.
172 */
173 public static function collect($class, $ids)
174 {
175 $gconf = new IDF_Gconf();
176 $stmpl = sprintf('model_class=%%s AND model_id IN (%s)',
177 implode(',' , $ids));
178 $sql = new Pluf_SQL($stmpl, array($class));
179 $out = array_fill_keys($ids, array());
180 foreach ($gconf->getList(array('filter' => $sql->gen())) as $c) {
181 $out[$c->model_id][$c->vkey] = $c->vdesc;
182 }
183
184 return $out;
185 }
186
187 /**
188 * Drop the conf of a model.
189 *
190 * If your model is using this table, just add the following line
191 * in your preDelete() method:
192 *
193 * IDF_Gconf::dropForModel($this)
194 *
195 * It will take care of the cleaning.
196 */
197 static public function dropForModel($model)
198 {
199 $table = Pluf::factory(__CLASS__)->getSqlTable();
200 $sql = new Pluf_SQL('model_class=%s AND model_id=%s',
201 array($model->_model, $model->id));
202 $db = &Pluf::db();
203 $db->execute('DELETE FROM '.$table.' WHERE '.$sql->gen());
204 }
205
206 static public function dropUser($signal, &$params)
207 {
208 self::dropForModel($params['user']);
209 }
210}
211

Archive Download this file