1<?php
2
3/*
4 * This file is part of the symfony package.
5 * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
6 * (c) Jonathan H. Wage <jonwage@gmail.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12/**
13 * Base sfDoctrineRecord extends the base Doctrine_Record in Doctrine to provide some
14 * symfony specific functionality to Doctrine_Records
15 *
16 * @package    symfony
17 * @subpackage doctrine
18 * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
19 * @author     Jonathan H. Wage <jonwage@gmail.com>
20 * @version    SVN: $Id$
21 */
22abstract class sfDoctrineRecord extends Doctrine_Record
23{
24  static protected
25    $_defaultCulture = 'en';
26
27  /**
28   * Initializes internationalization.
29   *
30   * @see Doctrine_Record
31   */
32  public function construct()
33  {
34    if ($this->getTable()->hasRelation('Translation'))
35    {
36      // only add filter to each table once
37      if (!$this->getTable()->getOption('has_symfony_i18n_filter'))
38      {
39        $this->getTable()
40          ->unshiftFilter(new sfDoctrineRecordI18nFilter())
41          ->setOption('has_symfony_i18n_filter', true)
42        ;
43      }
44    }
45  }
46
47  /**
48   * Listens to the user.change_culture event.
49   *
50   * @param sfEvent An sfEvent instance
51   */
52  static public function listenToChangeCultureEvent(sfEvent $event)
53  {
54    self::$_defaultCulture = $event['culture'];
55  }
56
57  /**
58   * Sets the default culture
59   *
60   * @param string $culture
61   */
62  static public function setDefaultCulture($culture)
63  {
64    self::$_defaultCulture = $culture;
65  }
66
67  /**
68   * Return the default culture
69   *
70   * @return string the default culture
71   */
72  static public function getDefaultCulture()
73  {
74    if (!self::$_defaultCulture)
75    {
76      throw new sfException('The default culture has not been set');
77    }
78
79    return self::$_defaultCulture;
80  }
81
82  /**
83   * Returns the current record's primary key.
84   *
85   * This a proxy method to {@link Doctrine_Record::identifier()} for
86   * compatibility with a Propel-style API.
87   *
88   * @return mixed The value of the current model's last identifier column
89   */
90  public function getPrimaryKey()
91  {
92    $identifier = (array) $this->identifier();
93    return end($identifier);
94  }
95
96  /**
97   * Function require by symfony >= 1.2 admin generators.
98   *
99   * @return boolean
100   */
101  public function isNew()
102  {
103    return ! $this->exists();
104  }
105
106  /**
107   * Returns a string representation of the record.
108   *
109   * @return string A string representation of the record
110   */
111  public function __toString()
112  {
113    $guesses = array('name',
114                     'title',
115                     'description',
116                     'subject',
117                     'keywords',
118                     'id');
119
120    // we try to guess a column which would give a good description of the object
121    foreach ($guesses as $descriptionColumn)
122    {
123      try
124      {
125        return (string) $this->get($descriptionColumn);
126      } catch (Exception $e) {}
127    }
128
129    return sprintf('No description for object of class "%s"', $this->getTable()->getComponentName());
130  }
131
132  /**
133   * Provides getter and setter methods.
134   *
135   * @param  string $method    The method name
136   * @param  array  $arguments The method arguments
137   *
138   * @return mixed The returned value of the called method
139   */
140  public function __call($method, $arguments)
141  {
142    $failed = false;
143    try {
144      if (in_array($verb = substr($method, 0, 3), array('set', 'get')))
145      {
146        $name = substr($method, 3);
147
148        $table = $this->getTable();
149        if ($table->hasRelation($name))
150        {
151          $entityName = $name;
152        }
153        else if ($table->hasField($fieldName = $table->getFieldName($name)))
154        {
155          $entityNameLower = strtolower($fieldName);
156          if ($table->hasField($entityNameLower))
157          {
158            $entityName = $entityNameLower;
159          } else {
160            $entityName = $fieldName;
161          }
162        }
163        else
164        {
165          $underScored = $table->getFieldName(sfInflector::underscore($name));
166          if ($table->hasField($underScored) || $table->hasRelation($underScored))
167          {
168            $entityName = $underScored;
169          } else if ($table->hasField(strtolower($name)) || $table->hasRelation(strtolower($name))) {
170            $entityName = strtolower($name);
171          } else {
172            $camelCase = $table->getFieldName(sfInflector::camelize($name));
173            $camelCase = strtolower($camelCase[0]).substr($camelCase, 1, strlen($camelCase));
174            if ($table->hasField($camelCase) || $table->hasRelation($camelCase))
175            {
176              $entityName = $camelCase;
177            } else {
178              $entityName = $underScored;
179            }
180          }
181        }
182
183        return call_user_func_array(
184          array($this, $verb),
185          array_merge(array($entityName), $arguments)
186        );
187      } else {
188        $failed = true;
189      }
190    } catch (Exception $e) {
191      $failed = true;
192    }
193    if ($failed)
194    {
195      try
196      {
197        return parent::__call($method, $arguments);
198      } catch (Doctrine_Record_UnknownPropertyException $e2) {}
199
200      if (isset($e) && $e)
201      {
202        throw $e;
203      } else if (isset($e2) && $e2) {
204        throw $e2;
205      }
206    }
207  }
208
209  /**
210   * Get the Doctrine date value as a PHP DateTime object, null if the value is not set
211   *
212   * @param string $dateFieldName   The field name to get the DateTime object for
213   *
214   * @return DateTime|null $dateTime     The instance of PHPs DateTime
215   * @throws sfException if the field is not one of date, datetime, or timestamp types
216   */
217  public function getDateTimeObject($dateFieldName)
218  {
219    $type = $this->getTable()->getTypeOf($dateFieldName);
220    if ($type == 'date' || $type == 'timestamp' || $type == 'datetime')
221    {
222      $datetime = $this->get($dateFieldName);
223      if ($datetime)
224      {
225        return new DateTime($datetime);
226      }
227    }
228    else
229    {
230      throw new sfException('Cannot call getDateTimeObject() on a field that is not of type date or timestamp.');
231    }
232  }
233
234  /**
235   * Set the Doctrine date value by passing a valid PHP DateTime object instance
236   *
237   * @param string $dateFieldName       The field name to set the date for
238   * @param DateTime $dateTimeObject    The DateTime instance to use to set the value
239   *
240   * @return sfDoctrineRecord
241   * @throws sfException if the field is not one of date, datetime, or timestamp types
242   */
243  public function setDateTimeObject($dateFieldName, DateTime $dateTimeObject = null)
244  {
245    $type = $this->getTable()->getTypeOf($dateFieldName);
246    if ($type == 'date' || $type == 'timestamp' || $type == 'datetime')
247    {
248      if (null === $dateTimeObject)
249      {
250        return $this->set($dateFieldName, null);
251      }
252      return $this->set($dateFieldName, $dateTimeObject->format('Y-m-d H:i:s'));
253    }
254    else
255    {
256      throw new sfException('Cannot call setDateTimeObject() on a field that is not of type date or timestamp.');
257    }
258  }
259}
260