YiiWheels
  • Package
  • Class
  • Tree

Packages

  • yiiwheels
    • behaviors
    • widgets
    • widgets
      • ace
      • box
      • datepicker
      • daterangepicker
      • datetimepicker
      • detail
      • editable
      • fileupload
      • fileuploader
      • formhelpers
      • gallery
      • google
      • grid
        • behaviors
        • operations
      • highcharts
      • maskInput
      • maskmoney
      • modal
      • multiselect
      • rangeslider
      • redactor
      • select2
      • sparklines
      • switch
      • timeago
      • timepicker
      • toggle
      • typeahead

Classes

  • WhEditable
  • WhEditableColumn
  • WhEditableDetailView
  • WhEditableField
  • WhEditableSaver
  1 <?php
  2 /**
  3  * WhEditableColumn class
  4  *
  5  * Makes editable single attribute of model.
  6  *
  7  * @author Antonio Ramirez <amigo.cobos@gmail.com>
  8  * @copyright Copyright &copy; 2amigos.us 2013-
  9  * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
 10  * @package YiiWheels.widgets.editable
 11  *
 12  *
 13  * @author Vitaliy Potapov <noginsk@rambler.ru>
 14  * @link https://github.com/vitalets/x-editable-yii
 15  * @copyright Copyright &copy; Vitaliy Potapov 2012
 16  * @version 1.3.1
 17  */
 18 
 19 Yii::import('yiiwheels.widgets.editable.WhEditable');
 20 
 21 class WhEditableField extends WhEditable
 22 {
 23     /**
 24      * @var CActiveRecord ActiveRecord to be updated.
 25      */
 26     public $model = null;
 27 
 28     /**
 29      * @var string attribute name.
 30      */
 31     public $attribute = null;
 32 
 33     /**
 34      * @var instance of model that is created always:
 35      * E.g. if related model does not exist, it will be `newed` to be able to get Attribute label, etc
 36      * for live update.
 37      */
 38     private $staticModel = null;
 39 
 40 
 41     /**
 42      * initialization of widget
 43      *
 44      */
 45     public function init()
 46     {
 47         if (!$this->model) {
 48             throw new CException('Parameter "model" should be provided for EditableField');
 49         }
 50 
 51         if (!$this->attribute) {
 52             throw new CException('Parameter "attribute" should be provided for EditableField');
 53         }
 54 
 55         $originalModel = $this->model;
 56         $originalAttribute = $this->attribute;
 57         $originalText = strlen($this->text) ? $this->text : CHtml::value($this->model, $this->attribute);
 58 
 59         //if apply set manually to false --> just render text, no js plugin applied
 60         if ($this->apply === false) {
 61             $this->text = $originalText;
 62         } else {
 63             $this->apply = true;
 64         }
 65 
 66         //try to resolve related model (if attribute contains '.')
 67         $resolved = $this->resolveModels($this->model, $this->attribute);
 68         $this->model = $resolved['model'];
 69         $this->attribute = $resolved['attribute'];
 70         $this->staticModel = $resolved['staticModel'];
 71         $staticModel = $this->staticModel;
 72         $isMongo = $resolved['isMongo'];
 73         $isFormModel = $this->model instanceOf CFormModel;
 74 
 75         //if real (related) model not exists --> just print text
 76         if (!$this->model) {
 77             $this->apply = false;
 78             $this->text = $originalText;
 79         }
 80 
 81 
 82         //for security reason only safe attributes can be editable (e.g. defined in rules of model)
 83         //just print text (see 'run' method)
 84         if (!$staticModel->isAttributeSafe($this->attribute)) {
 85             $this->apply = false;
 86             $this->text = $originalText;
 87         }
 88 
 89         /*
 90          try to detect type from metadata if not set
 91         */
 92         if ($this->type === null) {
 93             $this->type = 'text';
 94             if (!$isMongo && !$isFormModel && array_key_exists($this->attribute, $staticModel->tableSchema->columns)) {
 95                 $dbType = $staticModel->tableSchema->columns[$this->attribute]->dbType;
 96                 if ($dbType == 'date') {
 97                     $this->type = 'date';
 98                 }
 99                 if ($dbType == 'datetime') {
100                     $this->type = 'datetime';
101                 }
102                 if (stripos($dbType, 'text') !== false) {
103                     $this->type = 'textarea';
104                 }
105             }
106         }
107 
108         //name
109         if (empty($this->name)) {
110             $this->name = $isMongo ? $originalAttribute : $this->attribute;
111         }
112 
113         //pk (for mongo takes pk from parent!)
114         $pkModel = $isMongo ? $originalModel : $this->model;
115         if (!$isFormModel) {
116             if ($pkModel && !$pkModel->isNewRecord) {
117                 $this->pk = $pkModel->primaryKey;
118             }
119         } else {
120             //formModel does not have pk, so set `send` option to `always` (send without pk)
121             if (empty($this->send) && empty($this->options['send'])) {
122                 $this->send = 'always';
123             }
124         }
125 
126         parent::init();
127 
128         /*
129          If text not defined, generate it from model attribute for types except lists ('select', 'checklist' etc)
130          For lists keep it empty to apply autotext.
131          $this->_prepareToAutotext calculated in parent class WhEditable.php
132         */
133         if (!strlen($this->text) && !$this->_prepareToAutotext) {
134             $this->text = $originalText;
135         }
136 
137         //set value directly for autotext generation
138         if ($this->model && $this->_prepareToAutotext) {
139             $this->value = CHtml::value($this->model, $this->attribute);
140         }
141 
142         //generate title from attribute label
143         if ($this->title === null) {
144             $titles = array(
145                 'Select' => array('select', 'date'),
146                 'Check' => array('checklist')
147             );
148             $title = Yii::t('EditableField.editable', 'Enter');
149             foreach ($titles as $t => $types) {
150                 if (in_array($this->type, $types)) {
151                     $title = Yii::t('EditableField.editable', $t);
152                 }
153             }
154             $this->title = $title . ' ' . $staticModel->getAttributeLabel($this->attribute);
155         } else {
156             $this->title = strtr($this->title, array('{label}' => $staticModel->getAttributeLabel($this->attribute)));
157         }
158 
159         //scenario
160         if ($pkModel && !isset($this->params['scenario'])) {
161             $this->params['scenario'] = $pkModel->getScenario();
162         }
163     }
164 
165     /**
166      * Returns selector
167      * @return null|string
168      */
169     public function getSelector()
170     {
171         return str_replace('\\', '_', get_class($this->staticModel)) . '_' . parent::getSelector();
172     }
173 
174 
175     /**
176      * Checks is model is instance of mongo model
177      * see: http://www.yiiframework.com/extension/yiimongodbsuite
178      *
179      * @param mixed $model
180      * @return bool
181      */
182     public static function isMongo($model)
183     {
184         return in_array('EMongoEmbeddedDocument', class_parents($model, false));
185     }
186 
187     /**
188      * Resolves model and returns array of values:
189      * - staticModel: static class of model, need for checki safety of attribute
190      * - real model: containing attribute. Can be null
191      * - attribute: it will be without dots for activerecords
192      *
193      * @param mixed $model
194      * @param mixed $attribute
195      * @return array
196      * @throws CException
197      */
198     public static function resolveModels($model, $attribute)
199     {
200         //attribute contains dot: related model, trying to resolve
201         $explode = explode('.', $attribute);
202         $len = count($explode);
203 
204         $isMongo = self::isMongo($model);
205 
206         if ($len > 1) {
207             $attribute = $explode[$len - 1];
208             //try to resolve model instance
209             $resolved = true;
210             for ($i = 0; $i < $len - 1; $i++) {
211                 $name = $explode[$i];
212                 if ($model->$name instanceof CModel) {
213                     $model = $model->$name;
214                 } else {
215                     //related model not exist! Render text only.
216                     //$this->apply = false;
217                     $resolved = false;
218                     //$this->text = $originalText;
219                     break;
220                 }
221             }
222 
223             if ($resolved) {
224                 $staticModel = $model;
225             } else { //related model not resolved: maybe not exists
226                 $relationName = $explode[$len - 2];
227                 if ($model instanceof CActiveRecord) {
228                     $className = $model->getActiveRelation($relationName)->className;
229                 } elseif ($isMongo) {
230                     $embedded = $model->embeddedDocuments();
231                     if (isset($embedded[$relationName])) {
232                         $className = $embedded[$relationName];
233                     } else {
234                         throw new CException('Embedded relation not found');
235                     }
236                 } else {
237                     throw new CException('Unsupported model class ' . $relationName);
238                 }
239                 $staticModel = new $className();
240                 $model = null;
241             }
242         } else {
243             $staticModel = $model;
244         }
245 
246         return array(
247             'model' => $model,
248             'staticModel' => $staticModel,
249             'attribute' => $attribute,
250             'isMongo' => $isMongo
251         );
252     }
253 }
254 
YiiWheels API documentation generated by ApiGen 2.8.0