Switchboard
  • Namespace
  • Class
  • Tree

Namespaces

  • Fluxsauce
    • Switchboard

Classes

  • EnvDb
  • Environment
  • Persistent
  • Project
  • Provider
  • ProviderAcquia
  • ProviderPantheon
  • Site
  • Sqlite
  1 <?php
  2 /**
  3  * @file
  4  * Generic class providing database persistence.
  5  *
  6  * @todo Use a real ORM.
  7  */
  8 
  9 namespace Fluxsauce\Switchboard;
 10 
 11 /**
 12  * Generic class providing database persistence.
 13  * @package Fluxsauce\Switchboard
 14  */
 15 abstract class Persistent {
 16   /**
 17    * @var int The Primary Key of the record.
 18    */
 19   protected $id;
 20 
 21   /**
 22    * @var string The machine name of the record.
 23    */
 24   protected $name;
 25 
 26   /**
 27    * @var int The UNIX timestamp of when the record was last updated.
 28    */
 29   protected $updated;
 30 
 31   /**
 32    * @var string Metadata for ORM defining database structure.
 33    */
 34   protected $externalKeyName;
 35 
 36   /**
 37    * Constructor.
 38    *
 39    * @param int $external_id
 40    *   Optional external identifier.
 41    * @param string $name
 42    *   Optional name.
 43    *
 44    * @throws \Exception
 45    */
 46   public function __construct($external_id = NULL, $name = NULL) {
 47     // Ensure that implementing classes include an external key name of some
 48     // sort.
 49     if (!$this->externalKeyName) {
 50       throw new \Exception(get_called_class() . ' is missing the external key name.');
 51     }
 52     $this->{$this->externalKeyName} = $external_id;
 53     $this->name = $name;
 54 
 55     if ($external_id && $name) {
 56       $this->read();
 57     }
 58   }
 59 
 60   /**
 61    * Magic __get.
 62    *
 63    * @param string $name
 64    *   Name of the property to get.
 65    *
 66    * @return mixed
 67    *   Value of set property.
 68    * @throws \Exception
 69    */
 70   public function __get($name) {
 71     $name = switchboard_to_camel_case($name);
 72     if (!property_exists($this, $name)) {
 73       drush_print_r(debug_backtrace());
 74       throw new \Exception(get_called_class() . ' property ' . $name . ' does not exist, cannot get.');
 75     }
 76     return $this->$name;
 77   }
 78 
 79   /**
 80    * Magic __set.
 81    *
 82    * @param string $name
 83    *   Name of the property to set.
 84    * @param mixed $value
 85    *   Value of said property.
 86    *
 87    * @throws \Exception
 88    */
 89   public function __set($name, $value) {
 90     $name = switchboard_to_camel_case($name);
 91     if (!property_exists($this, $name)) {
 92       drush_print_r(debug_backtrace());
 93       throw new \Exception(get_called_class() . ' property ' . $name . ' does not exist, cannot set.');
 94     }
 95     $this->$name = $value;
 96   }
 97 
 98   /**
 99    * Get the SQLite3 table name of an extending class.
100    *
101    * @return string
102    *   Name of the table, which is the plural of the class name.
103    */
104   public function getTableName() {
105     $reflect = new \ReflectionClass($this);
106     return strtolower($reflect->getShortName()) . 's';
107   }
108 
109   /**
110    * Create a persistent record.
111    */
112   public function create() {
113     $pdo = Sqlite::get();
114 
115     try {
116       $sql_query = 'INSERT INTO ' . $this->getTableName() . ' ';
117       $sql_query .= '(' . $this->externalKeyName . ', name, updated) ';
118       $sql_query .= 'VALUES (:' . $this->externalKeyName . ', :name, :updated) ';
119       $stmt = $pdo->prepare($sql_query);
120       $stmt->bindParam(':' . $this->externalKeyName, $this->{$this->externalKeyName});
121       $stmt->bindParam(':name', $this->name);
122       $stmt->bindParam(':updated', time());
123       $stmt->execute();
124       $this->id = $pdo->lastInsertId();
125     }
126     catch (\PDOException $e) {
127       switchboard_pdo_exception_debug($e);
128     }
129   }
130 
131   /**
132    * Read an environment.
133    */
134   public function read() {
135     $pdo = Sqlite::get();
136     try {
137       $sql_query = 'SELECT * ';
138       $sql_query .= 'FROM ' . $this->getTableName() . ' ';
139       // ID known.
140       if ($this->id) {
141         $sql_query .= 'WHERE id = :id ';
142         $stmt = $pdo->prepare($sql_query);
143         $stmt->bindParam(':id', $this->id);
144       }
145       // Name and id known.
146       elseif ($this->name && $this->{$this->externalKeyName}) {
147         $sql_query .= 'WHERE ' . $this->externalKeyName . ' = :' . $this->externalKeyName . ' ';
148         $sql_query .= 'AND name = :name ';
149         $stmt = $pdo->prepare($sql_query);
150         $stmt->bindParam(':' . $this->externalKeyName, $this->{$this->externalKeyName});
151         $stmt->bindParam(':name', $this->name);
152       }
153       // Not enough information.
154       else {
155         return;
156       }
157       $result = $stmt->execute();
158       if ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
159         foreach ($row as $key => $value) {
160           $this->$key = $value;
161         }
162       }
163       else {
164         if ($this->id) {
165           $this->id = NULL;
166         }
167       }
168     }
169     catch (\PDOException $e) {
170       switchboard_pdo_exception_debug($e);
171     }
172   }
173 
174   /**
175    * Update a record.
176    */
177   public function update($update = array()) {
178     $pdo = Sqlite::get();
179     if (!$this->id) {
180       $this->create();
181     }
182 
183     if (!empty($update)) {
184       foreach ($update as $key => $value) {
185         $this->$key = $value;
186       }
187     }
188 
189     $fields_to_update = array();
190 
191     // Scan changed values.
192     foreach ($this->toArray() as $key => $value) {
193       // Do not save null values, but do allow empty string.
194       if (is_null($value)) {
195         continue;
196       }
197       // Protected.
198       if (in_array($key, array('name', 'id', 'updated'))) {
199         continue;
200       }
201       // Safe to update.
202       $fields_to_update[$key] = $value;
203     }
204 
205     if (empty($fields_to_update)) {
206       return;
207     }
208 
209     try {
210       $sql_query = 'UPDATE ' . $this->getTableName() . ' SET ';
211       $sql_query_set = array();
212       foreach (array_keys($fields_to_update) as $key) {
213         $sql_query_set[] = $key . ' = ? ';
214       }
215       $sql_query .= implode(', ', $sql_query_set);
216       $sql_query .= ', updated = ? ';
217       $sql_query .= 'WHERE id = ? ';
218       $values = array_merge($fields_to_update, array(
219         'updated' => time(),
220         'id' => $this->id,
221       ));
222       $stmt = $pdo->prepare($sql_query);
223       $result = $stmt->execute(array_values($values));
224       drush_log(dt('Updated @class @external_key_id:@name - @fields_to_update', array(
225         '@class' => get_class($this),
226         '@external_key_id' => $this->{$this->externalKeyName},
227         '@name' => $this->name,
228         '@fields_to_update' => implode(', ', array_keys($fields_to_update)),
229       )));
230     }
231     catch (\PDOException $e) {
232       drush_log($sql_query);
233       drush_log(var_export($values));
234       switchboard_pdo_exception_debug($e);
235     }
236   }
237 
238   /**
239    * Delete a record.
240    */
241   public function destroy() {
242     $pdo = Sqlite::get();
243     try {
244       $stmt = $pdo->prepare('DELETE FROM ' . $this->getTableName() . ' WHERE id = :id');
245       $stmt->execute(array(
246         $this->id,
247       ));
248     }
249     catch (\PDOException $e) {
250       switchboard_pdo_exception_debug($e);
251     }
252     $this->id = NULL;
253   }
254 
255   /**
256    * Dump to an array.
257    *
258    * @return array
259    *   Property names and values.
260    */
261   public function toArray() {
262     $fields = get_object_vars($this);
263     unset($fields['externalKeyName']);
264     return $fields;
265   }
266 
267   /**
268    * Render to standard output.
269    */
270   public function render() {
271     if (drush_get_option('json')) {
272       $this->renderJson();
273     }
274     else {
275       $this->renderDrushTable();
276     }
277   }
278 
279   /**
280    * Render as a Drush table.
281    */
282   public function renderDrushTable() {
283     $fields = $this->toArray();
284     foreach ($fields as $field => &$value) {
285       $value = $this->__get($field);
286     }
287 
288     $rows = array();
289     $rows[] = array_keys($fields);
290     $rows[] = array_values($fields);
291     drush_print_table($rows, TRUE);
292   }
293 
294   /**
295    * Render as a JSON array.
296    */
297   public function renderJson() {
298     $fields = $this->toArray();
299     foreach ($fields as $field => &$value) {
300       $value = $this->__get($field);
301     }
302     drush_print(json_encode($fields));
303   }
304 }
305 
Switchboard API documentation generated by ApiGen 2.8.0