1  <?php
  2  /* Copyright (c) 2013, Geert Bergman (geert@scrivo.nl)
  3   * All rights reserved.
  4   *
  5   * Redistribution and use in source and binary forms, with or without
  6   * modification, are permitted provided that the following conditions are met:
  7   *
  8   * 1. Redistributions of source code must retain the above copyright notice,
  9   *    this list of conditions and the following disclaimer.
 10   * 2. Redistributions in binary form must reproduce the above copyright notice,
 11   *    this list of conditions and the following disclaimer in the documentation
 12   *    and/or other materials provided with the distribution.
 13   * 3. Neither the name of "Scrivo" nor the names of its contributors may be
 14   *    used to endorse or promote products derived from this software without
 15   *    specific prior written permission.
 16   *
 17   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 18   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 19   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 20   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 21   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 22   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 23   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 24   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 25   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 26   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 27   * POSSIBILITY OF SUCH DAMAGE.
 28   *
 29   * $Id: Role.php 866 2013-08-25 16:22:35Z geert $
 30   */
 31  
 32  /**
 33   * Implementation of the \Scrivo\Role class.
 34   */
 35  
 36  namespace Scrivo;
 37  
 38  /**
 39   * Class that represents a system role class.
 40   *
 41   * Access to pages and assets is restricted through roles. Users can be
 42   * registered to one or more roles as well as objects (pages and assets).
 43   * Do one or more roles of the object and the user match an access level
 44   * higher than the default for the user is granted.
 45   *
 46   * When access is granted, a distiction is made in editor roles and public
 47   * roles. A user with User::STATUS_EDITOR can only be registered to one or
 48   * more Role::EDITOR_ROLE-s, a user with status User::STATUS_MEMBER only
 49   * to one or more User::PUBLIC_ROLE-s.
 50   *
 51   * For role matching see \Scrivo\AccessController.
 52   *
 53   * TODO currently object ids 1 and 2 are used for system roles, this is not
 54   * in line with the policy for object ids.
 55   *
 56   * @property-read int $id The role id (DB key).
 57   * @property \Scrivo\String $description A descriptive name for this role.
 58   * @property \Scrivo\String $title The role title.
 59   * @property int $type The role type, \Scrivo\Role::EDITOR_ROLE or
 60   *    \Scrivo\Role::PUBLIC_ROLE
 61   */
 62  class Role {
 63  
 64      /**
 65       * Constant to denote a public role.
 66       */
 67      const PUBLIC_ROLE 3;
 68  
 69      /**
 70       * Constant to denote an editor role.
 71       */
 72      const EDITOR_ROLE 2;
 73  
 74      /**
 75       * The role id (DB key).
 76       * @var int
 77       */
 78      protected $id 0;
 79  
 80      /**
 81       * The role type, \Scrivo\Role::EDITOR_ROLE or \Scrivo\Role::PUBLIC_ROLE
 82       * @var int
 83       */
 84      private $type self::PUBLIC_ROLE;
 85  
 86      /**
 87       * The role title.
 88       * @var \Scrivo\String
 89       */
 90      private $title null;
 91  
 92      /**
 93       * A descriptive name for this role.
 94       * @var \Scrivo\String
 95       */
 96      private $description null;
 97  
 98      /**
 99       * A Scrivo context.
100       * @var \Scrivo\Context
101       */
102      private $context null;
103  
104      /**
105       * Create an empty role object.
106       *
107       * @param \Scrivo\Context $context A Scrivo context.
108       */
109      public function __construct(\Scrivo\Context $context=null) {
110          \Scrivo\ArgumentCheck::assertArgs(func_get_args(), array(null), 0);
111  
112          if ($context) {
113              $this->title = new \Scrivo\String();
114              $this->description = new \Scrivo\String();
115  
116              $this->context $context;
117          }
118      }
119  
120      /**
121       * Implementation of the readable properties using the PHP magic
122       * method __get().
123       *
124       * @param string $name The name of the property to get.
125       *
126       * @return mixed The value of the requested property.
127       */
128      public function __get($name) {
129          switch($name) {
130              case "id": return $this->id;
131              case "type": return $this->type;
132              case "title": return $this->title;
133              case "description": return $this->description;
134          }
135          throw new \Scrivo\SystemException("No such get-property '$name'.");
136      }
137  
138      /**
139       * Implementation of the writable properties using the PHP magic
140       * method __set().
141       *
142       * @param string $name The name of the property to set.
143       * @param mixed $value The value of the property to set.
144       */
145      public function __set($name$value) {
146          switch($name) {
147              case "type"$this->setType($value); return;
148              case "title"$this->setTitle($value); return;
149              case "description"$this->setDescription($value); return;
150          }
151          throw new \Scrivo\SystemException("No such set-property '$name'.");
152      }
153  
154      /**
155       * Convenience method to set the fields of a role object from
156       * an array (result set row).
157       *
158       * @param \Scrivo\Context $context A Scrivo context.
159       * @param array $rd An array containing the field data using the database
160       *    field names as keys.
161       */
162      protected function setFields(\Scrivo\Context $context, array $rd) {
163  
164          $this->id intval($rd["role_id"]);
165          $this->type intval($rd["type"]);
166          $this->title = new \Scrivo\String($rd["title"]);
167          $this->description = new \Scrivo\String($rd["description"]);
168  
169          $this->context $context;
170      }
171  
172      /**
173       * Set the role's type, \Scrivo\Role::EDITOR_ROLE or
174       *    \Scrivo\Role::PUBLIC_ROLE.
175       *
176       * @param int $type The role's type, \Scrivo\Role::EDITOR_ROLE or
177       *    \Scrivo\Role::PUBLIC_ROLE.
178       */
179      private function setType($type) {
180          \Scrivo\ArgumentCheck::assertArgs(func_get_args(), array(
181              array(\Scrivo\ArgumentCheck::TYPE_INTEGER,
182                  array(self::EDITOR_ROLEself::PUBLIC_ROLE))
183          ));
184  
185          $this->type $type;
186      }
187  
188      /**
189       * Set the role title.
190       *
191       * @param \Scrivo\String $title The role's title.
192       */
193      private function setTitle(\Scrivo\String $title) {
194          $this->title $title;
195      }
196  
197      /**
198       * Set the descriptive name for this role.
199       *
200       * @param \Scrivo\String $description A descriptive name for this role.
201       */
202      private function setDescription(\Scrivo\String $description) {
203          $this->description $description;
204      }
205  
206      /**
207       * Check if this role object can be inserted into the database.
208       *
209       * @throws \Scrivo\ApplicationException If the data is not accessible or
210       *   one or more of the fields contain invalid data.
211       */
212      private function validateInsert() {
213          $this->context->checkPermission(\Scrivo\AccessController::WRITE_ACCESS);
214      }
215  
216      /**
217       * Insert new role object data into the database.
218       *
219       * First it is checked if the data of this role object can be inserted
220       * into the database, then the data is inserted into the database. If no id
221       * was set a new object id is generated.
222       *
223       * @throws \Scrivo\ApplicationException If the data is not accessible or
224       *   one or more of the fields contain invalid data.
225       */
226      public function insert() {
227          try {
228              $this->validateInsert();
229  
230              if (!$this->id) {
231                  $this->id $this->context->connection->generateId();
232              }
233  
234              $sth $this->context->connection->prepare(
235                  "INSERT INTO role (instance_id, role_id, type, title, description)
236                  VALUES (:instId, :id, :type, :title, :descr)");
237  
238              $this->context->connection->bindInstance($sth);
239              $sth->bindValue(":id"$this->id, \PDO::PARAM_INT);
240              $sth->bindValue(":type"$this->type, \PDO::PARAM_INT);
241              $sth->bindValue(":title"$this->title, \PDO::PARAM_STR);
242              $sth->bindValue(":descr"$this->description, \PDO::PARAM_STR);
243  
244              $sth->execute();
245  
246          } catch(\PDOException $e) {
247              throw new \Scrivo\ResourceException($e);
248          }
249      }
250  
251      /**
252       * Check if this role object can be updated in the database.
253       *
254       * @throws \Scrivo\ApplicationException If the data is not accessible or
255       *   one or more of the fields contain invalid data.
256       */
257      private function validateUpdate() {
258          $this->context->checkPermission(\Scrivo\AccessController::WRITE_ACCESS);
259      }
260  
261      /**
262       * Update existing role object data in the database.
263       *
264       * First it is checked if the data of this role object can be updated
265       * in the database, then the data is updated in the database.
266       *
267       * @throws \Scrivo\ApplicationException If the data is not accessible or
268       *   one or more of the fields contain invalid data.
269       */
270      public function update() {
271          try {
272              $this->validateUpdate();
273  
274              $sth $this->context->connection->prepare(
275                  "UPDATE role SET
276                    type = :type, title = :title, description = :descr
277                  WHERE instance_id = :instId AND role_id = :id");
278  
279              $this->context->connection->bindInstance($sth);
280              $sth->bindValue(":id"$this->id, \PDO::PARAM_INT);
281              $sth->bindValue(":type"$this->type, \PDO::PARAM_INT);
282              $sth->bindValue(":title"$this->title, \PDO::PARAM_STR);
283              $sth->bindValue(":descr"$this->description, \PDO::PARAM_STR);
284  
285              $sth->execute();
286  
287              unset($this->context->cache[$this->id]);
288  
289          } catch(\PDOException $e) {
290              throw new \Scrivo\ResourceException($e);
291          }
292      }
293  
294      /**
295       * Check if deletion of role object data does not violate any
296       * business rules.
297       *
298       * @param \Scrivo\Context $context A Scrivo context.
299       * @param int $id The object id of the role to select.
300       *
301       * @throws \Scrivo\ApplicationException If the data is not accessible or
302       *   if it is not possible to delete the language data.
303       */
304      private static function validateDelete(\Scrivo\Context $context$id) {
305          $context->checkPermission(\Scrivo\AccessController::WRITE_ACCESS);
306      }
307  
308      /**
309       * Delete existing role data from the database.
310       *
311       * First it is is checked if it's possible to delete role data,
312       * then the role data including its dependecies is deleted from
313       * the database.
314       *
315       * @param \Scrivo\Context $context A Scrivo context.
316       * @param int $id The object id of the role to select.
317       *
318       * @throws \Scrivo\ApplicationException If the data is not accessible or
319       *   if it is not possible to delete the role data.
320       */
321      public static function delete(\Scrivo\Context $context$id) {
322          \Scrivo\ArgumentCheck::assertArgs(func_get_args(), array(
323              null,
324              array(\Scrivo\ArgumentCheck::TYPE_INTEGER)
325          ));
326          try {
327              self::validateDelete($context$id);
328  
329              foreach (array("role""user_role""object_role") as $table) {
330  
331                  $sth $context->connection->prepare(
332                      "DELETE FROM $table
333                      WHERE instance_id = :instId AND role_id = :id");
334  
335                  $context->connection->bindInstance($sth);
336                  $sth->bindValue(":id"$id, \PDO::PARAM_INT);
337  
338                  $sth->execute();
339              }
340  
341              unset($context->cache[$id]);
342  
343          } catch(\PDOException $e) {
344              throw new \Scrivo\ResourceException($e);
345          }
346      }
347  
348      /**
349       * Fetch a role object from the database using its object id.
350       *
351       * @param \Scrivo\Context $context A Scrivo context.
352       * @param int $id The object id of the role to select.
353       *
354       * @return \Scrivo\Role The requested role object.
355       */
356      public static function fetch(\Scrivo\Context $context$id) {
357          \Scrivo\ArgumentCheck::assertArgs(func_get_args(), array(
358              null,
359              array(\Scrivo\ArgumentCheck::TYPE_INTEGER)
360          ));
361          try {
362              // Try to retieve the role from the cache ...
363              if (isset($context->cache[$id])) {
364                  // ... get it from the cache and set the context.
365                  $role $context->cache[$id];
366                  $role->context $context;
367              } else {
368                  // ... else retrieve it and set it in the cache.
369                  $sth $context->connection->prepare(
370                      "SELECT role_id, type, title, description
371                      FROM role
372                  WHERE instance_id = :instId AND role_id = :id");
373  
374                  $context->connection->bindInstance($sth);
375                  $sth->bindValue(":id"$id, \PDO::PARAM_INT);
376  
377                  $sth->execute();
378  
379                  if ($sth->rowCount() != 1) {
380                      throw new \Scrivo\SystemException("Failed to load role");
381                  }
382  
383                  $role = new \Scrivo\Role();
384                  $role->setFields($context$sth->fetch(\PDO::FETCH_ASSOC));
385  
386                  $context->cache[$id] = $role;
387              }
388  
389              return $role;
390  
391          } catch(\PDOException $e) {
392              throw new \Scrivo\ResourceException($e);
393          }
394      }
395  
396      /**
397       * Select roles from the database.
398       *
399       * Depending on the given arguments the public or editor roles can be
400       * retrieved.
401       *
402       * @param \Scrivo\Context $context A Scrivo context.
403       * @param int $type A role type: \Scrivo\Role::PUBLIC_ROLE or
404       *   \Scrivo\Role::EDITOR_ROLE for which to retrieve the roles.
405       *
406       * @return \Scrivo\Role[id] An array containing the selected roles.
407       */
408      public static function select(\Scrivo\Context $context$type) {
409          \Scrivo\ArgumentCheck::assertArgs(func_get_args(), array(
410              null,
411              array(\Scrivo\ArgumentCheck::TYPE_INTEGER,
412                  array(self::EDITOR_ROLEself::PUBLIC_ROLE))
413          ));
414          try {
415              $sth $context->connection->prepare(
416                  "SELECT role_id, type, title, description FROM role
417                  WHERE instance_id = :instId AND type = :type");
418  
419              $context->connection->bindInstance($sth);
420              $sth->bindValue(":type"$type, \PDO::PARAM_INT);
421  
422              $sth->execute();
423  
424              $res = array();
425  
426              while ($rd $sth->fetch(\PDO::FETCH_ASSOC)) {
427  
428                  $li = new Role();
429                  $li->setFields($context$rd);
430  
431                  $res[$li->id] = $li;
432              }
433  
434              return $res;
435  
436          } catch(\PDOException $e) {
437              throw new \Scrivo\ResourceException($e);
438          }
439      }
440  
441  }
442  
443  ?>

Documentation generated by phpDocumentor 2.0.0a12 and ScrivoDocumentor on August 29, 2013