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\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-2014 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 DataTables\Editor\ValidateOptions;
  17: 
  18: /**
  19:  * Validation methods for DataTables Editor fields.
  20:  *
  21:  * These methods will typically be applied through the {@link Field::validator}
  22:  * method and thus the arguments to be passed will be automatically resolved
  23:  * by Editor.
  24:  *
  25:  * The validation methods in this class all take three parameters:
  26:  *
  27:  * 1. Data to be validated
  28:  * 2. Full data from the form (this can be used with a custom validation method
  29:  *    for dependent validation).
  30:  * 3. Validation configuration options.
  31:  *
  32:  * When using the `Validate` class functions with the {@link Field::validator}
  33:  * method, the second parameter passed into {@link Field::validator} is given
  34:  * to the validation functions here as the third parameter. The first and
  35:  * second parameters are automatically resolved by the {@link Field} class.
  36:  *
  37:  * The validation configuration options is an array of options that can be used
  38:  * to customise the validation - for example defining a date format for date
  39:  * validation. Each validation method has the option of defining its own
  40:  * validation options, but all validation methods provide four common options:
  41:  *
  42:  * * `{boolean} optional` - Require the field to be submitted (`false`) or not
  43:  *   (`true` - default). When set to `true` the field does not need to be
  44:  *   included in the list of parameters sent by the client - if set to `false`
  45:  *   then it must be included. This option can be be particularly used in Editor
  46:  *   as Editor will not set a value for fields which have not been submitted -
  47:  *   giving the ability to submit just a partial list of options.
  48:  * * `{boolean} empty` - Allow a field to be empty, i.e. a zero length string -
  49:  *   `''` (`true` - default) or require it to be non-zero length (`false`).
  50:  * * `{boolean} required` - Short-cut for `optional=false` and `empty=false`.
  51:  *   Note that if this option is set the `optional` and `empty` parameters are
  52:  *   automatically set and cannot be overridden by passing in different values.
  53:  * * `{string} message` - Error message shown should validation fail. This
  54:  *   provides complete control over the message shown to the end user, including
  55:  *   internationalisation (i.e. to provide a translation that is not in the
  56:  *   English language).
  57:  *
  58:  *  @example
  59:  *    <code>
  60:  *      // Ensure that a non-empty value is given for a field
  61:  *      Field::inst( 'engine' )->validator( Validate::required() )
  62:  *    </code>
  63:  *
  64:  *  @example
  65:  *    <code>
  66:  *      // Don't require a field to be submitted, but if it is submitted, it
  67:  *      // must be non-empty
  68:  *      Field::inst( 'reg_date' )->validator( Validate::notEmpty() )
  69:  *    </code>
  70:  *
  71:  *  @example
  72:  *    <code>
  73:  *      // Date validation
  74:  *      Field::inst( 'reg_date' )->validator( Validate::dateFormat( 'D, d M y' ) )
  75:  *    </code>
  76:  *
  77:  *  @example
  78:  *    <code>
  79:  *      // Date validation with a custom error message
  80:  *      Field::inst( 'reg_date' )->validator( Validate::dateFormat( 'D, d M y',
  81:  *          ValidateOptions::inst()
  82:  *              ->message( 'Invalid date' )
  83:  *      ) )
  84:  *    </code>
  85:  *
  86:  *  @example
  87:  *    <code>
  88:  *      // Require a non-empty e-mail address
  89:  *      Field::inst( 'reg_date' )->validator( Validate::email( ValidateOptions::inst()
  90:  *        ->empty( false )
  91:  *      ) )
  92:  *    </code>
  93:  *
  94:  *  @example
  95:  *    <code>
  96:  *      // Custom validation - closure
  97:  *      Field::inst( 'engine' )->validator( function($val, $data, $opts) {
  98:  *         if ( ! preg_match( '/^1/', $val ) ) {
  99:  *           return "Value <b>must</b> start with a 1";
 100:  *         }
 101:  *         return true;
 102:  *      } )
 103:  *    </code>
 104:  */
 105: class Validate {
 106:     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 107:      * Internal functions
 108:      */
 109: 
 110:     /**
 111:      * "Magic" method to automatically apply the required check to any of the
 112:      * static methods simply by adding '_required' or '_empty' to the end of the
 113:      * method's name, depending on if you need the field to be submitted or not.
 114:      *
 115:      * This is retained for backwards compatibility, but the validation options
 116:      * are now the recommended way of indicating that a field is required.
 117:      *
 118:      * @internal
 119:      * @param string $name Function name
 120:      * @param array $arguments Function arguments
 121:      * @return mixed|string
 122:      */
 123:     public static function __callStatic( $name, $arguments ) {
 124:         if ( preg_match( '/_required$/', $name ) ) {
 125:             if ( $arguments[0] === null || $arguments[0] === '' ) {
 126:                 return 'This field is required';
 127:             }
 128: 
 129:             return call_user_func_array( 
 130:                 __NAMESPACE__.'\Validate::'.str_replace( '_required', '', $name ),
 131:                 $arguments
 132:             );
 133:         }
 134:     }
 135: 
 136: 
 137:     /**
 138:      * Extend the options from the user function and the validation function
 139:      * with core defaults.
 140:      *
 141:      *  @internal
 142:      */
 143:     public static function _extend( $userOpts, $prop, $fnOpts ) {
 144:         $cfg = array(
 145:             'message'  => 'Input not valid',
 146:             'required' => false,
 147:             'empty'    => true,
 148:             'optional' => true
 149:         );
 150: 
 151:         if ( ! is_array( $userOpts ) ) {
 152:             if ( $prop ) {
 153:                 $cfg[ $prop ] = $userOpts;
 154:             }
 155: 
 156:             // Not an array, but the non-array case has been handled above, so
 157:             // just an empty array
 158:             $userOpts = array();
 159:         }
 160: 
 161:         // Merge into a single array - first array gets priority if there is a
 162:         // key clash, so user first, then function commands and finally the
 163:         // global options 
 164:         $cfg = $userOpts + $fnOpts + $cfg;
 165: 
 166:         return $cfg;
 167:     }
 168: 
 169: 
 170:     /**
 171:      * Perform common validation using the configuration parameters
 172:      *
 173:      *  @internal
 174:      */
 175:     public static function _common( $val, $opts ) {
 176:         $optional = $opts->optional();
 177:         $empty    = $opts->allowEmpty();
 178: 
 179:         // Error state tests
 180:         if ( ! $optional && $val === null  ) {
 181:             // Value must be given
 182:             return false;
 183:         }
 184:         else if ( $empty === false && $val === '' ) {
 185:             // Value must not be empty
 186:             return false;
 187:         }
 188:         
 189:         // Validation passed states
 190:         if ( $optional && $val === null ) {
 191:             return true;
 192:         }
 193:         else if ( $empty === true && $val === '' ) {
 194:             return true;
 195:         }
 196: 
 197:         // Have the specific validation function perform its tests
 198:         return null;
 199:     }
 200: 
 201:     /**
 202:      * Convert the old style validation parameters into ValidateOptions
 203:      *
 204:      *  @internal
 205:      */
 206:     public static function _commonLegacy( $cfg ) {
 207:         $opts = new ValidateOptions();
 208: 
 209:         if ( is_array( $cfg ) ) {
 210:             // `required` is a legacy shortcut for optional=false, empty=false
 211:             if ( isset( $cfg['required'] ) ) {
 212:                 $opts->optional( false );
 213:                 $opts->allowEmpty( false );
 214:             }
 215: 
 216:             if ( isset( $cfg['empty'] ) ) {
 217:                 $opts->allowEmpty( $cfg['empty'] );
 218:             }
 219: 
 220:             if ( isset( $cfg['message'] ) ) {
 221:                 $opts->message( $cfg['message'] );
 222:             }
 223: 
 224:             if ( isset( $cfg['optional'] ) ) {
 225:                 $opts->optional( $cfg['optional'] );
 226:             }
 227:         }
 228: 
 229:         return $opts;
 230:     }
 231: 
 232: 
 233: 
 234:     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 235:      * Basic validation
 236:      */
 237: 
 238:     /**
 239:      * No validation - all inputs are valid.
 240:      *  @return callable Validation function
 241:      */
 242:     public static function none() {
 243:         return function ( $val, $data, $field, $host ) {
 244:             return true;
 245:         };
 246:     }
 247: 
 248: 
 249:     /**
 250:      * Basic validation - this is used to perform the validation provided by the
 251:      * validation options only. If the validation options pass (e.g. `required`,
 252:      * `empty` and `optional`) then the validation will pass regardless of the
 253:      * actual value.
 254:      *
 255:      * Note that there are two helper short-cut methods that provide the same
 256:      * function as this method, but are slightly shorter:
 257:      *
 258:      * ```
 259:      * // Required:
 260:      * Validate::required()
 261:      *
 262:      * // is the same as
 263:      * Validate::basic( $val, $data, array(
 264:      *   "required" => true
 265:      * );
 266:      * ```
 267:      *
 268:      * ```
 269:      * // Optional, but not empty if given:
 270:      * Validate::notEmpty()
 271:      *
 272:      * // is the same as
 273:      * Validate::basic( $val, $data, array(
 274:      *   "empty" => false
 275:      * );
 276:      * ```
 277:      *
 278:      * @param string $val The value to check for validity
 279:      * @param string[] $data The full data set submitted
 280:      * @param array $opts Validation options. No additional options are
 281:      *    available or required for this validation method.
 282:      * @param array $host Host information
 283:      * @return string|true true if the value is valid, a string with an error
 284:      *    message otherwise.
 285:      */
 286:     static function basic( $cfg=null ) {
 287:         $opts = ValidateOptions::select( $cfg );
 288: 
 289:         return function ( $val, $data, $field, $host ) use ( $opts ) {
 290:             $common = Validate::_common( $val, $opts );
 291: 
 292:             return $common === false ?
 293:                 $opts->message() :
 294:                 true;
 295:         };
 296:     }
 297: 
 298: 
 299:     /**
 300:      * Required field - there must be a value and it must be a non-empty value
 301:      *
 302:      * This is a helper short-cut method which is the same as:
 303:      * 
 304:      * ```
 305:      * Validate::basic( $val, $data, array(
 306:      *   "required" => true
 307:      * );
 308:      * ```
 309:      * 
 310:      *  @param string $val The value to check for validity
 311:      *  @param string[] $data The full data set submitted
 312:      *  @param array $opts Validation options. No additional options are
 313:      *    available or required for this validation method.
 314:      * @param array $host Host information
 315:      *  @return string|true true if the value is valid, a string with an error
 316:      *    message otherwise.
 317:      */
 318:     static function required( $cfg=null ) {
 319:         $opts = ValidateOptions::select( $cfg );
 320:         $opts->allowEmpty( false );
 321:         $opts->optional( false );
 322: 
 323:         return function ( $val, $data, $field, $host ) use ( $opts ) {
 324:             $common = Validate::_common( $val, $opts );
 325: 
 326:             return $common === false ?
 327:                 $opts->message() :
 328:                 true;
 329:         };
 330:     }
 331: 
 332: 
 333:     /**
 334:      * Optional field, but if given there must be a non-empty value
 335:      *
 336:      * This is a helper short-cut method which is the same as:
 337:      * 
 338:      * ```
 339:      * Validate::basic( $val, $data, array(
 340:      *   "empty" => false
 341:      * );
 342:      * ```
 343:      *
 344:      *  @param ValidateOptions $cfg Validation options
 345:      *  @return callable Validation function
 346:      */
 347:     static function notEmpty( $cfg=null ) {
 348:         $opts = ValidateOptions::select( $cfg );
 349:         $opts->allowEmpty( false );
 350: 
 351:         return function ( $val, $data, $field, $host ) use ( $opts ) {
 352:             $common = Validate::_common( $val, $opts );
 353: 
 354:             return $common === false ?
 355:                 $opts->message() :
 356:                 true;
 357:         };
 358:     }
 359: 
 360: 
 361:     /**
 362:      * Validate an input as a boolean value.
 363:      *
 364:      *  @param string $val The value to check for validity
 365:      *  @param string[] $data The full data set submitted
 366:      *  @param array $opts Validation options. No additional options are
 367:      *    available or required for this validation method.
 368:      *  @param array $host Host information
 369:      *  @return string|true true if the value is valid, a string with an error
 370:      *    message otherwise.
 371:      */
 372:     public static function boolean( $cfg=null ) {
 373:         $opts = ValidateOptions::select( $cfg );
 374: 
 375:         return function ( $val, $data, $field, $host ) use ( $opts ) {
 376:             $common = Validate::_common( $val, $opts );
 377: 
 378:             if ( $common !== null ) {
 379:                 return $common === false ?
 380:                     $opts->message() :
 381:                     $common;
 382:             }
 383:     
 384:             if ( filter_var($val, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) === null ) {
 385:                 return $opt->message();
 386:             }
 387:             return true;
 388:         };
 389:     }
 390: 
 391: 
 392: 
 393:     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 394:      * Number validation methods
 395:      */
 396: 
 397:     /**
 398:      * Check that any input is numeric.
 399:      *
 400:      *  @param string $val The value to check for validity
 401:      *  @param string[] $data The full data set submitted
 402:      *  @param array $opts Validation options. Additional options:
 403:      *     * `decimal`: is available to indicate what character should be used
 404:      *       as the decimal
 405:      *  @param array $host Host information
 406:      *  @return string|true true if the value is valid, a string with an error
 407:      *    message otherwise.
 408:      */
 409:     public static function numeric ( $decimal=".", $cfg=null ) {
 410:         $opts = ValidateOptions::select( $cfg );
 411: 
 412:         return function ( $val, $data, $field, $host ) use ( $opts, $decimal ) {
 413:             $common = Validate::_common( $val, $opts );
 414: 
 415:             if ( $common !== null ) {
 416:                 return $common === false ?
 417:                     $opts->message() :
 418:                     $common;
 419:             }
 420:     
 421:             if ( $decimal !== '.' ) {
 422:                 $val = str_replace( $decimal, '.', $val );
 423:             }
 424:     
 425:             return ! is_numeric( $val ) ?
 426:                 $opts->message() :
 427:                 true;
 428:         };
 429:     }
 430: 
 431:     /**
 432:      * Check for a numeric input and that it is greater than a given value.
 433:      *
 434:      *  @param string $val The value to check for validity
 435:      *  @param string[] $data The full data set submitted
 436:      *  @param int|array $opts Validation options. Additional options:
 437:      *     * `min`: indicate the minimum value. If only the default validation
 438:      *       options are required, this parameter can be given as an integer
 439:      *       value, which will be used as the minimum value.
 440:      *     * `decimal`: is available to indicate what character should be used
 441:      *       as the decimal
 442:      *    separator (default '.').
 443:      *  @param array $host Host information
 444:      *  @return string|true true if the value is valid, a string with an error
 445:      *    message otherwise.
 446:      */
 447:     public static function minNum ( $min, $decimal=".", $cfg=null ) {
 448:         $opts = ValidateOptions::select( $cfg );
 449: 
 450:         return function ( $val, $data, $field, $host ) use ( $opts, $min, $decimal ) {
 451:             $common = Validate::_common( $val, $opts );
 452:             
 453:             if ( $common !== null ) {
 454:                 return $common === false ?
 455:                     $opts->message() :
 456:                     $common;
 457:             }
 458:             
 459:             $fn = Validate::numeric( $decimal, $opts );
 460:             $numeric = $fn( $val, $data, $field, $host );
 461: 
 462:             if ( $numeric !== true ) {
 463:                 return $numeric;
 464:             }
 465:     
 466:             if ( $decimal !== '.' ) {
 467:                 $val = str_replace( $decimal, '.', $val );
 468:             }
 469:     
 470:             return $val < $min ?
 471:                 $opts->message() :
 472:                 true;
 473:         };
 474:     }
 475: 
 476:     /**
 477:      * Check for a numeric input and that it is less than a given value.
 478:      *
 479:      *  @param string $val The value to check for validity
 480:      *  @param string[] $data The full data set submitted
 481:      *  @param int|array $opts Validation options.
 482:      *     * `max`: indicate the maximum value. If only the default validation
 483:      *       options are required, this parameter can be given as an integer
 484:      *       value, which will be used as the maximum value.
 485:      *     * `decimal`: is available to indicate what character should be used
 486:      *       as the decimal
 487:      *  @param array $host Host information
 488:      *  @return string|true true if the value is valid, a string with an error
 489:      *    message otherwise.
 490:      */
 491:     public static function maxNum ( $max, $decimal=".", $cfg=null ) {
 492:         $opts = ValidateOptions::select( $cfg );
 493: 
 494:         return function ( $val, $data, $field, $host ) use ( $opts, $max, $decimal ) {
 495:             $common = Validate::_common( $val, $opts );
 496:             
 497:             if ( $common !== null ) {
 498:                 return $common === false ?
 499:                     $opts->message() :
 500:                     $common;
 501:             }
 502:             
 503:             $fn = Validate::numeric( $decimal, $opts );
 504:             $numeric = $fn( $val, $data, $field, $host );
 505: 
 506:             if ( $numeric !== true ) {
 507:                 return $numeric;
 508:             }
 509:     
 510:             if ( $decimal !== '.' ) {
 511:                 $val = str_replace( $decimal, '.', $val );
 512:             }
 513:     
 514:             return $val > $max ?
 515:                 $opts->message() :
 516:                 true;
 517:         };
 518:     }
 519: 
 520: 
 521:     /**
 522:      * Check for a numeric input and that it is both greater and smaller than
 523:      * given numbers.
 524:      *
 525:      *  @param string $val The value to check for validity
 526:      *  @param string[] $data The full data set submitted
 527:      *  @param int|array $opts Validation options. Additional options:
 528:      *     * `min`: indicate the minimum value.
 529:      *     * `max`: indicate the maximum value.
 530:      *     * `decimal`: is available to indicate what character should be used
 531:      *       as the decimal
 532:      *  @param array $host Host information
 533:      *  @return string|true true if the value is valid, a string with an error
 534:      *    message otherwise.
 535:      */
 536:     public static function minMaxNum ( $min, $max, $decimal='.', $cfg=null ) {
 537:         $opts = ValidateOptions::select( $cfg );
 538:         
 539:         return function ( $val, $data, $field, $host ) use ( $opts, $min, $max, $decimal ) {
 540:             $common = Validate::_common( $val, $opts );
 541:             
 542:             if ( $common !== null ) {
 543:                 return $common === false ?
 544:                     $opts->message() :
 545:                     $common;
 546:             }
 547:             
 548:             $fn = Validate::numeric( $decimal, $opts );
 549:             $numeric = $fn( $val, $data, $field, $host );
 550: 
 551:             if ( $numeric !== true ) {
 552:                 return $numeric;
 553:             }
 554: 
 555:             $fn = Validate::minNum( $min, $decimal, $opts );
 556:             $numeric = $fn( $val, $data, $field, $host );
 557: 
 558:             if ( $numeric !== true ) {
 559:                 return $numeric;
 560:             }
 561:             
 562:             $fn = Validate::maxNum( $max, $decimal, $opts );
 563:             $numeric = $fn( $val, $data, $field, $host );
 564: 
 565:             if ( $numeric !== true ) {
 566:                 return $numeric;
 567:             }
 568: 
 569:             return true;
 570:         };
 571:     }
 572: 
 573: 
 574: 
 575:     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 576:      * String validation methods
 577:      */
 578: 
 579:     /**
 580:      * Validate an input as an e-mail address.
 581:      *
 582:      *  @param string $val The value to check for validity
 583:      *  @param string[] $data The full data set submitted
 584:      *  @param array $opts Validation options. No additional options are
 585:      *    available or required for this validation method.
 586:      *  @param array $host Host information
 587:      *  @return string|true true if the value is valid, a string with an error
 588:      *    message otherwise.
 589:      */
 590:     public static function email( $cfg=null ) {
 591:         $opts = ValidateOptions::select( $cfg );
 592:         
 593:         return function ( $val, $data, $field, $host ) use ( $opts ) {
 594:             $common = Validate::_common( $val, $opts );
 595: 
 596:             if ( $common !== null ) {
 597:                 return $common === false ?
 598:                     $opts->message() :
 599:                     $common;
 600:             }
 601: 
 602:             return filter_var($val, FILTER_VALIDATE_EMAIL) !== false ?
 603:                 true :
 604:                 $opts->message();
 605:         };
 606:     }
 607: 
 608: 
 609:     /**
 610:      * Validate a string has a minimum length.
 611:      *
 612:      *  @param string $val The value to check for validity
 613:      *  @param string[] $data The full data set submitted
 614:      *  @param int|array $opts Validation options. The additional option of
 615:      *    `min` is available for this method to indicate the minimum string
 616:      *    length. If only the default validation options are required, this
 617:      *    parameter can be given as an integer value, which will be used as the
 618:      *    minimum string length.
 619:      *  @param array $host Host information
 620:      *  @return string|true true if the value is valid, a string with an error
 621:      *    message otherwise.
 622:      */
 623:     public static function minLen( $min, $cfg=null ) {
 624:         $opts = ValidateOptions::select( $cfg );
 625:         
 626:         return function ( $val, $data, $field, $host ) use ( $min, $opts ) {
 627:             $common = Validate::_common( $val, $opts );
 628: 
 629:             if ( $common !== null ) {
 630:                 return $common === false ?
 631:                     $opts->message() :
 632:                     $common;
 633:             }
 634:     
 635:             return strlen( $val ) < $min ?
 636:                 $opts->message() :
 637:                 true;
 638:         };
 639:     }
 640: 
 641: 
 642:     /**
 643:      * Validate a string does not exceed a maximum length.
 644:      *
 645:      *  @param string $val The value to check for validity
 646:      *  @param string[] $data The full data set submitted
 647:      *  @param int|array $opts Validation options. The additional option of
 648:      *    `max` is available for this method to indicate the maximum string
 649:      *    length. If only the default validation options are required, this
 650:      *    parameter can be given as an integer value, which will be used as the
 651:      *    maximum string length.
 652:      *  @param array $host Host information
 653:      *  @return string|true true if the value is valid, a string with an error
 654:      *    message otherwise.
 655:      */
 656:     public static function maxLen( $max, $cfg=null ) {
 657:         $opts = ValidateOptions::select( $cfg );
 658:         
 659:         return function ( $val, $data, $field, $host ) use ( $max, $opts ) {
 660:             $common = Validate::_common( $val, $opts );
 661: 
 662:             if ( $common !== null ) {
 663:                 return $common === false ?
 664:                     $opts->message() :
 665:                     $common;
 666:             }
 667:     
 668:             return strlen( $val ) > $max ?
 669:                 $opts->message() :
 670:                 true;
 671:         };
 672:     }
 673: 
 674:     /**
 675:      * Require a string with a certain minimum or maximum number of characters.
 676:      *
 677:      *  @param string $val The value to check for validity
 678:      *  @param string[] $data The full data set submitted
 679:      *  @param int|array $opts Validation options. The additional options of
 680:      *    `min` and `max` are available for this method to indicate the minimum
 681:      *    and maximum string lengths, respectively.
 682:      *  @param array $host Host information
 683:      *  @return string|true true if the value is valid, a string with an error
 684:      *    message otherwise.
 685:      */
 686:     public static function minMaxLen( $min, $max, $cfg=null ) {
 687:         $opts = ValidateOptions::select( $cfg );
 688:         
 689:         return function ( $val, $data, $field, $host ) use ( $opts, $min, $max ) {
 690:             $common = Validate::_common( $val, $opts );
 691:             
 692:             if ( $common !== null ) {
 693:                 return $common === false ?
 694:                     $opts->message() :
 695:                     $common;
 696:             }
 697:             
 698:             $fn = Validate::minLen( $min, $opts );
 699:             $res = $fn( $val, $data, $field, $host );
 700: 
 701:             if ( $res !== true ) {
 702:                 return $res;
 703:             }
 704:             
 705:             $fn = Validate::maxLen( $max, $opts );
 706:             $res = $fn( $val, $data, $field, $host );
 707: 
 708:             if ( $res !== true ) {
 709:                 return $res;
 710:             }
 711: 
 712:             return true;
 713:         };
 714:     }
 715: 
 716: 
 717:     /**
 718:      * Validate as an IP address.
 719:      *
 720:      *  @param string $val The value to check for validity
 721:      *  @param string[] $data The full data set submitted
 722:      *  @param array $opts Validation options. No additional options are
 723:      *    available or required for this validation method.
 724:      *  @param array $host Host information
 725:      *  @return string|true true if the value is valid, a string with an error
 726:      *    message otherwise.
 727:      */
 728:     public static function ip( $cfg=null ) {
 729:         $opts = ValidateOptions::select( $cfg );
 730:         
 731:         return function ( $val, $data, $field, $host ) use ( $opts ) {
 732:             $common = Validate::_common( $val, $opts );
 733: 
 734:             if ( $common !== null ) {
 735:                 return $common === false ?
 736:                     $opts->message() :
 737:                     $common;
 738:             }
 739: 
 740:             return filter_var($val, FILTER_VALIDATE_IP) !== false ?
 741:                 true :
 742:                 $opts->message();
 743:         };
 744:     }
 745: 
 746: 
 747:     /**
 748:      * Validate as an URL address.
 749:      *
 750:      *  @param string $val The value to check for validity
 751:      *  @param string[] $data The full data set submitted
 752:      *  @param array $opts Validation options. No additional options are
 753:      *    available or required for this validation method.
 754:      *  @param array $host Host information
 755:      *  @return string|true true if the value is valid, a string with an error
 756:      *    message otherwise.
 757:      */
 758:     public static function url( $cfg=null ) {
 759:         $opts = ValidateOptions::select( $cfg );
 760:         
 761:         return function ( $val, $data, $field, $host ) use ( $opts ) {
 762:             $common = Validate::_common( $val, $opts );
 763: 
 764:             if ( $common !== null ) {
 765:                 return $common === false ?
 766:                     $opts->message() :
 767:                     $common;
 768:             }
 769: 
 770:             return filter_var($val, FILTER_VALIDATE_URL) !== false ?
 771:                 true :
 772:                 $opts->message();
 773:         };
 774:     }
 775: 
 776: 
 777:     /**
 778:      * Check if string could contain an XSS attack string
 779:      *
 780:      *  @param string $val The value to check for validity
 781:      *  @param string[] $data The full data set submitted
 782:      *  @param int|array $opts Validation options. The additional options of
 783:      *    `db` - database connection object, `table` - database table to use and
 784:      *    `column` - the column to check this value against as value, are also
 785:      *    available. These options are not required and if not given are
 786:      *    automatically derived from the Editor and Field instances.
 787:      *  @param array $host Host information
 788:      *  @return string|true true if the value is valid, a string with an error
 789:      *    message otherwise.
 790:      */
 791:     public static function xss ( $cfg=null ) {
 792:         $opts = ValidateOptions::select( $cfg );
 793:         
 794:         return function ( $val, $data, $field, $host ) use ( $opts ) {
 795:             $common = Validate::_common( $val, $opts );
 796: 
 797:             if ( $common !== null ) {
 798:                 return $common === false ?
 799:                     $opts->message() :
 800:                     $common;
 801:             }
 802: 
 803:             return $field->xssSafety( $val ) != $val ?
 804:                 $opts->message() :
 805:                 true;
 806:         };
 807:     }
 808: 
 809: 
 810:     /**
 811:      * Confirm that the value submitted is in a list of allowable values
 812:      *
 813:      *  @param string $val The value to check for validity
 814:      *  @param string[] $data The full data set submitted
 815:      *  @param int|array $opts Validation options. The additional options of
 816:      *    `db` - database connection object, `table` - database table to use and
 817:      *    `column` - the column to check this value against as value, are also
 818:      *    available. These options are not required and if not given are
 819:      *    automatically derived from the Editor and Field instances.
 820:      *  @param array $host Host information
 821:      *  @return string|true true if the value is valid, a string with an error
 822:      *    message otherwise.
 823:      */
 824:     public static function values( $values, $cfg=null ) {
 825:         $opts = ValidateOptions::select( $cfg );
 826:         
 827:         return function ( $val, $data, $field, $host ) use ( $values, $opts ) {
 828:             $common = Validate::_common( $val, $opts );
 829: 
 830:             if ( $common !== null ) {
 831:                 return $common === false ?
 832:                     $opts->message() :
 833:                     $common;
 834:             }
 835: 
 836:             return in_array($val, $values) ?
 837:                 true :
 838:                 $opts->message();
 839:         };
 840:     }
 841: 
 842: 
 843:     /**
 844:      * Check if there are any tags in the submitted value
 845:      *
 846:      *  @param string $val The value to check for validity
 847:      *  @param string[] $data The full data set submitted
 848:      *  @param int|array $opts Validation options. The additional options of
 849:      *    `db` - database connection object, `table` - database table to use and
 850:      *    `column` - the column to check this value against as value, are also
 851:      *    available. These options are not required and if not given are
 852:      *    automatically derived from the Editor and Field instances.
 853:      *  @param array $host Host information
 854:      *  @return string|true true if the value is valid, a string with an error
 855:      *    message otherwise.
 856:      */
 857:     public static function noTags ( $cfg=null ) {
 858:         $opts = ValidateOptions::select( $cfg );
 859:         
 860:         return function ( $val, $data, $field, $host ) use ( $opts ) {
 861:             $common = Validate::_common( $val, $opts );
 862: 
 863:             if ( $common !== null ) {
 864:                 return $common === false ?
 865:                     $opts->message() :
 866:                     $common;
 867:             }
 868: 
 869:             return strip_tags( $val ) != $val ?
 870:                 $opts->message() :
 871:                 true;
 872:         };
 873:     }
 874: 
 875: 
 876: 
 877:     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 878:      * Date validation methods
 879:      */
 880: 
 881:     /**
 882:      * Check that a valid date input is given
 883:      *
 884:      *  @param string $val The value to check for validity
 885:      *  @param string[] $data The full data set submitted
 886:      *  @param array|string $opts If given as a string, then $opts is the date
 887:      *    format to check the validity of. If given as an array, then the
 888:      *    date format is in the 'format' parameter, and the return error
 889:      *    message in the 'message' parameter.
 890:      *  @param array $host Host information
 891:      *  @return string|true true if the value is valid, a string with an error
 892:      *    message otherwise.
 893:      */
 894:     public static function dateFormat( $format, $cfg=null ) {
 895:         $opts = ValidateOptions::select( $cfg );
 896:         
 897:         return function ( $val, $data, $field, $host ) use ( $format, $opts ) {
 898:             $common = Validate::_common( $val, $opts );
 899: 
 900:             if ( $common !== null ) {
 901:                 return $common === false ?
 902:                     $opts->message() :
 903:                     $common;
 904:             }
 905: 
 906:             $date = \DateTime::createFromFormat( $format, $val) ;
 907:             
 908:             return $date && $date->format( $format ) == $val ?
 909:                 true :
 910:                 $opts->message();
 911:         };
 912:     }
 913: 
 914: 
 915:     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 916:      * Database validation methods
 917:      */
 918: 
 919:     /**
 920:      * Check that the given value is unique in the database
 921:      *
 922:      *  @param string $val The value to check for validity
 923:      *  @param string[] $data The full data set submitted
 924:      *  @param int|array $opts Validation options. The additional options of
 925:      *    `db` - database connection object, `table` - database table to use and
 926:      *    `column` - the column to check this value against as value, are also
 927:      *    available. These options are not required and if not given are
 928:      *    automatically derived from the Editor and Field instances.
 929:      *  @param array $host Host information
 930:      *  @return string|true true if the value is valid, a string with an error
 931:      *    message otherwise.
 932:      */
 933:     public static function unique( $cfg=null, $column=null, $table=null, $db=null ) {
 934:         $opts = ValidateOptions::select( $cfg );
 935:         
 936:         return function ( $val, $data, $field, $host ) use ( $opts, $column, $table, $db ) {
 937:             $common = Validate::_common( $val, $opts );
 938: 
 939:             if ( $common !== null ) {
 940:                 return $common === false ?
 941:                     $opts->message() :
 942:                     $common;
 943:             }
 944: 
 945:             $editor = $host['editor'];
 946: 
 947:             if ( ! $db ) {
 948:                 $db = $host['db'];
 949:             }
 950: 
 951:             if ( ! $table ) {
 952:                 $table = $editor->table(); // Returns an array, but `select` will take an array
 953:             }
 954: 
 955:             if ( ! $column ) {
 956:                 $column = $field->dbField();
 957:             }
 958: 
 959:             $query = $db
 960:                 ->query( 'select', $table )
 961:                 ->get( $column )
 962:                 ->where( $column, $val );
 963: 
 964:             // If doing an edit, then we need to also discount the current row,
 965:             // since it is of course already validly unique
 966:             if ( $host['action'] === 'edit' ) {
 967:                 $cond = $editor->pkeyToArray( $host['id'], true );
 968:                 $query->where( $cond, null, '!=' );
 969:             }
 970: 
 971:             $res = $query->exec();
 972: 
 973:             return $res->count() === 0 ?
 974:                 true :
 975:                 $opts->message(); 
 976:         };
 977:     }
 978: 
 979:     /**
 980:      * Check that the given value is a value that is available in a database -
 981:      * i.e. a join primary key. This will attempt to automatically use the table
 982:      * name and value column from the field's `options` method (under the
 983:      * assumption that it will typically be used with a joined field), but the
 984:      * table and field can also be specified via the options.
 985:      *
 986:      *  @param string $val The value to check for validity
 987:      *  @param string[] $data The full data set submitted
 988:      *  @param int|array $opts Validation options. The additional options of
 989:      *    `db` - database connection object, `table` - database table to use and
 990:      *    `column` - the column to check this value against as value, are also
 991:      *    available. These options are not required and if not given are
 992:      *    automatically derived from the Editor and Field instances.
 993:      *  @param array $host Host information
 994:      *  @return string|true true if the value is valid, a string with an error
 995:      *    message otherwise.
 996:      */
 997:     public static function dbValues( $cfg=null, $column=null, $table=null, $db=null, $values=array() ) {
 998:         $opts = ValidateOptions::select( $cfg );
 999:         
1000:         return function ( $val, $data, $field, $host ) use ( $opts, $column, $table, $db, $values ) {
1001:             $common = Validate::_common( $val, $opts );
1002: 
1003:             if ( $common !== null ) {
1004:                 return $common === false ?
1005:                     $opts->message() :
1006:                     $common;
1007:             }
1008: 
1009:             // Allow local values to be defined - for example null
1010:             if ( in_array($val, $values) ) {
1011:                 return true;
1012:             }
1013: 
1014:             $editor = $host['editor'];
1015:             $options = $field->options();
1016: 
1017:             if ( ! $db ) {
1018:                 $db = $host['db'];
1019:             }
1020: 
1021:             if ( ! $table ) {
1022:                 $table = $options->table(); // Returns an array, but `select` will take an array
1023:             }
1024: 
1025:             if ( ! $column ) {
1026:                 $column = $options->value();
1027:             }
1028: 
1029:             if ( ! $table ) {
1030:                 throw new \Exception('Table for database value check is not defined for field '.$field->name());
1031:             }
1032: 
1033:             if ( ! $column ) {
1034:                 throw new \Exception('Value column for database value check is not defined for field '.$field->name());
1035:             }
1036: 
1037:             // Try / catch in case the submitted value can't be represented as the
1038:             // database type (e.g. an empty string as an integer)
1039:             try {
1040:                 $count = $db
1041:                     ->query( 'select', $table )
1042:                     ->get( $column )
1043:                     ->where( $column, $val )
1044:                     ->exec()
1045:                     ->count();
1046: 
1047:                 return $count === 0 ?
1048:                     $opts->message() :
1049:                     true;
1050:             }
1051:             catch (\Exception $e) {
1052:                 return $opts->message();
1053:             }
1054:         };
1055:     }
1056:     
1057:     
1058: 
1059:     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1060:     * File validation methods
1061:     */
1062:     static function fileExtensions ( $extensions, $msg="This file type cannot be uploaded." ) {
1063:         return function ( $file ) use ( $extensions, $msg ) {
1064:             $extn = pathinfo($file['name'], PATHINFO_EXTENSION);
1065: 
1066:             for ( $i=0, $ien=count($extensions) ; $i<$ien ; $i++ ) {
1067:                 if ( strtolower( $extn ) === strtolower( $extensions[$i] ) ) {
1068:                     return true;
1069:                 }
1070:             }
1071: 
1072:             return $msg;
1073:         };
1074:     }
1075: 
1076:     static function fileSize ( $size, $msg="Uploaded file is too large." ) {
1077:         return function ( $file ) use ( $size, $msg ) {
1078:             return $file['size'] > $size ?
1079:                 $msg :
1080:                 true;
1081:         };
1082:     }
1083: 
1084: 
1085:     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1086:      * Internal functions
1087:      * These legacy methods are for backwards compatibility with the old way of
1088:      * using the validation methods. They basically do argument swapping.
1089:      */
1090: 
1091:     /**
1092:      * @internal
1093:      */
1094:     static function noneLegacy( $legacyOpts ) {
1095:         return Validate::none();
1096:     }
1097:     
1098:     /**
1099:      * @internal
1100:      */
1101:     static function basicLegacy( $legacyOpts ) {
1102:         $cfg = Validate::_extend( $legacyOpts, null, array() );
1103:         $opts = Validate::_commonLegacy( $cfg );
1104: 
1105:         return Validate::required( $opts );
1106:     }
1107:     
1108:     /**
1109:      * @internal
1110:      */
1111:     static function requiredLegacy( $legacyOpts ) {
1112:         $cfg = Validate::_extend( $legacyOpts, null, array(
1113:             'message' => "This field is required."
1114:         ) );
1115:         $opts = Validate::_commonLegacy( $cfg );
1116: 
1117:         return Validate::required( $opts );
1118:     }
1119:     
1120:     /**
1121:      * @internal
1122:      */
1123:     static function notEmptyLegacy( $legacyOpts ) {
1124:         $cfg = Validate::_extend( $legacyOpts, null, array(
1125:             'message' => "This field is required."
1126:         ) );
1127:         $opts = Validate::_commonLegacy( $cfg );
1128: 
1129:         return Validate::notEmpty( $opts );
1130:     }
1131:     
1132:     /**
1133:      * @internal
1134:      */
1135:     static function booleanLegacy( $legacyOpts ) {
1136:         $cfg = Validate::_extend( $legacyOpts, null, array(
1137:             'message' => "Please enter true or false."
1138:         ) );
1139:         $opts = Validate::_commonLegacy( $cfg );
1140: 
1141:         return Validate::notEmpty( $opts );
1142:     }
1143:     
1144:     /**
1145:      * @internal
1146:      */
1147:     static function numericLegacy( $legacyOpts ) {
1148:         $cfg = Validate::_extend( $legacyOpts, null, array(
1149:             'message' => "This input must be given as a number."
1150:         ) );
1151:         $opts = Validate::_commonLegacy( $cfg );
1152: 
1153:         return isset( $legacyOpts['decimal'] ) ?
1154:             Validate::numeric( $legacyOpts['decimal'], $opts ) :
1155:             Validate::numeric( '.', $opts );
1156:     }
1157:     
1158:     /**
1159:      * @internal
1160:      */
1161:     static function minNumLegacy( $legacyOpts ) {
1162:         $min = is_array($legacyOpts) ? $legacyOpts['min'] : $legacyOpts;
1163:         $cfg = Validate::_extend( $legacyOpts, null, array(
1164:             'message' => "Number is too small, must be ".$min." or larger."
1165:         ) );
1166:         $opts = Validate::_commonLegacy( $cfg );
1167: 
1168:         return isset( $legacyOpts['decimal'] ) ?
1169:             Validate::minNum( $min, $legacyOpts['decimal'], $opts ) :
1170:             Validate::minNum( $min, '.', $opts );
1171:     }
1172:     
1173:     /**
1174:      * @internal
1175:      */
1176:     static function maxNumLegacy( $legacyOpts ) {
1177:         $max = is_array($legacyOpts) ? $legacyOpts['max'] : $legacyOpts;
1178:         $cfg = Validate::_extend( $legacyOpts, null, array(
1179:             'message' => "Number is too large, must be ".$max." or smaller."
1180:         ) );
1181:         $opts = Validate::_commonLegacy( $cfg );
1182: 
1183:         return isset( $legacyOpts['decimal'] ) ?
1184:             Validate::maxNum( $max, $legacyOpts['decimal'], $opts ) :
1185:             Validate::maxNum( $max, '.', $opts );
1186:     }
1187:     
1188:     /**
1189:      * @internal
1190:      */
1191:     static function minMaxNumLegacy( $legacyOpts ) {
1192:         $min = $legacyOpts['min'];
1193:         $max = $legacyOpts['max'];
1194:         $cfg = Validate::_extend( $legacyOpts, null, array() );
1195:         $opts = Validate::_commonLegacy( $cfg );
1196: 
1197:         return isset( $legacyOpts['decimal'] ) ?
1198:             Validate::minMaxNum( $min, $max, $legacyOpts['decimal'], $opts ) :
1199:             Validate::minMaxNum( $min, $max, '.', $opts );
1200:     }
1201:     
1202:     /**
1203:      * @internal
1204:      */
1205:     static function emailLegacy( $legacyOpts ) {
1206:         $cfg = Validate::_extend( $legacyOpts, null, array(
1207:             'message' => "Please enter a valid e-mail address."
1208:         ) );
1209:         $opts = Validate::_commonLegacy( $cfg );
1210: 
1211:         return Validate::email( $opts );
1212:     }
1213:     
1214:     /**
1215:      * @internal
1216:      */
1217:     static function minLenLegacy( $legacyOpts ) {
1218:         $min = is_array($legacyOpts) ? $legacyOpts['min'] : $legacyOpts;
1219:         $cfg = Validate::_extend( $legacyOpts, null, array(
1220:             'message' => "The input is too short. ".$min." characters required."
1221:         ) );
1222:         $opts = Validate::_commonLegacy( $cfg );
1223: 
1224:         return Validate::minLen( $min, $opts );
1225:     }
1226:     
1227:     /**
1228:      * @internal
1229:      */
1230:     static function maxLenLegacy( $legacyOpts ) {
1231:         $max = is_array($legacyOpts) ? $legacyOpts['max'] : $legacyOpts;
1232:         $cfg = Validate::_extend( $legacyOpts, null, array(
1233:             'message' => "The input is too long. ".$max." characters maximum."
1234:         ) );
1235:         $opts = Validate::_commonLegacy( $cfg );
1236: 
1237:         return Validate::maxLen( $max, $opts );
1238:     }
1239:     
1240:     /**
1241:      * @internal
1242:      */
1243:     static function minMaxLenLegacy( $legacyOpts ) {
1244:         $min = $legacyOpts['min'];
1245:         $max = $legacyOpts['max'];
1246:         $cfg = Validate::_extend( $legacyOpts, null, array() );
1247:         $opts = Validate::_commonLegacy( $cfg );
1248: 
1249:         return Validate::minMaxLen( $min, $max, $opts );
1250:     }
1251:     
1252:     /**
1253:      * @internal
1254:      */
1255:     static function ipLegacy( $legacyOpts ) {
1256:         $cfg = Validate::_extend( $legacyOpts, null, array(
1257:             'message' => "Please enter a valid IP address."
1258:         ) );
1259:         $opts = Validate::_commonLegacy( $cfg );
1260: 
1261:         return Validate::ip( $opts );
1262:     }
1263:     
1264:     /**
1265:      * @internal
1266:      */
1267:     static function urlLegacy( $legacyOpts ) {
1268:         $cfg = Validate::_extend( $legacyOpts, null, array(
1269:             'message' => "Please enter a valid URL."
1270:         ) );
1271:         $opts = Validate::_commonLegacy( $cfg );
1272: 
1273:         return Validate::url( $opts );
1274:     }
1275:     
1276:     /**
1277:      * @internal
1278:      */
1279:     static function xssLegacy( $legacyOpts ) {
1280:         $cfg = Validate::_extend( $legacyOpts, null, array(
1281:             'message' => "This field contains potentially unsafe data."
1282:         ) );
1283:         $opts = Validate::_commonLegacy( $cfg );
1284: 
1285:         return Validate::xss( $opts );
1286:     }
1287:     
1288:     /**
1289:      * @internal
1290:      */
1291:     static function valuesLegacy( $legacyOpts ) {
1292:         $values = isset($legacyOpts['valid']) ? $legacyOpts['valid'] : $legacyOpts;
1293:         $cfg = Validate::_extend( $legacyOpts, null, array(
1294:             'message' => "This value is not valid."
1295:         ) );
1296:         $opts = Validate::_commonLegacy( $cfg );
1297: 
1298:         return Validate::values( $values, $opts );
1299:     }
1300:     
1301:     /**
1302:      * @internal
1303:      */
1304:     static function noTagsLegacy( $legacyOpts ) {
1305:         $cfg = Validate::_extend( $legacyOpts, null, array(
1306:             'message' => "This field may not contain HTML."
1307:         ) );
1308:         $opts = Validate::_commonLegacy( $cfg );
1309: 
1310:         return Validate::noTags( $opts );
1311:     }
1312:     
1313:     /**
1314:      * @internal
1315:      */
1316:     static function dateFormatLegacy( $legacyOpts ) {
1317:         $format = is_array($legacyOpts) ? $legacyOpts['format'] : $legacyOpts;
1318:         $cfg = Validate::_extend( $legacyOpts, null, array(
1319:             'message' => "Date is not in the expected format."
1320:         ) );
1321:         $opts = Validate::_commonLegacy( $cfg );
1322: 
1323:         return Validate::dateFormat( $format, $opts );
1324:     }
1325:     
1326:     /**
1327:      * @internal
1328:      */
1329:     static function uniqueLegacy( $legacyOpts ) {
1330:         $table =  isset( $legacyOpts['table'] )  ? $legacyOpts['table']  : null;
1331:         $column = isset( $legacyOpts['column'] ) ? $legacyOpts['column'] : null;
1332:         $db =     isset( $legacyOpts['db'] )     ? $legacyOpts['db']     : null;
1333:         $cfg = Validate::_extend( $legacyOpts, null, array(
1334:             'message' => "This field must have a unique value."
1335:         ) );
1336:         $opts = Validate::_commonLegacy( $cfg );
1337: 
1338:         return Validate::unique( $opts, $column, $table, $db );
1339:     }
1340:     
1341:     /**
1342:      * @internal
1343:      */
1344:     static function dbValuesLegacy( $legacyOpts ) {
1345:         $table =  isset( $legacyOpts['table'] )  ? $legacyOpts['table']  : null;
1346:         $column = isset( $legacyOpts['column'] ) ? $legacyOpts['column'] : null;
1347:         $db =     isset( $legacyOpts['db'] )     ? $legacyOpts['db']     : null;
1348:         $values = isset( $legacyOpts['values'] ) ? $legacyOpts['values'] : array();
1349:         $cfg = Validate::_extend( $legacyOpts, null, array(
1350:             'message' => "This value is not valid."
1351:         ) );
1352:         $opts = Validate::_commonLegacy( $cfg );
1353: 
1354:         return Validate::dbValues( $opts, $column, $table, $db, $values );
1355:     }
1356: }
1357: 
1358: 
DataTables Editor 1.8.0 - PHP libraries API documentation generated by ApiGen