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: File.php 866 2013-08-25 16:22:35Z geert $
 30   */
 31  
 32  /**
 33   * Implementation of the \Scrivo\Asset class.
 34   */
 35  
 36  namespace Scrivo;
 37  
 38  /**
 39   */
 40  class File extends Asset {
 41  
 42      /**
 43       * The size in bytes of the asset.
 44       * @var int
 45       */
 46      private $size 0;
 47  
 48      /**
 49       * The asset location.
 50       * @var \Scrivo\String
 51       */
 52      private $location null;
 53  
 54      /**
 55       * The asset mimeType.
 56       * @var \Scrivo\String
 57       */
 58      private $mimeType null;
 59  
 60      /**
 61       * The date/time this asset need to go online.
 62       * @var \DateTime
 63       */
 64      private $dateOnline null;
 65  
 66      /**
 67       * The date/time this asset need to go offline.
 68       * @var \DateTime
 69       */
 70      private $dateOffline null;
 71  
 72      /**
 73       * Create an empty asset object.
 74       *
 75       * @param \Scrivo\Context $context A Scrivo context.
 76       */
 77      public function __construct(\Scrivo\Context $context=null) {
 78          \Scrivo\ArgumentCheck::assertArgs(func_get_args(), array(null), 0);
 79  
 80          if ($context) {
 81  
 82              parent::__construct($context);
 83  
 84              $this->size 0;
 85              $this->location = new \Scrivo\String();
 86              $this->mimeType = new \Scrivo\String();
 87              $this->dateOnline = new \DateTime("now");
 88              $this->dateOffline null;
 89          }
 90      }
 91  
 92      /**
 93       * Implementation of the readable properties using the PHP magic
 94       * method __get().
 95       *
 96       * @param string $name The name of the property to get.
 97       *
 98       * @return mixed The value of the requested property.
 99       */
100      public function __get($name) {
101          switch($name) {
102              case "size": return $this->size;
103              case "location": return $this->location;
104              case "mimeType": return $this->mimeType;
105              case "dateOnline": return $this->dateOnline;
106              case "dateOffline": return $this->dateOffline;
107          }
108          return parent::__get($name);
109      }
110  
111      /**
112       * Implementation of the writable properties using the PHP magic
113       * method __set().
114       *
115       * @param string $name The name of the property to set.
116       * @param mixed $value The value of the property to set.
117       */
118      public function __set($name$value) {
119          switch($name) {
120              case "size"$this->setSize($value); return;
121              case "location"$this->setLocation($value); return;
122              case "mimeType"$this->setMimeType($value); return;
123              case "dateOnline"$this->setDateOnline($value); return;
124              case "dateOffline"$this->setDateOffline($value); return;
125          }
126          parent::__set($name$value);
127      }
128  
129      /**
130       * Convenience method to set the fields of a asset definition object from
131       * an array (result set row).
132       *
133       * @param \Scrivo\Context $context A Scrivo context.
134       * @param array $rd An array containing the field data using the database
135       *    field names as keys.
136       */
137      protected function setFields(\Scrivo\Context $context, array $rd) {
138  
139          parent::setFields($context$rd);
140  
141          $this->size intval($rd["size"]);
142          $this->location = new \Scrivo\String($rd["location"]);
143          $this->mimeType = new \Scrivo\String($rd["mime_type"]);
144          $this->dateOnline = new \DateTime($rd["date_online"]);
145          $this->dateOffline $rd["date_offline"] == null
146              null : new \DateTime($rd["date_offline"]);
147      }
148  
149      /**
150       * Set the id of the asset template.
151       *
152       * @param int $size The id ot the asset template.
153       */
154      private function setSize($size) {
155          \Scrivo\ArgumentCheck::assertArgs(func_get_args(), array(
156              array(\Scrivo\ArgumentCheck::TYPE_INTEGER)
157          ));
158          $this->size $size;
159      }
160  
161      /**
162       * Set the asset location (&lt;location&gt;).
163       *
164       * @param \Scrivo\String $location The asset location
165       *   (&lt;location&gt;).
166       */
167      private function setLocation(\Scrivo\String $location) {
168          $this->location $location;
169      }
170  
171      /**
172       * Set the mimeType for this asset (&lt;mimeType&gt;).
173       *
174       * @param \Scrivo\String $mimeType The mimeType for this asset
175       *   (&lt;mimeType&gt;).
176       */
177      private function setMimeType(\Scrivo\String $mimeType) {
178          $this->mimeType $mimeType;
179      }
180  
181      /**
182       * Set the date/time this asset needs to go online.
183       *
184       * @param \DateTime $dateOnline The date/time this asset needs to go online.
185       */
186      private function setDateOnline(\DateTime $dateOnline) {
187          $this->dateOnline $dateOnline;
188      }
189  
190      /**
191       * Set the date/time this asset need to go offline.
192       *
193       * @param \DateTime $dateOffline The date/time this asset need to go offline.
194       */
195      private function setDateOffline(\DateTime $dateOffline=null) {
196          $this->dateOffline $dateOffline;
197      }
198  
199      /**
200       * Get a unique filename within the scope of the selected directory.
201       */
202      private function getUniqueName() {
203      
204          $base $this->title;
205          $ext "";
206          $pos $this->title->lastIndexOf(new String("."));
207          
208          if ($pos !== -1) {
209              $base $this->title->substr(0$pos);
210              if (!$base[$base->length 1]->equals(new String("_"))) {
211                  $base "{$base}_";
212              }
213              $ext $this->title->substr($pos);
214          }
215          
216          $index 1;
217          while (!$this->checkUnique()) {
218              $this->title = new String($base.$index.$ext);
219              $index++;
220          }
221          
222      }    
223  
224      /**
225       * Test if the asset title is unique within the scope of the directory.
226       * @return boolean
227       */
228      private function checkUnique() {
229      
230          $sth $this->context->connection->prepare(
231              "SELECT COUNT(*) cnt FROM asset WHERE
232                  instance_id = :instId AND
233                  parent_id = :parentId AND title = :title");
234          
235          $this->context->connection->bindInstance($sth);
236          $sth->bindValue(":parentId"$this->parentId, \PDO::PARAM_INT);
237          $sth->bindValue(":title"$this->title, \PDO::PARAM_STR);
238          
239          $sth->execute();
240          
241          if (intval($sth->fetchColumn(0)) == 0) {
242              return true;
243          }
244          return false;
245      }
246      
247      /**
248       * Check if the asset data can be inserted into the database.
249       *
250       * @throws \Scrivo\ApplicationException If the data is not accessible,
251       *   one or more of the fields contain invalid data or some other business
252       *   rule is not met.
253       */
254      private function validateInsert() {
255  
256          if (!$this->parentId) {
257              throw new \Scrivo\SystemException(
258                  "Files can't be created whithout folder");
259          }
260  
261          $this->context->checkPermission(
262              \Scrivo\AccessController::WRITE_ACCESS$this->parentId);
263          
264          $this->getUniqueName();
265      }
266      
267      /**
268       * Insert a new asset into the database.
269       *
270       * First the data fields of this asset will be validated. If no id
271       * is set a new object id is generated. Then the data is inserted into to
272       * database.
273       *
274       * @throws \Scrivo\ApplicationException If one or more of the fields
275       *   contain invalid data.
276       */
277      public function insert() {
278          try {
279              $this->validateInsert();
280  
281              if (!$this->id) {
282                  $this->id $this->context->connection->generateId();
283              }
284  
285              $sth $this->context->connection->prepare(
286                  "INSERT INTO asset (
287                      instance_id, asset_id, parent_id, sequence_no,
288                      type, size, date_created, date_modified, date_online, date_offline,
289                      title, location, mime_type
290                  ) VALUES (
291                      :instId, :id, :parentId, 0,
292                      1, :size, now(), now(), :dateOnline, :dateOffline,
293                      :title, :location, :mimeType
294                  )");
295  
296              $this->context->connection->bindInstance($sth);
297              $sth->bindValue(":id"$this->id, \PDO::PARAM_INT);
298              $sth->bindValue(":parentId"$this->parentId, \PDO::PARAM_INT);
299              $sth->bindValue(":size"$this->size, \PDO::PARAM_INT);
300              $sth->bindValue(":dateOnline",
301                  $this->dateOnline->format("Y-m-d H:i:s"), \PDO::PARAM_STR);
302              $sth->bindValue(":dateOffline"$this->dateOffline
303                  $this->dateOffline->format("Y-m-d H:i:s")
304                  : null, \PDO::PARAM_STR);
305              $sth->bindValue(":title"$this->title, \PDO::PARAM_STR);
306              $sth->bindValue(":location"$this->location, \PDO::PARAM_STR);
307              $sth->bindValue(":mimeType"$this->mimeType, \PDO::PARAM_STR);
308  
309              $sth->execute();
310  
311              unset($this->context->cache[$this->parentId]);
312  
313          } catch(\PDOException $e) {
314              throw new \Scrivo\ResourceException($e);
315          }
316      }
317  
318      /**
319       * Check if this the asset data can be updated in the database.
320       *
321       * @throws \Scrivo\ApplicationException If the data is not accessible,
322       *   one or more of the fields contain invalid data or some other business
323       *   rule is not met.
324       */
325      private function validateUpdate() {
326  
327          $this->context->checkPermission(
328              \Scrivo\AccessController::WRITE_ACCESS$this->id);
329  
330          try {
331              $newPath self::selectPath($this);
332          } catch (\Scrivo\SystemException $e) {
333              throw new \Scrivo\ApplicationException(
334                  "Can't move a asset underneath itself");
335          }
336  
337          $this->getUniqueName();
338      }
339  
340      /**
341       * Update an existing asset in the database.
342       *
343       * First the data fields of this user will be validated, then the data
344       * is updated in to database.
345       *
346       * @throws \Scrivo\ApplicationException If one or more of the fields
347       *   contain invalid data.
348       */
349      public function update() {
350          try {
351              $this->validateUpdate();
352  
353              $isParentWritable false;
354              if ($this->parentId) {
355                  try {
356                      $this->context->checkPermission(
357                          \Scrivo\AccessController::WRITE_ACCESS,
358                          $this->parentId);
359                      $isParentWritable true;
360                  } catch (\Scrivo\ApplicationException $e) {}
361              }
362  
363              $sth $this->context->connection->prepare(
364                  "UPDATE asset SET
365                      parent_id = :parentId, type = 1, size = :size,
366                      date_online = :dateOnline, date_offline = :dateOffline,
367                      date_modified = now(), title = :title, location = :location,
368                      mime_type = :mimeType
369                  WHERE instance_id = :instId AND asset_id = :id");
370  
371              $this->context->connection->bindInstance($sth);
372              $sth->bindValue(":id"$this->id, \PDO::PARAM_INT);
373  
374              $sth->bindValue(":parentId"$this->parentId, \PDO::PARAM_INT);
375              $sth->bindValue(":size"$this->size, \PDO::PARAM_INT);
376              $sth->bindValue(":dateOnline",
377                  $this->dateOnline->format("Y-m-d H:i:s"), \PDO::PARAM_STR);
378              $sth->bindValue(":dateOffline"$this->dateOffline
379                  $this->dateOffline->format("Y-m-d H:i:s")
380                  : null, \PDO::PARAM_STR);
381              $sth->bindValue(":title"$this->title, \PDO::PARAM_STR);
382              $sth->bindValue(":location"$this->location, \PDO::PARAM_STR);
383              $sth->bindValue(":mimeType"$this->mimeType, \PDO::PARAM_STR);
384  
385              $sth->execute();
386  
387              unset($this->context->cache[$this->id]);
388              unset($this->context->cache[$this->parentId]);
389  
390          } catch(\PDOException $e) {
391              throw new \Scrivo\ResourceException($e);
392          }
393      }
394  
395      /**
396       * Check if deletion of asset object data does not violate any
397       * business rules.
398       *
399       * @param \Scrivo\Context $context A Scrivo context.
400       * @param int $id The object id of the asset definition to select.
401       *
402       * @throws \Scrivo\ApplicationException If the data is not accessible or
403       *   if it is not possible to delete the language data.
404       */
405      protected static function validateDelete(\Scrivo\Context $context$id) {
406  
407          $context->checkPermission(\Scrivo\AccessController::WRITE_ACCESS$id);
408  
409          // Is it a labeled asset?
410          $sth $context->connection->prepare(
411              "SELECT COUNT(*) FROM id_label
412              WHERE instance_id = :instId AND id = :id");
413  
414          $context->connection->bindInstance($sth);
415          $sth->bindValue(":id"$id, \PDO::PARAM_INT);
416  
417          $sth->execute();
418  
419          if ($sth->fetchColumn(0) > 0) {
420              throw new \Scrivo\ApplicationException(
421                  "Trying to delete a labelled asset");
422          }
423  
424      }
425  
426  }
427  
428  ?>

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