Overview

Namespaces

  • DataTables
    • Database
    • Editor
    • Vendor

Classes

  • DataTables\Database
  • DataTables\Database\Query
  • DataTables\Database\Result
  • DataTables\Editor
  • DataTables\Editor\Field
  • DataTables\Editor\Format
  • DataTables\Editor\Join
  • DataTables\Editor\Mjoin
  • DataTables\Editor\Options
  • DataTables\Editor\SearchPaneOptions
  • DataTables\Editor\Upload
  • DataTables\Editor\Validate
  • DataTables\Editor\ValidateOptions
  • DataTables\Ext
  • DataTables\Vendor\Htmlaw
  • DataTables\Vendor\htmLawed
  • Overview
  • Namespace
  • Class
  1: <?php
  2: /**
  3:  * DataTables PHP libraries.
  4:  *
  5:  * PHP libraries for DataTables and DataTables Editor, utilising PHP 5.3+.
  6:  *
  7:  *  @author    SpryMedia
  8:  *  @copyright 2012 SpryMedia ( http://sprymedia.co.uk )
  9:  *  @license   http://editor.datatables.net/license DataTables Editor
 10:  *  @link      http://editor.datatables.net
 11:  */
 12: 
 13: namespace DataTables\Editor;
 14: if (!defined('DATATABLES')) exit();
 15: 
 16: use
 17:     DataTables,
 18:     DataTables\Editor,
 19:     DataTables\Editor\Options,
 20:     DataTables\Editor\Join;
 21: 
 22: 
 23: /**
 24:  * Field definitions for the DataTables Editor.
 25:  *
 26:  * Each Database column that is used with Editor can be described with this 
 27:  * Field method (both for Editor and Join instances). It basically tells
 28:  * Editor what table column to use, how to format the data and if you want
 29:  * to read and/or write this column.
 30:  *
 31:  * Field instances are used with the {@link Editor::field} and 
 32:  * {@link Join::field} methods to describe what fields should be interacted
 33:  * with by the editable table.
 34:  *
 35:  *  @example
 36:  *    Simply get a column with the name "city". No validation is performed.
 37:  *    <code>
 38:  *      Field::inst( 'city' )
 39:  *    </code>
 40:  *
 41:  *  @example
 42:  *    Get a column with the name "first_name" - when edited a value must
 43:  *    be given due to the "required" validation from the {@link Validate} class.
 44:  *    <code>
 45:  *      Field::inst( 'first_name' )->validator( 'Validate::required' )
 46:  *    </code>
 47:  *
 48:  *  @example
 49:  *    Working with a date field, which is validated, and also has *get* and
 50:  *    *set* formatters.
 51:  *    <code>
 52:  *      Field::inst( 'registered_date' )
 53:  *          ->validator( 'Validate::dateFormat', 'D, d M y' )
 54:  *          ->getFormatter( 'Format::date_sql_to_format', 'D, d M y' )
 55:  *          ->setFormatter( 'Format::date_format_to_sql', 'D, d M y' )
 56:  *    </code>
 57:  *
 58:  *  @example
 59:  *    Using an alias in the first parameter
 60:  *    <code>
 61:  *      Field::inst( 'name.first as first_name' )
 62:  *    </code>
 63:  */
 64: class Field extends DataTables\Ext {
 65:     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 66:      * Statics
 67:      */
 68:     
 69:     /** Set option flag (`set()`) - do not set data */
 70:     const SET_NONE = 'none';
 71: 
 72:     /** Set option flag (`set()`) - write to database on both create and edit */
 73:     const SET_BOTH = 'both';
 74: 
 75:     /** Set option flag (`set()`) - write to database only on create */
 76:     const SET_CREATE = 'create';
 77: 
 78:     /** Set option flag (`set()`) - write to database only on edit */
 79:     const SET_EDIT = 'edit';
 80: 
 81: 
 82:     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 83:      * Constructor
 84:      */
 85: 
 86:     /**
 87:      * Field instance constructor.
 88:      *  @param string $dbField Name of the database column
 89:      *  @param string $name Name to use in the JSON output from Editor and the
 90:      *    HTTP submit from the client-side when editing. If not given then the
 91:      *    $dbField name is used.
 92:      */
 93:     function __construct( $dbField=null, $name=null )
 94:     {
 95:         if ( $dbField !== null && $name === null ) {
 96:             // Allow just a single parameter to be passed - each can be 
 97:             // overridden if needed later using the API.
 98:             $this->name( $dbField );
 99:             $this->dbField( $dbField );
100:         }
101:         else {
102:             $this->name( $name );
103:             $this->dbField( $dbField );
104:         }
105:     }
106: 
107: 
108: 
109:     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
110:      * Private parameters
111:      */
112: 
113:     /** @var string */
114:     private $_dbField = null;
115: 
116:     /** @var boolean */
117:     private $_get = true;
118: 
119:     /** @var mixed */
120:     private $_getFormatter = null;
121: 
122:     /** @var mixed */
123:     private $_getFormatterOpts = null;
124: 
125:     /** @var mixed */
126:     private $_getValue = null;
127: 
128:     /** @var Options */
129:     private $_opts = null;
130: 
131:     /** @var SearchPaneOptions */
132:     private $_spopts = null;
133: 
134:     /** @var callable */
135:     private $_optsFn = null;
136: 
137:     /** @var callable */
138:     private $_spoptsFn = null;
139: 
140:     /** @var string */
141:     private $_name = null;
142: 
143:     /** @var string */
144:     private $_set = Field::SET_BOTH;
145: 
146:     /** @var mixed */
147:     private $_setFormatter = null;
148: 
149:     /** @var mixed */
150:     private $_setFormatterOpts = null;
151: 
152:     /** @var mixed */
153:     private $_setValue = null;
154: 
155:     /** @var mixed */
156:     private $_validator = array();
157: 
158:     /** @var Upload */
159:     private $_upload = null;
160: 
161:     /** @var callable */
162:     private $_xss = null;
163: 
164:     /** @var boolean */
165:     private $_xssFormat = true;
166: 
167: 
168: 
169:     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
170:      * Public methods
171:      */
172: 
173: 
174:     /**
175:      * Get / set the DB field name.
176:      * 
177:      * Note that when used as a setter, an alias can be given for the field
178:      * using the SQL `as` keyword - for example: `firstName as name`. In this
179:      * situation the dbField is set to the field name before the `as`, and the
180:      * field's name (`name()`) is set to the name after the ` as `.
181:      *
182:      * As a result of this, the following constructs have identical
183:      * functionality:
184:      *
185:      *    Field::inst( 'firstName as name' );
186:      *    Field::inst( 'firstName', 'name' );
187:      *
188:      *  @param string $_ Value to set if using as a setter.
189:      *  @return string|self The name of the db field if no parameter is given,
190:      *    or self if used as a setter.
191:      */
192:     public function dbField ( $_=null )
193:     {
194:         if ( $_ === null ) {
195:             return $this->_dbField;
196:         }
197: 
198:         // Don't split on an `as` inside paraenthesis
199:         $a = preg_split( '/ as (?![^\(]*\))/i', $_ );
200:         if ( count($a) > 1 ) {
201:             $this->_dbField = trim( $a[0] );
202:             $this->_name = trim( $a[1] );
203:         }
204:         else {
205:             $this->_dbField = $_;
206:         }
207: 
208:         return $this;
209:     }
210: 
211: 
212:     /**
213:      * Get / set the 'get' property of the field.
214:      *
215:      * A field can be marked as write only when setting the get property to false
216:      * here.
217:      *  @param boolean $_ Value to set if using as a setter.
218:      *  @return boolean|self The get property if no parameter is given, or self
219:      *    if used as a setter.
220:      */
221:     public function get ( $_=null )
222:     {
223:         return $this->_getSet( $this->_get, $_ );
224:     }
225: 
226: 
227:     /**
228:      * Get formatter for the field's data.
229:      *
230:      * When the data has been retrieved from the server, it can be passed through
231:      * a formatter here, which will manipulate (format) the data as required. This
232:      * can be useful when, for example, working with dates and a particular format
233:      * is required on the client-side.
234:      *
235:      * Editor has a number of formatters available with the {@link Format} class
236:      * which can be used directly with this method.
237:      *  @param callable|string $_ Value to set if using as a setter. Can be given as
238:      *    a closure function or a string with a reference to a function that will
239:      *    be called with call_user_func().
240:      *  @param mixed $opts Variable that is passed through to the get formatting
241:      *    function - can be useful for passing through extra information such as
242:      *    date formatting string, or a required flag. The actual options available
243:      *    depend upon the formatter used.
244:      *  @return callable|string|self The get formatter if no parameter is given, or
245:      *    self if used as a setter.
246:      */
247:     public function getFormatter ( $_=null, $opts=null )
248:     {
249:         if ( $opts !== null ) {
250:             $this->_getFormatterOpts = $opts;
251:         }
252:         return $this->_getSet( $this->_getFormatter, $_ );
253:     }
254: 
255: 
256:     /**
257:      * Get / set a get value. If given, then this value is used to send to the
258:      * client-side, regardless of what value is held by the database.
259:      * 
260:      * @param callable|string|number $_ Value to set, or no value to use as a
261:      *     getter
262:      * @return callable|string|self Value if used as a getter, or self if used
263:      *     as a setter.
264:      */
265:     public function getValue ( $_=null )
266:     {
267:         return $this->_getSet( $this->_getValue, $_ );
268:     }
269: 
270: 
271:     /**
272:      * Get / set the 'name' property of the field.
273:      *
274:      * The name is typically the same as the dbField name, since it makes things
275:      * less confusing(!), but it is possible to set a different name for the data
276:      * which is used in the JSON returned to DataTables in a 'get' operation and
277:      * the field name used in a 'set' operation.
278:      *  @param string $_ Value to set if using as a setter.
279:      *  @return string|self The name property if no parameter is given, or self
280:      *    if used as a setter.
281:      */
282:     public function name ( $_=null )
283:     {
284:         return $this->_getSet( $this->_name, $_ );
285:     }
286: 
287: 
288:     /**
289:      * Get a list of values that can be used for the options list in radio,
290:      * select and checkbox inputs from the database for this field.
291:      *
292:      * Note that this is for simple 'label / value' pairs only. For more complex
293:      * data, including pairs that require joins and where conditions, use a
294:      * closure to provide a query
295:      *
296:      * @param  string|callable $table Database table name to use to get the
297:      *     paired data from, or a closure function if providing a method
298:      * @param  string          $value Table column name that contains the pair's
299:      *     value. Not used if the first parameter is given as a closure
300:      * @param  string          $label Table column name that contains the pair's
301:      *     label. Not used if the first parameter is given as a closure
302:      * @param  callable        $condition Function that will add `where`
303:      *     conditions to the query
304:      * @param  callable        $format Function will render each label
305:      * @param  string          $order SQL ordering
306:      * @return Field                  Self for chaining
307:      */
308:     public function options ( $table=null, $value=null, $label=null, $condition=null, $format=null, $order=null )
309:     {
310:         if ( $table === null ) {
311:             return $this->_opts;
312:         }
313: 
314:         // Overloads for backwards compatibility
315:         if ( is_a( $table, '\DataTables\Editor\Options' ) ) {
316:             // Options class
317:             $this->_optsFn = null;
318:             $this->_opts = $table;
319:         }
320:         else if ( is_callable($table) && is_object($table) ) {
321:             // Function
322:             $this->_opts = null;
323:             $this->_optsFn = $table;
324:         }
325:         else {
326:             $this->_optsFn = null;
327:             $this->_opts = Options::inst()
328:                 ->table( $table )
329:                 ->value( $value )
330:                 ->label( $label );
331: 
332:             if ( $condition ) {
333:                 $this->_opts->where( $condition );
334:             }
335: 
336:             if ( $format ) {
337:                 $this->_opts->render( $format );
338:             }
339: 
340:             if ( $order ) {
341:                 $this->_opts->order( $order );
342:             }
343:         }
344: 
345:         return $this;
346:     }
347: 
348:     /**
349:      * Get a list of values that can be used for the options list in SearchPanes
350:      * 
351:      * @param SearchPaneOptions|callable $spInput SearchPaneOptions instance or a closure function if providing a method
352:      * @return self
353:      */
354:     public function searchPaneOptions ( $spInput=null )
355:     {
356:         if ( $spInput === null ) {
357:             return $this->_spopts;
358:         }
359: 
360:         // Overloads for backwards compatibility
361:         if ( is_a( $spInput, '\DataTables\Editor\SearchPaneOptions' ) ) {
362:             // Options class
363:             $this->_spoptsFn = null;
364:             $this->_spopts = $spInput;
365:         }
366:         else if ( is_callable($spInput) && is_object($spInput) ) {
367:             // Function
368:             $this->_spopts = null;
369:             $this->_spoptsFn = $spInput;
370:         }
371: 
372:         return $this;
373:     }
374: 
375: 
376: 
377:     /**
378:      * Get / set the 'set' property of the field.
379:      *
380:      * A field can be marked as read only using this option, to be set only
381:      * during an create or edit action or to be set during both actions. This
382:      * provides the ability to have fields that are only set when a new row is
383:      * created (for example a "created" time stamp).
384:      *  @param string|boolean $_ Value to set when the method is being used as a
385:      *    setter (leave as undefined to use as a getter). This can take the
386:      *    value of:
387:      *    
388:      *    * `true`              - Same as `Field::SET_BOTH`
389:      *    * `false`             - Same as `Field::SET_NONE`
390:      *    * `Field::SET_BOTH`   - Set the database value on both create and edit commands
391:      *    * `Field::SET_NONE`   - Never set the database value
392:      *    * `Field::SET_CREATE` - Set the database value only on create
393:      *    * `Field::SET_EDIT`   - Set the database value only on edit
394:      *  @return string|self The set property if no parameter is given, or self
395:      *    if used as a setter.
396:      */
397:     public function set ( $_=null )
398:     {
399:         if ( $_ === true ) {
400:             $_ = Field::SET_BOTH;
401:         }
402:         else if ( $_ === false ) {
403:             $_ = Field::SET_NONE;
404:         }
405: 
406:         return $this->_getSet( $this->_set, $_ );
407:     }
408: 
409: 
410:     /**
411:      * Set formatter for the field's data.
412:      *
413:      * When the data has been retrieved from the server, it can be passed through
414:      * a formatter here, which will manipulate (format) the data as required. This
415:      * can be useful when, for example, working with dates and a particular format
416:      * is required on the client-side.
417:      *
418:      * Editor has a number of formatters available with the {@link Format} class
419:      * which can be used directly with this method.
420:      *  @param callable|string $_ Value to set if using as a setter. Can be given as
421:      *    a closure function or a string with a reference to a function that will
422:      *    be called with call_user_func().
423:      *  @param mixed $opts Variable that is passed through to the get formatting
424:      *    function - can be useful for passing through extra information such as
425:      *    date formatting string, or a required flag. The actual options available
426:      *    depend upon the formatter used.
427:      *  @return callable|string|self The set formatter if no parameter is given, or
428:      *    self if used as a setter.
429:      */
430:     public function setFormatter ( $_=null, $opts=null )
431:     {
432:         if ( $opts !== null ) {
433:             $this->_setFormatterOpts = $opts;
434:         }
435:         return $this->_getSet( $this->_setFormatter, $_ );
436:     }
437: 
438: 
439:     /**
440:      * Get / set a set value. If given, then this value is used to write to the
441:      * database regardless of what data is sent from the client-side.
442:      * 
443:      * @param callable|string|number $_ Value to set, or no value to use as a
444:      *     getter
445:      * @return callable|string|self Value if used as a getter, or self if used
446:      *     as a setter.
447:      */
448:     public function setValue ( $_=null )
449:     {
450:         return $this->_getSet( $this->_setValue, $_ );
451:     }
452: 
453: 
454:     /**
455:      * Get / set the upload class for this field.
456:      * @param  Upload $_ Upload class if used as a setter
457:      * @return Upload|self Value if used as a getter, or self if used
458:      *     as a setter.
459:      */
460:     public function upload ( $_=null )
461:     {
462:         return $this->_getSet( $this->_upload, $_ );
463:     }
464: 
465: 
466:     /**
467:      * Get / set the 'validator' of the field.
468:      *
469:      * The validator can be used to check if any abstract piece of data is valid
470:      * or not according to the given rules of the validation function used.
471:      *
472:      * Multiple validation options can be applied to a field instance by calling
473:      * this method multiple times. For example, it would be possible to have a
474:      * 'required' validation and a 'maxLength' validation with multiple calls.
475:      * 
476:      * Editor has a number of validation available with the {@link Validate} class
477:      * which can be used directly with this method.
478:      *  @param callable|string $_ Value to set if using as the validation method.
479:      *    Can be given as a closure function or a string with a reference to a 
480:      *    function that will be called with call_user_func().
481:      *  @param mixed $opts Variable that is passed through to the validation
482:      *    function - can be useful for passing through extra information such as
483:      *    date formatting string, or a required flag. The actual options available
484:      *    depend upon the validation function used.
485:      *  @return callable|string|self The validation method if no parameter is given,
486:      *    or self if used as a setter.
487:      */
488:     public function validator ( $_=null, $opts=null )
489:     {
490:         if ( $_ === null ) {
491:             return $this->_validator;
492:         }
493:         else {
494:             $this->_validator[] = array(
495:                 "func" => $_,
496:                 "opts" => $opts
497:             );
498:         }
499: 
500:         return $this;
501:     }
502: 
503: 
504:     /**
505:      * Set a formatting method that will be used for XSS checking / removal.
506:      * This should be a function that takes a single argument (the value to be
507:      * cleaned) and returns the cleaned value.
508:      *
509:      * Editor will use HtmLawed by default for this operation, which is built
510:      * into the software and no additional configuration is required, but a
511:      * custom function can be used if you wish to use a different formatter such
512:      * as HTMLPurifier.
513:      *
514:      * If you wish to disable this option (which you would only do if you are
515:      * absolutely confident that your validation will pick up on any XSS inputs)
516:      * simply provide a closure function that returns the value given to the
517:      * function. This is _not_ recommended.
518:      *
519:      * @param  callable|false $xssFormatter XSS cleaner function, use `false` or
520:      *   `null` to disable XSS cleaning.
521:      * @return Field                        Self for chaining.
522:      */
523:     public function xss ( $xssFormatter )
524:     {
525:         if ( $xssFormatter === true || $xssFormatter === false || $xssFormatter === null ) {
526:             $this->_xssFormat = $xssFormatter;
527:         }
528:         else {
529:             $this->_xss = $xssFormatter;
530:         }
531: 
532:         return $this;
533:     }
534: 
535: 
536: 
537:     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
538:      * Internal methods
539:      * Used by the Editor class and not generally for public use
540:      */
541: 
542:     /**
543:      * Check to see if a field should be used for a particular action (get or set).
544:      *
545:      * Called by the Editor / Join class instances - not expected for general
546:      * consumption - internal.
547:      *  @param string $action Direction that the data is travelling  - 'get' is
548:      *    reading DB data, `create` and `edit` for writing to the DB
549:      *  @param array $data Data submitted from the client-side when setting.
550:      *  @return boolean true if the field should be used in the get / set.
551:      *  @internal
552:      */
553:     public function apply ( $action, $data=null )
554:     {
555:         if ( $action === 'get' ) {
556:             // Get action - can we get this field
557:             return $this->_get;
558:         }
559:         else {
560:             // Note that validation must be done on input data before we get here
561: 
562:             // Create or edit action, are we configured to use this field
563:             if ( $action === 'create' &&
564:                 ($this->_set === Field::SET_NONE || $this->_set === Field::SET_EDIT)
565:             ) {
566:                 return false;
567:             }
568:             else if ( $action === 'edit' &&
569:                 ($this->_set === Field::SET_NONE || $this->_set === Field::SET_CREATE)
570:             ) {
571:                 return false;
572:             }
573: 
574:             // Check it was in the submitted data. If not, then not required
575:             // (validation would have failed if it was) and therefore we don't
576:             // set it. Check for a value as well, as it can format data from
577:             // some other source
578:             if ( $this->_setValue === null && ! $this->_inData( $this->name(), $data ) ) {
579:                 return false;
580:             }
581: 
582:             // In the data set, so use it
583:             return true;
584:         }
585:     }
586: 
587: 
588:     /**
589:      * Execute the ipOpts to get the list of options to return to the client-
590:      * side
591:      *
592:      * @param  \DataTables\Database $db Database instance
593:      * @return Array        Array of value / label options for the list
594:      * @internal
595:      */
596:     public function optionsExec ( $db )
597:     {
598:         if ( $this->_optsFn ) {
599:             $fn = $this->_optsFn;
600:             return $fn();
601:         }
602:         else if ( $this->_opts ) {
603:             return $this->_opts->exec( $db );
604:         }
605: 
606:         return false;
607:     }
608: 
609:     /**
610:      * Execute the spopts to get the list of options for SearchPanes to return
611:      * to the client-side
612:      * 
613:      * @param DataTables\Field $field The field to retrieve the data from
614:      * @param DataTables\Editor $editor The editor instance
615:      * @param DataTables\DTRequest $http The http request sent to the server
616:      * @param DataTables\Field[] $fields All of the fields
617:      * @param any $leftJoin Info for a leftJoin if required
618:      * @return Promise<IOption[]> | boolean
619:      * @internal
620:      */
621:     public function searchPaneOptionsExec ( $field, $editor, $http, $fields, $leftJoin)
622:     {
623:         if ( $this->_spoptsFn ) {
624:             $fn = $this->_spoptsFn;
625:             return $fn($editor->db(), $editor);
626:         }
627:         else if ( $this->_spopts ) {
628:             return $this->_spopts->exec( $field, $editor, $http, $fields, $leftJoin );
629:         }
630: 
631:         return false;
632:     }
633: 
634:     
635:     /**
636:      * Get the value of the field, taking into account if it is coming from the
637:      * DB or from a POST. If formatting has been specified for this field, it
638:      * will be applied here.
639:      *
640:      * Called by the Editor / Join class instances - not expected for general
641:      * consumption - internal.
642:      *  @param string $direction Direction that the data is travelling  - 'get' is
643:      *    reading data, and 'set' is writing it to the DB.
644:      *  @param array $data Data submitted from the client-side when setting or the
645:      *    data for the row when getting data from the DB.
646:      *  @return string Value for the field
647:      *  @internal
648:      */
649:     public function val ( $direction, $data )
650:     {
651:         if ( $direction === 'get' ) {
652:             if ( $this->_getValue !== null ) {
653:                 $val = $this->_getAssignedValue( $this->_getValue );
654:             }
655:             else {
656:                 // Getting data, so the db field name
657:                 $val = isset( $data[ $this->_dbField ] ) ?
658:                     $data[ $this->_dbField ] :
659:                     null;
660:             }
661: 
662:             return $this->_format(
663:                 $val, $data, $this->_getFormatter, $this->_getFormatterOpts
664:             );
665:         }
666:         else {
667:             // Sanity check that we aren't operating on a function
668:             if ( strpos( $this->dbField(), '(' ) !== false ) {
669:                 throw new \Exception('Cannot set the value for an SQL function field. These fields are read only.');
670:             }
671: 
672:             // Setting data, so using from the payload (POST usually) and thus
673:             // use the 'name'
674:             $val = $this->_setValue !== null ?
675:                 $this->_getAssignedValue( $this->_setValue ) :
676:                 $this->_readProp( $this->name(), $data );
677: 
678:             // XSS removal / checker
679:             if ( $this->_xssFormat ) {
680:                 $val = $this->xssSafety( $val );
681:             }
682: 
683:             return $this->_format(
684:                 $val, $data, $this->_setFormatter, $this->_setFormatterOpts
685:             );
686:         }
687:     }
688: 
689: 
690:     /**
691:      * Check the validity of the field based on the data submitted. Note that
692:      * this validation is performed on the wire data - i.e. that which is
693:      * submitted, before any setFormatter is run
694:      *
695:      * Called by the Editor / Join class instances - not expected for general
696:      * consumption - internal.
697:      *
698:      * @param array $data Data submitted from the client-side 
699:      * @param Editor $editor Editor instance
700:      * @param mixed $id Row id that is being validated
701:      * @return boolean|string `true` if valid, string with error message if not
702:      * @internal
703:      */
704:     public function validate ( $data, $editor, $id=null )
705:     {
706:         // Three cases for the validator - closure, string or null
707:         if ( ! count( $this->_validator ) ) {
708:             return true;
709:         }
710: 
711:         $val = $this->_readProp( $this->name(), $data );
712:         $processData = $editor->inData();
713:         $instances = array(
714:             'action' => $processData['action'],
715:             'id'     => $id,
716:             'field'  => $this,
717:             'editor' => $editor,
718:             'db'     => $editor->db()
719:         );
720: 
721:         for ( $i=0, $ien=count( $this->_validator ) ; $i<$ien ; $i++ ) {
722:             $validator = $this->_validator[$i];
723: 
724:             // Backwards compatibility
725:             if ( is_string( $validator['func'] ) ) {
726:                 if ( strpos($validator['func'], "Validate::") === 0 ) {
727:                     $a = explode("::", $validator['func']);
728: 
729:                     // Validate class static methods - they have `Legacy` counter parts that
730:                     // convert from the old style to the new so the old style options still work.
731:                     if ( method_exists( "\\DataTables\\Editor\\".$a[0], $a[1].'Legacy' ) ) {
732:                         $func = call_user_func( "\\DataTables\\Editor\\".$validator['func'].'Legacy', $validator['opts'] );
733:                         $res = call_user_func( $func, $val, $data, $this, $instances );
734:                     }
735:                     else {
736:                         // User style legacy function. Call it directly
737:                         $func = "\\DataTables\\Editor\\".$validator['func'];
738:                         $res = call_user_func( $func, $val, $data, $this, $instances );
739:                     }
740:                 }
741:                 else {
742:                     // And for cases where a string was used to point to a function,
743:                     // which was not in the Validate class
744:                     $res = call_user_func( $validator['func'], $val, $data, $validator['opts'], $instances );
745:                 }
746:             }
747:             else {
748:                 $func = $validator['func'];
749:                 $res = $func( $val, $data, $this, $instances );
750:             }
751: 
752:             // Check if there was a validation error and if so, return it
753:             if ( $res !== true ) {
754:                 return $res;
755:             }
756:         }
757: 
758:         // Validation methods all run, must be valid
759:         return true;
760:     }
761: 
762: 
763:     /**
764:      * Write the value for this field to the output array for a read operation
765:      *
766:      * @param  array $out     Row output data (to the JSON)
767:      * @param  mixed $srcData Row input data (raw, from the database)
768:      * @internal
769:      */
770:     public function write( &$out, $srcData )
771:     {
772:         $this->_writeProp( $out, $this->name(), $this->val('get', $srcData) );
773:     }
774: 
775: 
776:     /**
777:      * Perform XSS prevention on an input.
778:      *
779:      * @param  mixed $val Value to be escaped
780:      * @return string Safe value
781:      */
782:     public function xssSafety ( $val ) {
783:         $xss = $this->_xss;
784: 
785:         if ( is_array( $val ) ) {
786:             $res = array();
787: 
788:             foreach ( $val as $individual ) {
789:                 $res[] = $xss ?
790:                     $xss( $individual ) :
791:                     DataTables\Vendor\Htmlaw::filter( $individual );
792:             }
793: 
794:             return $res;
795:         }
796: 
797:         return $xss ?
798:             $xss( $val ) :
799:             DataTables\Vendor\Htmlaw::filter( $val );
800:     }
801: 
802: 
803: 
804:     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
805:      * Private methods
806:      */
807: 
808:     /**
809:      * Apply a formatter to data. The caller will decide what formatter to apply
810:      * (get or set)
811:      *
812:      * @param  mixed    $val       Value to be formatted
813:      * @param  mixed    $data      Full row data
814:      * @param  callable $formatter Formatting function to be called
815:      * @param  array    $opts      Array of options to be passed to the formatter
816:      * @return mixed               Formatted value
817:      */
818:     private function _format( $val, $data, $formatter, $opts )
819:     {
820:         // Three cases for the formatter - closure, string or null
821:         if ( ! $formatter ) {
822:             return $val;
823:         }
824: 
825:         if ( ! is_string( $formatter ) ) {
826:             return $formatter( $val, $data, $opts );
827:         }
828: 
829:         // Backwards compatibility - strings will not be supported in v2
830:         if ( strpos($formatter, "Format::") === 0 ) {
831:             $a = explode( '::', $formatter );
832: 
833:             // Old style Editor formatter - use the legacy functions to
834:             // convert to the new style
835:             if ( method_exists( "\\DataTables\\Editor\\".$a[0], $a[1].'Legacy' ) ) {
836:                 $func = call_user_func( "\\DataTables\\Editor\\".$formatter.'Legacy', $opts );
837: 
838:                 return $func( $val, $data );
839:             }
840:             else {
841:                 // User added old style methods
842:                 return call_user_func( "\\DataTables\\Editor\\".$formatter, $val, $data, $opts );
843:             }
844:         }
845: 
846:         // User function (string identifier)
847:         return call_user_func( $formatter, $val, $data, $opts );
848:     }
849: 
850:     /**
851:      * Get the value from `_[gs]etValue` - taking into account if it is callable
852:      * function or not
853:      *
854:      * @param  mixed $val Value to be evaluated
855:      * @return mixed      Value assigned, or returned from the function
856:      */
857:     private function _getAssignedValue ( $val )
858:     {
859:         return is_callable($val) && is_object($val) ?
860:             $val() :
861:             $val;
862:     }
863: 
864:     /**
865:      * Check is a parameter is in the submitted data set. This is functionally
866:      * the same as the `_readProp()` method, but in this case a binary value
867:      * is required to indicate if the value is present or not.
868:      *
869:      * @param  string $name  Javascript dotted object name to write to
870:      * @param  array  $data   Data source array to read from
871:      * @return boolean       `true` if present, `false` otherwise
872:      * @private
873:      */
874:     private function _inData ( $name, $data )
875:     {
876:         if ( strpos($name, '.') === false ) {
877:             return isset( $data[ $name ] ) ?
878:                 true :
879:                 false;
880:         }
881: 
882:         $names = explode( '.', $name );
883:         $inner = $data;
884: 
885:         for ( $i=0 ; $i<count($names)-1 ; $i++ ) {
886:             if ( ! isset( $inner[ $names[$i] ] ) ) {
887:                 return false;
888:             }
889: 
890:             $inner = $inner[ $names[$i] ];
891:         }
892: 
893:         return isset( $inner [ $names[count($names)-1] ] ) ?
894:             true :
895:             false;
896:     }
897: }
898: 
899: 
DataTables Editor 1.9.4 - PHP libraries API documentation generated by ApiGen