wCMF  3.6
 All Classes Namespaces Files Functions Variables Groups Pages
class.PersistenceFacade.php
Go to the documentation of this file.
1 <?php
2 /**
3  * wCMF - wemove Content Management Framework
4  * Copyright (C) 2005-2014 wemove digital solutions GmbH
5  *
6  * Licensed under the terms of any of the following licenses
7  * at your choice:
8  *
9  * - GNU Lesser General Public License (LGPL)
10  * http://www.gnu.org/licenses/lgpl.html
11  * - Eclipse Public License (EPL)
12  * http://www.eclipse.org/org/documents/epl-v10.php
13  *
14  * See the license.txt file distributed with this work for
15  * additional information.
16  *
17  * $Id: class.PersistenceFacade.php 1462 2014-02-04 23:52:27Z iherwig $
18  */
19 require_once(BASE."wcmf/lib/persistence/class.RemoteCapablePersistenceFacadeImpl.php");
20 require_once(BASE."wcmf/lib/persistence/class.PersistenceFacadeImpl.php");
21 
22 /**
23  * Some constants describing the build process
24  */
25 define("BUILDDEPTH_INFINITE", -1); // build complete tree from given root on
26 define("BUILDDEPTH_SINGLE", -2); // build only given object
27 define("BUILDDEPTH_REQUIRED", -4); // build tree from given root on respecting the required property defined in element relations
28 define("BUILDDEPTH_MAX", 10); // maximum possible creation depth in one call
29 
30 /**
31  * @class PersistenceFacade
32  * @ingroup Persistence
33  * @brief PersistenceFacade instantiates the PersistenceFacade implementation.
34  *
35  * @author ingo herwig <ingo@wemove.com>
36  */
38 {
39  private static $knownTypes = null;
40  private static $numPkKeys = array();
41  private static $dummyIdPattern = 'wcmf[A-Za-z0-9]{32}';
42 
43  /**
44  * Returns an instance of the PersistenceFacade implementation.
45  * @return A reference to the only instance of the Singleton object
46  */
47  function &getInstance()
48  {
49  static $instance = null;
50 
51  if (!isset($instance))
52  $instance = new RemoteCapablePersistenceFacadeImpl();
53 
54  return $instance;
55  }
56  /**
57  * Get a list of types defined in the application.
58  * @return The list of types
59  */
60  function getKnownTypes()
61  {
62  if (self::$knownTypes == null)
63  {
64  $parser = &InifileParser::getInstance();
65  self::$knownTypes = $parser->getSection('typemapping');
66  }
67  return array_keys(self::$knownTypes);
68  }
69  /**
70  * Check if a type is defined in the application.
71  * @param type The type to check
72  * @return True/False wether the type is defined or not
73  */
74  function isKnownType($type)
75  {
76  if (self::$knownTypes == null) {
77  self::getKnownTypes();
78  }
79  return (isset(self::$knownTypes[$type]) || isset(self::$knownTypes['*']));
80  }
81  /**
82  * Create an object query.
83  * @param type The object type to search for
84  * @return An ObjectQuery instance
85  */
86  function createObjectQuery($type)
87  {
88  return new ObjectQuery($type);
89  }
90  /**
91  * Create a string query.
92  * @return An StringQuery instance
93  */
94  function createStringQuery()
95  {
96  return new StringQuery();
97  }
98  /**
99  * Compose an OID from several parameters.
100  * @param params An assoziative array with the keys 'prefix', 'type' and 'id' where the value of id
101  * maybe a single value or an array (for compound primary keys). If id is an array, the order
102  * of the values must match the order of the primary key names given by PersistenceMapper::getPkNames().
103  * If only type is given in params, the primary key columns will be set with initial values.
104  * @return An OID
105  */
106  function composeOID($params)
107  {
108  if (!is_array($params) || !isset($params['type']))
109  WCMFException::throwEx("Parameter 'type' is missing.", __FILE__, __LINE__);
110 
111  $type = $params['type'];
112 
113  // get given primary keys
114  $pks = array();
115  if (array_key_exists('id', $params))
116  {
117  $givenPKs = $params['id'];
118  if (!is_array($givenPKs))
119  array_push($pks, $givenPKs);
120  else
121  $pks = $givenPKs;
122  }
123 
124  // add dummy ids for missing primary key values
125  $numPKs = self::getNumberOfPKs($type);
126  while (sizeof($pks) < $numPKs)
127  array_push($pks, self::getDummyId());
128 
129  // compose the oid
130  $oid = $type.':'.join(':', $pks);
131  if (isset($params['prefix']) && strlen(trim($params['prefix'])) > 0) {
132  $oid = $params['prefix'].':'.$oid;
133  }
134  return $oid;
135  }
136  /**
137  * Get the base oid for a given oid (@see PersistentObject::getBaseOID()).
138  * @param oid The object id
139  * @param validate True/False if an exception should be thrown if the OID is invalid (default: true)
140  * @return An OID
141  */
142  function getBaseOID($oid, $validate=true)
143  {
144  $oidParts = PersistenceFacade::decomposeOID($oid, $validate);
145  if (self::isKnownType($oidParts['type']))
146  {
147  $persistenceFacade = &PersistenceFacade::getInstance();
148  $tpl = $persistenceFacade->create($oidParts['type'], BUILDDEPTH_SINGLE);
149 
150  $oidParams = array('type' => $tpl->getBaseType(), 'id' => $oidParts['id']);
151  if (strlen($oidParts['prefix']) > 0) {
152  $oidParams['prefix'] = $oidParts['prefix'];
153  }
154  $oid = PersistenceFacade::composeOID($oidParams);
155  }
156  return $oid;
157  }
158  /**
159  * Decompose an OID into several parameters.
160  * @param oid The OID of the object.
161  * @param validate True/False if an exception should be thrown if the OID is invalid (default: true)
162  * @return An assoziative array with the keys 'prefix', 'type' and 'id' where the value of id is an array
163  * holding the primary key values.
164  */
165  function decomposeOID($oid, $validate=true)
166  {
167  // do simple test first
168  $oidParts = self::extractOIDParts($oid);
169  if (!$oidParts['valid'] && $validate) {
170  WCMFException::throwEx('Illegal OID found: '.$oid, __FILE__, __LINE__);
171  }
172  return $oidParts;
173  }
174  /**
175  * Get a part of an object id (e.g. the 'type' parameter).
176  * @param oid The OID of the object.
177  * @param param The name of the parameter.
178  * @param validate True/False if an exception should be thrown if the OID is invalid (default: true)
179  * @return The value of the parameter.
180  */
181  function getOIDParameter($oid, $param, $validate=true)
182  {
183  if ($oid == null)
184  return null;
185  $oidParts = self::decomposeOID($oid, $validate);
186  return $oidParts[$param];
187  }
188  /**
189  * Set a part of an object id (e.g. the 'type' parameter).
190  * @param oid The OID of the object.
191  * @param param The name of the parameter.
192  * @param value The value of the parameter.
193  * @return The modified object id.
194  */
195  function setOIDParameter($oid, $param, $value)
196  {
197  if ($oid == null)
198  return null;
199  $oidParts = self::decomposeOID($oid);
200  $oidParts[$param] = $value;
201  return self::composeOID($oidParts);
202  }
203  /**
204  * Validate a given OID.
205  * @param oid The OID of the object.
206  * @return An True/False whether the OID is valid
207  */
208  function isValidOID($oid)
209  {
210  $oidParts = self::extractOIDParts($oid);
211  if (!$oidParts['valid']) {
212  return false;
213  }
214  return true;
215  }
216  /**
217  * Get the number of primary keys a type has.
218  * @param type The type to check.
219  * @return The number of primary keys [defaults to 1]
220  */
221  function getNumberOfPKs($type)
222  {
223  if (!isset(self::$numPkKeys[$type]))
224  {
225  $numPKs = 1;
226  if (self::isKnownType($type))
227  {
228  $persistenceFacade = &self::getInstance();
229  $mapper = &$persistenceFacade->getMapper($type);
230  $numPKs = sizeof(array_keys($mapper->getPKNames()));
231  }
232  self::$numPkKeys[$type] = $numPKs;
233  }
234  return self::$numPkKeys[$type];
235  }
236  /**
237  * Get a dummy id ("wcmf" + unique 32 character string).
238  * @return A dummy id
239  */
240  function getDummyId()
241  {
242  return "wcmf".md5(uniqid(ip2long($_SERVER['REMOTE_ADDR']) ^ (int)$_SERVER['REMOTE_PORT'] ^ @getmypid() ^ @disk_free_space('/tmp'), 1));
243  }
244  /**
245  * Check if a given id is a dummy id.
246  * @param id The id to check
247  * @return True/False
248  */
249  function isDummyId($id)
250  {
251  static $pattern = null;
252  if ($pattern == null) {
253  $pattern = '/^'.self::$dummyIdPattern.'$/';
254  }
255  return preg_match($pattern, $id) > 0;
256  }
257  /**
258  * Extract all parts of an object id.
259  * @param oid The object id
260  * @return An associative array with keys 'prefix', 'type', 'id', 'valid'
261  */
262  private function extractOIDParts($oid)
263  {
264  $valid = true;
265 
266  // fast checks first
267  if (strlen($oid) == 0) {
268  $valid = false;
269  }
270  else
271  {
272  $oidParts = split(':', $oid);
273  if (!is_array($oidParts)) {
274  $valid = false;
275  }
276  else
277  {
278  static $idPattern = null;
279  if ($idPattern == null) {
280  $idPattern = '/^[0-9]*$|^'.self::$dummyIdPattern.'$/';
281  }
282 
283  // get the ids from the oid
284  $ids = array();
285  $nextPart = array_pop($oidParts);
286  while($nextPart !== null && preg_match($idPattern, $nextPart) == 1)
287  {
288  $ids[] = $nextPart;
289  $nextPart = array_pop($oidParts);
290  }
291  $ids = array_reverse($ids);
292 
293  // get the type
294  $type = $nextPart;
295  if (!self::isKnownType($type)) {
296  $valid = false;
297  }
298  else
299  {
300  // check if number of ids match the type
301  $numPks = self::getNumberOfPKs($type);
302  if ($numPks == null || $numPks != sizeof($ids)) {
303  $valid = false;
304  }
305  }
306  // get the prefix
307  $prefix = join(':', $oidParts);
308  }
309  }
310  return array('prefix' => $prefix, 'type' => $type, 'id' => $ids, 'valid' => $valid);
311  }
312 }
313 ?>
ObjectQuery is the base class for object queries. This class provides the user with object templates ...
setOIDParameter($oid, $param, $value)
throwEx($message, $file='', $line='')
PersistenceFacade instantiates the PersistenceFacade implementation.
decomposeOID($oid, $validate=true)
getBaseOID($oid, $validate=true)
getOIDParameter($oid, $param, $validate=true)
StringQuery executes queries from a string representation. Queries are constructed like WHERE clauses...
const BUILDDEPTH_SINGLE