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