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: Language.php 866 2013-08-25 16:22:35Z geert $
 30   */
 31  
 32  /**
 33   * Implementation of the \Scrivo\Language class.
 34   */
 35  
 36  namespace Scrivo;
 37  
 38  /**
 39   * Class that represents a language.
 40   *
 41   * Pages (and possible HTML elements) can have a language attribute. For that
 42   * reason Scrivo maintains a table of (primary) language codes.
 43   *
 44   * To facilitate language selection a short list of languages can be compiled.
 45   * In the user interface language selection will be limited to those that
 46   * are on the short list.
 47   *
 48   * Since the primary purpose of the language class is to fill language
 49   * selection dialogs the full display name of the languages is stored in
 50   * both Dutch and English.
 51   *
 52   * TODO: This should be refactored. There is no need for a seperate class:
 53   * ISO language codes will do fully here. An other undesirable feature is
 54   * the storage of i18n data (the full language names) in the database.
 55   *
 56   * @property-read int $id The language id (DB key).
 57   * @property \Scrivo\String $family The language family (Germanic, Slavic).
 58   * @property \Scrivo\String $isoCode The language ISO code.
 59   * @property \Scrivo\String $nameEn The language name in English.
 60   * @property \Scrivo\String $nameNl The language name in Dutch.
 61   * @property boolean $shortList Whether a language is on the short list or not.
 62   */
 63  class Language {
 64  
 65      /**
 66       * The language id (DB key).
 67       * @var int
 68       */
 69      private $id 0;
 70  
 71      /**
 72       * Whether a language is on the short list or not.
 73       * @var boolean
 74       */
 75      private $shortList false;
 76  
 77      /**
 78       * The language ISO code.
 79       * @var \Scrivo\String
 80       */
 81      private $isoCode null;
 82  
 83      /**
 84       * The language family (Germanic, Slavic).
 85       * @var \Scrivo\String
 86       */
 87      private $family null;
 88  
 89      /**
 90       * The language name in English.
 91       * @var \Scrivo\String
 92       */
 93      private $nameEn null;
 94  
 95      /**
 96       * The language name in Dutch.
 97       * @var \Scrivo\String
 98       */
 99      private $nameNl null;
100  
101      /**
102       * A Scrivo context.
103       * @var \Scrivo\Context
104       */
105      private $context null;
106  
107      /**
108       * Create an empty language object.
109       *
110       * @param \Scrivo\Context $context A Scrivo context.
111       */
112      public function __construct(\Scrivo\Context $context=null) {
113          \Scrivo\ArgumentCheck::assertArgs(func_get_args(), array(null));
114  
115          if ($context) {
116              $this->isoCode = new\Scrivo\String();
117              $this->family = new\Scrivo\String();
118              $this->nameEn = new\Scrivo\String();
119              $this->nameNl = new\Scrivo\String();
120  
121              $this->context $context;
122          }
123      }
124  
125      /**
126       * Implementation of the readable properties using the PHP magic
127       * method __get().
128       *
129       * @param string $name The name of the property to get.
130       *
131       * @return mixed The value of the requested property.
132       */
133      public function __get($name) {
134          switch($name) {
135              case "id": return $this->id;
136              case "shortList": return $this->shortList;
137              case "isoCode": return $this->isoCode;
138              case "family": return $this->family;
139              case "nameEn": return $this->nameEn;
140              case "nameNl": return $this->nameNl;
141          }
142          throw new \Scrivo\SystemException("No such get-property '$name'.");
143      }
144  
145      /**
146       * Implementation of the writable properties using the PHP magic
147       * method __set().
148       *
149       * @param string $name The name of the property to set.
150       * @param mixed $value The value of the property to set.
151       */
152      public function __set($name$value) {
153          switch($name) {
154              case "shortList"$this->setShortList($value); return;
155              case "isoCode"$this->setIsoCode($value); return;
156              case "family"$this->setFamily($value); return;
157              case "nameEn"$this->setNameEn($value); return;
158              case "nameNl"$this->setNameNl($value); return;
159          }
160          throw new \Scrivo\SystemException("No such set-property '$name'.");
161      }
162  
163      /**
164       * Convenience method to set the fields of a language object from
165       * an array (result set row).
166       *
167       * @param \Scrivo\Context $context A Scrivo context.
168       * @param array $rd An array containing the field data using the database
169       *    field names as keys.
170       */
171      private function setFields(\Scrivo\Context $context, array $rd) {
172  
173          $this->id intval($rd["language_id"]);
174          $this->shortList intval($rd["short_list"]) == true false;
175          $this->isoCode = new \Scrivo\String($rd["iso_code"]);
176          $this->family = new \Scrivo\String($rd["family"]);
177          $this->nameEn = new \Scrivo\String($rd["name_en"]);
178          $this->nameNl = new \Scrivo\String($rd["name_nl"]);
179  
180          $this->context $context;
181      }
182  
183      /**
184       * Set the value to indicate if a language is on the short list or not.
185       *
186       * @param boolean $shortList Whether a language is on the short list or not.
187       */
188      private function setShortList($shortList) {
189          \Scrivo\ArgumentCheck::assert(
190              $shortList, \Scrivo\ArgumentCheck::TYPE_BOOLEAN);
191          $this->shortList $shortList;
192      }
193  
194      /**
195       * Set the language ISO code.
196       *
197       * @param \Scrivo\String $isoCode The language ISO code.
198       */
199      private function setIsoCode(\Scrivo\String $isoCode) {
200          $this->isoCode $isoCode;
201      }
202  
203      /**
204       * Set the language family (Germanic, Slavic).
205       *
206       * @param \Scrivo\String $family The language family (Germanic, Slavic).
207       */
208      private function setFamily(\Scrivo\String $family) {
209          $this->family $family;
210      }
211  
212      /**
213       * Set the language name in English.
214       *
215       * @param \Scrivo\String $nameEn The language name in English.
216       */
217      private function setNameEn(\Scrivo\String $nameEn) {
218          $this->nameEn $nameEn;
219      }
220  
221      /**
222       * Set the language name in Dutch.
223       *
224       * @param \Scrivo\String $nameNl The language name in Dutch.
225       */
226      private function setNameNl(\Scrivo\String $nameNl) {
227          $this->nameNl $nameNl;
228      }
229  
230      /**
231       * Check if this language object can be inserted into the database.
232       *
233       * @throws \Scrivo\ApplicationException If the data is not accessible or
234       *   one or more of the fields contain invalid data.
235       */
236      private function validateInsert() {
237          $this->context->checkPermission(\Scrivo\AccessController::WRITE_ACCESS);
238      }
239  
240      /**
241       * Insert new language object data into the database.
242       *
243       * First it is checked if the data of this language object can be inserted
244       * into the database, then the data is inserted into the database. If no id
245       * was set a new object id is generated.
246       *
247       * @throws \Scrivo\ApplicationException If the data is not accessible or
248       *   one or more of the fields contain invalid data.
249       */
250      public function insert() {
251          try {
252              $this->validateInsert();
253  
254              if (!$this->id) {
255                  $this->id $this->context->connection->generateId();
256              }
257  
258              $sth $this->context->connection->prepare(
259                  "INSERT INTO language (
260                      instance_id, language_id, short_list, iso_code, family,
261                      name_en, name_nl
262                  ) VALUES (
263                      :instId, :id, :shortList, :isoCode, :family,
264                      :nameEn, :nameNl
265                  )");
266  
267              $this->context->connection->bindInstance($sth);
268              $sth->bindValue(":id"$this->id, \PDO::PARAM_INT);
269              $sth->bindValue(":shortList"$this->shortList, \PDO::PARAM_INT);
270              $sth->bindValue(":isoCode"$this->isoCode, \PDO::PARAM_STR);
271              $sth->bindValue(":family"$this->family, \PDO::PARAM_STR);
272              $sth->bindValue(":nameEn"$this->nameEn, \PDO::PARAM_STR);
273              $sth->bindValue(":nameNl"$this->nameNl, \PDO::PARAM_STR);
274  
275              $sth->execute();
276  
277          } catch(\PDOException $e) {
278              throw new \Scrivo\ResourceException($e);
279          }
280      }
281  
282      /**
283       * Check if this language object can be updated in the database.
284       *
285       * @throws \Scrivo\ApplicationException If the data is not accessible or
286       *   one or more of the fields contain invalid data.
287      */
288      private function validateUpdate() {
289          $this->context->checkPermission(\Scrivo\AccessController::WRITE_ACCESS);
290      }
291  
292      /**
293       * Update an existing language object data in the database.
294       *
295       * First it is checked if the data of this language object can be updated
296       * in the database, then the data is updated in the database.
297       *
298       * @throws \Scrivo\ApplicationException If the data is not accessible or
299       *   one or more of the fields contain invalid data.
300       */
301      public function update() {
302          try {
303              $this->validateUpdate();
304  
305              $sth $this->context->connection->prepare(
306                  "UPDATE language SET
307                      short_list = :shortList, iso_code = :isoCode, family = :family,
308                      name_en = :nameEn, name_nl = :nameNl
309                  WHERE instance_id = :instId AND language_id = :id");
310  
311              $this->context->connection->bindInstance($sth);
312              $sth->bindValue(":id"$this->id, \PDO::PARAM_INT);
313  
314              $sth->bindValue(":shortList"$this->shortList, \PDO::PARAM_INT);
315              $sth->bindValue(":isoCode"$this->isoCode, \PDO::PARAM_STR);
316              $sth->bindValue(":family"$this->family, \PDO::PARAM_STR);
317              $sth->bindValue(":nameEn"$this->nameEn, \PDO::PARAM_STR);
318              $sth->bindValue(":nameNl"$this->nameNl, \PDO::PARAM_STR);
319  
320              $sth->execute();
321  
322              unset($this->context->cache["L".$this->id]);
323  
324          } catch(\PDOException $e) {
325              throw new \Scrivo\ResourceException($e);
326          }
327      }
328  
329      /**
330       * Check if deletion of language object data does not violate any
331       * business rules.
332       *
333       * @param \Scrivo\Context $context A Scrivo context.
334       * @param int $id The object id of the language to select.
335       *
336       * @throws \Scrivo\ApplicationException If the data is not accessible or
337       *   if it is not possible to delete the language data.
338       */
339      private static function validateDelete(\Scrivo\Context $context$id) {
340          $context->checkPermission(\Scrivo\AccessController::WRITE_ACCESS);
341      }
342  
343      /**
344       * Delete existing language data from the database.
345       *
346       * First it is is checked if it's possible to delete language data,
347       * then the language data including its dependecies is deleted from
348       * the database.
349       *
350       * @param \Scrivo\Context $context A Scrivo context.
351       * @param int $id The object id of the language to select.
352       *
353       * @throws \Scrivo\ApplicationException If the data is not accessible or
354       *   if it is not possible to delete the language data.
355       */
356      public static function delete(\Scrivo\Context $context$id) {
357          \Scrivo\ArgumentCheck::assertArgs(func_get_args(), array(
358              null,
359              array(\Scrivo\ArgumentCheck::TYPE_INTEGER)
360          ));
361          try {
362              self::validateDelete($context$id);
363  
364              $sth $context->connection->prepare(
365                  "DELETE FROM language
366                  WHERE instance_id = :instId AND language_id = :id");
367  
368              $context->connection->bindInstance($sth);
369              $sth->bindValue(":id"$id, \PDO::PARAM_INT);
370  
371              $sth->execute();
372  
373              unset($context->cache["L".$id]);
374  
375          } catch(\PDOException $e) {
376              throw new \Scrivo\ResourceException($e);
377          }
378      }
379  
380      /**
381       * Fetch a language object by from the database using the object id.
382       *
383       * @param \Scrivo\Context $context A Scrivo context.
384       * @param int $id The object id of the language to select.
385       *
386       * @return \Scrivo\Language The requested language object.
387       */
388      public static function fetch(\Scrivo\Context $context$id) {
389          \Scrivo\ArgumentCheck::assertArgs(func_get_args(), array(
390              null,
391              array(\Scrivo\ArgumentCheck::TYPE_INTEGER)
392          ));
393          try {
394              // Try to retieve the language from the cache ...
395              if (isset($context->cache["L".$id])) {
396                  // ... get it from the cache and set the context.
397                  $language $context->cache["L".$id];
398                  $language->context $context;
399              } else {
400                  // ... else retrieve it and set it in the cache.
401                  $sth $context->connection->prepare(
402                      "SELECT language_id, short_list, iso_code, family, name_en, name_nl
403                      FROM language
404                      WHERE instance_id = :instId AND language_id = :id");
405  
406                  $context->connection->bindInstance($sth);
407                  $sth->bindValue(":id"$id, \PDO::PARAM_INT);
408  
409                  $sth->execute();
410  
411                  if ($sth->rowCount() != 1) {
412                      throw new
413                          \Scrivo\SystemException("Failed to load language");
414                  }
415  
416                  $language = new \Scrivo\Language();
417                  $language->setFields($context$sth->fetch(\PDO::FETCH_ASSOC));
418  
419                  $context->cache["L".$id] = $language;
420              }
421  
422              return $language;
423  
424          } catch(\PDOException $e) {
425              throw new \Scrivo\ResourceException($e);
426          }
427      }
428  
429      /**
430       * Select languages from the database.
431       *
432       * @param \Scrivo\Context $context A Scrivo context.
433       * @param boolean $shortList A Scrivo context.
434       *
435       * @return Language[id] An array containing the selected languages.
436       */
437      public static function select(\Scrivo\Context $context$shortList=null) {
438          \Scrivo\ArgumentCheck::assertArgs(func_get_args(), array(
439              null,
440              array(\Scrivo\ArgumentCheck::TYPE_BOOLEAN)
441          ), 1);
442          try {
443              $sth $context->connection->prepare(
444                  "SELECT language_id, short_list, iso_code, family, name_en, name_nl
445                  FROM language WHERE instance_id = :instId ".
446                  ($shortList " AND short_list=1" ""). " ORDER BY iso_code");
447  
448              $context->connection->bindInstance($sth);
449  
450              $sth->execute();
451  
452              $res = array();
453  
454              while ($rd $sth->fetch(\PDO::FETCH_ASSOC)) {
455  
456                  $li = new Language();
457                  $li->setFields($context$rd);
458  
459                  $res[$li->id] = $li;
460              }
461  
462              return $res;
463  
464          } catch(\PDOException $e) {
465              throw new \Scrivo\ResourceException($e);
466          }
467      }
468  
469  }
470  
471  ?>

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