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\Upload
  • DataTables\Editor\Validate
  • 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\Database;
  14: if (!defined('DATATABLES')) exit();
  15: 
  16: use
  17:     DataTables,
  18:     DataTables\Database,
  19:     DataTables\Database\Query,
  20:     DataTables\Database\Result;
  21: 
  22: 
  23: //
  24: // This is a stub class that a driver must extend and complete
  25: //
  26: 
  27: /**
  28:  * Perform an individual query on the database.
  29:  * 
  30:  * The typical pattern for using this class is through the {@link
  31:  * \DataTables\Database::query} method (and it's 'select', etc short-cuts).
  32:  * Typically it would not be initialised directly.
  33:  *
  34:  * Note that this is a stub class that a driver will extend and complete as
  35:  * required for individual database types. Individual drivers could add
  36:  * additional methods, but this is discouraged to ensure that the API is the
  37:  * same for all database types.
  38:  */
  39: class Query {
  40:     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  41:      * Constructor
  42:      */
  43: 
  44:     /**
  45:      * Query instance constructor.
  46:      *
  47:      * Note that typically instances of this class will be automatically created
  48:      * through the {@link \DataTables\Database::query} method.
  49:      *  @param Database        $db    Database instance
  50:      *  @param string          $type  Query type - 'select', 'insert', 'update' or 'delete'
  51:      *  @param string|string[] $table Tables to operate on - see {@link table}.
  52:      */
  53:     public function __construct( $db, $type, $table=null )
  54:     {
  55:         $this->_dbcon = $db;
  56:         $this->_type = $type;
  57:         $this->table( $table );
  58:     }
  59: 
  60: 
  61:     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  62:      * Private properties
  63:      */
  64: 
  65:     /**
  66:      * @var string Driver to use
  67:      * @internal
  68:      */
  69:     protected $_type = "";
  70: 
  71:     /**
  72:      * @var resource Database connection
  73:      * @internal
  74:      */
  75:     protected $_dbcon = null;
  76: 
  77:     /**
  78:      * @var array
  79:      * @internal
  80:      */
  81:     protected $_table = array();
  82: 
  83:     /**
  84:      * @var array
  85:      * @internal
  86:      */
  87:     protected $_field = array();
  88: 
  89:     /**
  90:      * @var array
  91:      * @internal
  92:      */
  93:     protected $_bindings = array();
  94: 
  95:     /**
  96:      * @var array
  97:      * @internal
  98:      */
  99:     protected $_where = array();
 100: 
 101:     /**
 102:      * @var array
 103:      * @internal
 104:      */
 105:     protected $_join = array();
 106: 
 107:     /**
 108:      * @var array
 109:      * @internal
 110:      */
 111:     protected $_order = array();
 112: 
 113:     /**
 114:      * @var array
 115:      * @internal
 116:      */
 117:     protected $_noBind = array();
 118: 
 119:     /**
 120:      * @var int
 121:      * @internal
 122:      */
 123:     protected $_limit = null;
 124: 
 125:     /**
 126:      * @var int
 127:      * @internal
 128:      */
 129:     protected $_offset = null;
 130: 
 131:     /**
 132:      * @var string
 133:      * @internal
 134:      */
 135:     protected $_distinct = false;
 136: 
 137:     /**
 138:      * @var string
 139:      * @internal
 140:      */
 141:     protected $_identifier_limiter = '`';
 142: 
 143:     /**
 144:      * @var string
 145:      * @internal
 146:      */
 147:     protected $_field_quote = '\'';
 148: 
 149: 
 150: 
 151:     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 152:      * Static methods
 153:      */
 154: 
 155:     /**
 156:      * Commit a transaction.
 157:      *  @param \PDO $dbh The Database handle (typically a PDO object, but not always).
 158:      */
 159:     public static function commit ( $dbh )
 160:     {
 161:         $dbh->commit();
 162:     }
 163: 
 164:     /**
 165:      * Database connection - override by the database driver.
 166:      *  @param string|array $user User name or all parameters in an array
 167:      *  @param string $pass Password
 168:      *  @param string $host Host name
 169:      *  @param string $db   Database name
 170:      *  @return Query
 171:      */
 172:     public static function connect ( $user, $pass='', $host='', $port='', $db='', $dsn='' )
 173:     {
 174:         return false;
 175:     }
 176: 
 177: 
 178:     /**
 179:      * Start a database transaction
 180:      *  @param \PDO $dbh The Database handle (typically a PDO object, but not always).
 181:      */
 182:     public static function transaction ( $dbh )
 183:     {
 184:         $dbh->beginTransaction();
 185:     }
 186: 
 187: 
 188:     /**
 189:      * Rollback the database state to the start of the transaction.
 190:      *  @param \PDO $dbh The Database handle (typically a PDO object, but not always).
 191:      */
 192:     public static function rollback ( $dbh )
 193:     {
 194:         $dbh->rollBack();
 195:     }
 196: 
 197: 
 198:     /**
 199:      * Common helper for the drivers to handle a PDO DSN postfix
 200:      *  @param string $dsn DSN postfix to use
 201:      *  @return Query
 202:      *  @internal
 203:      */
 204:     static function dsnPostfix ( $dsn )
 205:     {
 206:         if ( ! $dsn ) {
 207:             return '';
 208:         }
 209: 
 210:         // Add a DSN field separator if not given
 211:         if ( strpos( $dsn, ';' ) !== 0 ) {
 212:             return ';'.$dsn;
 213:         }
 214: 
 215:         return $dsn;
 216:     }
 217: 
 218: 
 219: 
 220:     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 221:      * Public methods
 222:      */
 223: 
 224:     /**
 225:      * Safely bind an input value to a parameter. This is evaluated when the
 226:      * query is executed. This allows user input to be safely executed without
 227:      * risk of an SQL injection attack.
 228:      *
 229:      * @param  [type] $name  Parameter name. This should include a leading colon
 230:      * @param  [type] $value Value to bind
 231:      * @param  [type] $type  Data type. See the PHP PDO documentation:
 232:      *   http://php.net/manual/en/pdo.constants.php
 233:      * @return Query
 234:      */
 235:     public function bind ( $name, $value, $type=null )
 236:     {
 237:         $this->_bindings[] = array(
 238:             "name"  => $this->_safe_bind( $name ),
 239:             "value" => $value,
 240:             "type"  => $type
 241:         );
 242: 
 243:         return $this;
 244:     }
 245: 
 246:     /**
 247:      * Set a distinct flag for a `select` query. Note that this has no effect on
 248:      * any of the other query types.
 249:      *  @param boolean $dis Optional
 250:      *  @return Query
 251:      */
 252:     public function distinct ( $dis )
 253:     {
 254:         $this->_distinct = $dis;
 255:         return $this;
 256:     }
 257: 
 258:     /**
 259:      * Execute the query.
 260:      *  @param string $sql SQL string to execute (only if _type is 'raw').
 261:      *  @return Result
 262:      */
 263:     public function exec ( $sql=null )
 264:     {
 265:         $type = strtolower( $this->_type );
 266: 
 267:         if ( $type === 'select' ) {
 268:             return $this->_select();
 269:         }
 270:         else if ( $type === 'insert' ) {
 271:             return $this->_insert();
 272:         }
 273:         else if ( $type === 'update' ) {
 274:             return $this->_update();
 275:         }
 276:         else if ( $type === 'delete' ) {
 277:             return $this->_delete();
 278:         }
 279:         else if ( $type === 'raw' ) {
 280:             return $this->_raw( $sql );
 281:         }
 282:         
 283:         throw new \Exception("Unknown database command or not supported: ".$type, 1);
 284:     }
 285: 
 286: 
 287:     /**
 288:      * Get fields.
 289:      *  @param string|string[] $get,... Fields to get - can be specified as
 290:      *    individual fields, an array of fields, a string of comma separated
 291:      *    fields or any combination of those.
 292:      *  @return self
 293:      */
 294:     public function get ( $get )
 295:     {
 296:         if ( $get === null ) {
 297:             return $this;
 298:         }
 299: 
 300:         $args = func_get_args();
 301: 
 302:         for ( $i=0 ; $i<count($args) ; $i++ ) {
 303:             // If argument is an array then we loop over and add each using a
 304:             // recursive call
 305:             if ( is_array( $args[$i] ) ) {
 306:                 for ( $j=0 ; $j<count($args[$i]) ; $j++ ) {
 307:                     $this->get( $args[$i][$j] );
 308:                 }
 309:             }
 310:             else {
 311:                 // String argument so split into pieces and add
 312:                 // TODO - This limits the ability to use functions. Need to
 313:                 // parse the string so it will split when not in a function
 314:                 $fields = explode(",", $args[$i]);
 315: 
 316:                 for ( $j=0 ; $j<count($fields) ; $j++ ) {
 317:                     $this->_field[] = trim( $fields[$j] );
 318:                 }
 319:             }
 320:         }
 321: 
 322:         return $this;
 323:     }
 324: 
 325: 
 326:     /**
 327:      * Perform a JOIN operation
 328:      *  @param string $table     Table name to do the JOIN on
 329:      *  @param string $condition JOIN condition
 330:      *  @param string $type      JOIN type
 331:      *  @return self
 332:      */
 333:     public function join ( $table, $condition, $type='' )
 334:     {
 335:         // Tidy and check we know what the join type is
 336:         if ($type !== '') {
 337:             $type = strtoupper(trim($type));
 338: 
 339:             if ( ! in_array($type, array('LEFT', 'RIGHT', 'INNER', 'OUTER', 'LEFT OUTER', 'RIGHT OUTER'))) {
 340:                 $type = '';
 341:             }
 342:         }
 343: 
 344:         // Protect the identifiers
 345:         if (preg_match('/([\w\.]+)([\W\s]+)(.+)/', $condition, $match))
 346:         {
 347:             $match[1] = $this->_protect_identifiers( $match[1] );
 348:             $match[3] = $this->_protect_identifiers( $match[3] );
 349: 
 350:             $condition = $match[1].$match[2].$match[3];
 351:         }
 352: 
 353:         $this->_join[] = $type .' JOIN '. $this->_protect_identifiers($table) .' ON '. $condition .' ';
 354: 
 355:         return $this;
 356:     }
 357: 
 358: 
 359:     /**
 360:      * Limit the result set to a certain size.
 361:      *  @param int $lim The number of records to limit the result to.
 362:      *  @return self
 363:      */
 364:     public function limit ( $lim )
 365:     {
 366:         $this->_limit = $lim;
 367: 
 368:         return $this;
 369:     }
 370: 
 371: 
 372:     /**
 373:      * Set table(s) to perform the query on.
 374:      *  @param string|string[] $table,... Table(s) to use - can be specified as
 375:      *    individual names, an array of names, a string of comma separated
 376:      *    names or any combination of those.
 377:      *  @return self
 378:      */
 379:     public function table ( $table )
 380:     {
 381:         if ( $table === null ) {
 382:             return $this;
 383:         }
 384: 
 385:         if ( is_array($table) ) {
 386:             // Array so loop internally
 387:             for ( $i=0 ; $i<count($table) ; $i++ ) {
 388:                 $this->table( $table[$i] );
 389:             }
 390:         }
 391:         else {
 392:             // String based, explode for multiple tables
 393:             $tables = explode(",", $table);
 394: 
 395:             for ( $i=0 ; $i<count($tables) ; $i++ ) {
 396:                 $this->_table[] = $this->_protect_identifiers( trim($tables[$i]) );
 397:             }
 398:         }
 399: 
 400:         return $this;
 401:     }
 402: 
 403: 
 404:     /**
 405:      * Offset the return set by a given number of records (useful for paging).
 406:      *  @param int $off The number of records to offset the result by.
 407:      *  @return self
 408:      */
 409:     public function offset ( $off )
 410:     {
 411:         $this->_offset = $off;
 412: 
 413:         return $this;
 414:     }
 415: 
 416: 
 417:     /**
 418:      * Order by
 419:      *  @param string|string[] $order Columns and direction to order by - can
 420:      *    be specified as individual names, an array of names, a string of comma 
 421:      *    separated names or any combination of those.
 422:      *  @return self
 423:      */
 424:     public function order ( $order )
 425:     {
 426:         if ( $order === null ) {
 427:             return $this;
 428:         }
 429: 
 430:         if ( !is_array($order) ) {
 431:             $order = explode(",", $order);
 432:         }
 433: 
 434:         for ( $i=0 ; $i<count($order) ; $i++ ) {
 435:             // Simplify the white-space
 436:             $order[$i] = trim( preg_replace('/[\t ]+/', ' ', $order[$i]) );
 437: 
 438:             // Find the identifier so we don't escape that
 439:             if ( strpos($order[$i], ' ') !== false ) {
 440:                 $direction = strstr($order[$i], ' ');
 441:                 $identifier = substr($order[$i], 0, - strlen($direction));
 442:             }
 443:             else {
 444:                 $direction = '';
 445:                 $identifier = $order[$i];
 446:             }
 447: 
 448:             $this->_order[] = $this->_protect_identifiers( $identifier ).' '.$direction;
 449:         }
 450: 
 451:         return $this;
 452:     }
 453: 
 454: 
 455:     /**
 456:      * Set fields to a given value.
 457:      *
 458:      * Can be used in two different ways, as set( field, value ) or as an array of
 459:      * fields to set: set( array( 'fieldName' => 'value', ...) );
 460:      *  @param string|string[] $set Can be given as a single string, when then $val
 461:      *    must be set, or as an array of key/value pairs to be set.
 462:      *  @param string          $val When $set is given as a simple string, $set is the field
 463:      *    name and this is the field's value.
 464:      *  @param boolean         $bind Should the value be bound or not
 465:      *  @return self
 466:      */
 467:     public function set ( $set, $val=null, $bind=true )
 468:     {
 469:         if ( $set === null ) {
 470:             return $this;
 471:         }
 472: 
 473:         if ( !is_array($set) ) {
 474:             $set = array( $set => $val );
 475:         }
 476: 
 477:         foreach ($set as $key => $value) {
 478:             $this->_field[] = $key;
 479: 
 480:             if ( $bind ) {
 481:                 $this->bind( ':'.$key, $value );
 482:             }
 483:             else {
 484:                 $this->_noBind[$key] = $value;
 485:             }
 486:         }
 487: 
 488:         return $this;
 489:     }
 490: 
 491: 
 492:     /**
 493:      * Where query - multiple conditions are bound as ANDs.
 494:      *
 495:      * Can be used in two different ways, as where( field, value ) or as an array of
 496:      * conditions to use: where( array('fieldName', ...), array('value', ...) );
 497:      *  @param string|string[]|callable $key   Single field name, or an array of field names.
 498:      *    If given as a function (i.e. a closure), the function is called, passing the
 499:      *    query itself in as the only parameter, so the function can add extra conditions
 500:      *    with parentheses around the additional parameters.
 501:      *  @param string|string[]          $value Single field value, or an array of
 502:      *    values. Can be null to search for `IS NULL` or `IS NOT NULL` (depending
 503:      *    on the value of `$op` which should be `=` or `!=`.
 504:      *  @param string                   $op    Condition operator: <, >, = etc
 505:      *  @param boolean                  $bind  Escape the value (true, default) or not (false).
 506:      *  @return self
 507:      *
 508:      *  @example
 509:      *     The following will produce
 510:      *     `'WHERE name='allan' AND ( location='Scotland' OR location='Canada' )`:
 511:      *
 512:      *     <code>
 513:      *       $query
 514:      *         ->where( 'name', 'allan' )
 515:      *         ->where( function ($q) {
 516:      *           $q->where( 'location', 'Scotland' );
 517:      *           $q->where( 'location', 'Canada' );
 518:      *         } );
 519:      *     </code>
 520:      */
 521:     public function where ( $key, $value=null, $op="=", $bind=true )
 522:     {
 523:         if ( $key === null ) {
 524:             return $this;
 525:         }
 526:         else if ( is_callable($key) && is_object($key) ) { // is a closure
 527:             $this->_where_group( true, 'AND' );
 528:             $key( $this );
 529:             $this->_where_group( false, 'OR' );
 530:         }
 531:         else {
 532:             if ( !is_array($key) && is_array($value) ) {
 533:                 for ( $i=0 ; $i<count($value) ; $i++ ) {
 534:                     $this->where( $key, $value[$i], $op, $bind );
 535:                 }
 536:                 return $this;
 537:             }
 538: 
 539:             $this->_where( $key, $value, 'AND ', $op, $bind );
 540:         }
 541: 
 542:         return $this;
 543:     }
 544: 
 545: 
 546:     /**
 547:      * Add addition where conditions to the query with an AND operator. An alias
 548:      * of `where` for naming consistency.
 549:      *
 550:      * Can be used in two different ways, as where( field, value ) or as an array of
 551:      * conditions to use: where( array('fieldName', ...), array('value', ...) );
 552:      *  @param string|string[]|callable $key   Single field name, or an array of field names.
 553:      *    If given as a function (i.e. a closure), the function is called, passing the
 554:      *    query itself in as the only parameter, so the function can add extra conditions
 555:      *    with parentheses around the additional parameters.
 556:      *  @param string|string[]          $value Single field value, or an array of
 557:      *    values. Can be null to search for `IS NULL` or `IS NOT NULL` (depending
 558:      *    on the value of `$op` which should be `=` or `!=`.
 559:      *  @param string                   $op    Condition operator: <, >, = etc
 560:      *  @param boolean                  $bind  Escape the value (true, default) or not (false).
 561:      *  @return self
 562:      */
 563:     public function and_where ( $key, $value=null, $op="=", $bind=true )
 564:     {
 565:         return $this->where( $key, $value, $op, $bind );
 566:     }
 567: 
 568: 
 569:     /**
 570:      * Add addition where conditions to the query with an OR operator.
 571:      *
 572:      * Can be used in two different ways, as where( field, value ) or as an array of
 573:      * conditions to use: where( array('fieldName', ...), array('value', ...) );
 574:      *  @param string|string[]|callable $key   Single field name, or an array of field names.
 575:      *    If given as a function (i.e. a closure), the function is called, passing the
 576:      *    query itself in as the only parameter, so the function can add extra conditions
 577:      *    with parentheses around the additional parameters.
 578:      *  @param string|string[]          $value Single field value, or an array of
 579:      *    values. Can be null to search for `IS NULL` or `IS NOT NULL` (depending
 580:      *    on the value of `$op` which should be `=` or `!=`.
 581:      *  @param string                   $op    Condition operator: <, >, = etc
 582:      *  @param boolean                  $bind  Escape the value (true, default) or not (false).
 583:      *  @return self
 584:      */
 585:     public function or_where ( $key, $value=null, $op="=", $bind=true )
 586:     {
 587:         if ( $key === null ) {
 588:             return $this;
 589:         }
 590:         else if ( is_callable($key) ) {
 591:             $this->_where_group( true, 'OR' );
 592:             $key( $this );
 593:             $this->_where_group( false, 'OR' );
 594:         }
 595:         else {
 596:             if ( !is_array($key) && is_array($value) ) {
 597:                 for ( $i=0 ; $i<count($value) ; $i++ ) {
 598:                     $this->or_where( $key, $value[$i], $op, $bind );
 599:                 }
 600:                 return $this;
 601:             }
 602: 
 603:             $this->_where( $key, $value, 'OR ', $op, $bind );
 604:         }
 605: 
 606:         return $this;
 607:     }
 608: 
 609: 
 610:     /**
 611:      * Provide grouping for WHERE conditions. Calling this function with `true`
 612:      * as the first parameter will open a bracket, and `false` will then close
 613:      * it.
 614:      *
 615:      *  @param boolean $inOut `true` to open brackets, `false` to close
 616:      *  @param string  $op    Conditional operator to use to join to the
 617:      *      preceding condition. Default `AND`.
 618:      *  @return self
 619:      */
 620:     public function where_group ( $inOut, $op='AND' )
 621:     {
 622:         $this->_where_group( $inOut, $op );
 623: 
 624:         return $this;
 625:     }
 626: 
 627: 
 628: 
 629:     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 630:      * Protected methods
 631:      */
 632: 
 633:     /**
 634:      * Create a comma separated field list
 635:      * @param bool $addAlias Flag to add an alias
 636:      * @return string
 637:      * @internal
 638:      */
 639:     protected function _build_field( $addAlias=false )
 640:     {
 641:         $a = array();
 642: 
 643:         for ( $i=0 ; $i<count($this->_field) ; $i++ ) {
 644:             $field = $this->_field[$i];
 645: 
 646:             // Keep the name when referring to a table
 647:             if ( $addAlias && strpos($field, ' as ') !== false && $field !== '*' ) {
 648:                 $split = explode(' as ', $field);
 649:                 $a[] = $this->_protect_identifiers( $split[0] ).' as '.
 650:                     $this->_field_quote. $split[1] .$this->_field_quote;
 651:             }
 652:             else if ( $addAlias && strpos($field, ' as ') === false && $field !== '*' ) {
 653:                 $a[] = $this->_protect_identifiers( $field ).' as '.
 654:                     $this->_field_quote. $field .$this->_field_quote;
 655:             }
 656:             else {
 657:                 $a[] = $this->_protect_identifiers( $field );
 658:             }
 659:         }
 660: 
 661:         return ' '.implode(', ', $a).' ';
 662:     }
 663: 
 664:     /**
 665:      * Create a JOIN statement list
 666:      *  @return string
 667:      *  @internal
 668:      */
 669:     protected function _build_join()
 670:     {
 671:         return implode(' ', $this->_join);
 672:     }
 673: 
 674:     /**
 675:      * Create the LIMIT / OFFSET string
 676:      *
 677:      * MySQL and Postgres stylee - anything else can have the driver override
 678:      *  @return string
 679:      *  @internal
 680:      */
 681:     protected function _build_limit()
 682:     {
 683:         $out = '';
 684:         
 685:         if ( $this->_limit ) {
 686:             $out .= ' LIMIT '.$this->_limit;
 687:         }
 688: 
 689:         if ( $this->_offset ) {
 690:             $out .= ' OFFSET '.$this->_offset;
 691:         }
 692: 
 693:         return $out;
 694:     }
 695: 
 696:     /**
 697:      * Create the ORDER BY string
 698:      *  @return string
 699:      *  @internal
 700:      */
 701:     protected function _build_order()
 702:     {
 703:         if ( count( $this->_order ) > 0 ) {
 704:             return ' ORDER BY '.implode(', ', $this->_order).' ';
 705:         }
 706:         return '';
 707:     }
 708: 
 709:     /**
 710:      * Create a set list
 711:      *  @return string
 712:      *  @internal
 713:      */
 714:     protected function _build_set()
 715:     {
 716:         $a = array();
 717: 
 718:         for ( $i=0 ; $i<count($this->_field) ; $i++ ) {
 719:             $field = $this->_field[$i];
 720: 
 721:             if ( isset( $this->_noBind[ $field ] ) ) {
 722:                 $a[] = $this->_protect_identifiers( $field ) .' = '. $this->_noBind[ $field ];
 723:             }
 724:             else {
 725:                 $a[] = $this->_protect_identifiers( $field ) .' = :'. $this->_safe_bind( $field );
 726:             }
 727:         }
 728: 
 729:         return ' '.implode(', ', $a).' ';
 730:     }
 731: 
 732:     /**
 733:      * Create the TABLE list
 734:      *  @return string
 735:      *  @internal
 736:      */
 737:     protected function _build_table()
 738:     {
 739:         return ' '.implode(', ', $this->_table).' ';
 740:     }
 741: 
 742:     /**
 743:      * Create a bind field value list
 744:      *  @return string
 745:      *  @internal
 746:      */
 747:     protected function _build_value()
 748:     {
 749:         $a = array();
 750: 
 751:         for ( $i=0, $ien=count($this->_field) ; $i<$ien ; $i++ ) {
 752:             $a[] = ' :'.$this->_safe_bind( $this->_field[$i] );
 753:         }
 754: 
 755:         return ' '.implode(', ', $a).' ';
 756:     }
 757: 
 758:     /**
 759:      * Create the WHERE statement
 760:      *  @return string
 761:      *  @internal
 762:      */
 763:     protected function _build_where()
 764:     {
 765:         if ( count($this->_where) === 0 ) {
 766:             return "";
 767:         }
 768: 
 769:         $condition = "WHERE ";
 770: 
 771:         for ( $i=0 ; $i<count($this->_where) ; $i++ ) {
 772:             if ( $i === 0 ) {
 773:                 // Nothing (simplifies the logic!)
 774:             }
 775:             else if ( $this->_where[$i]['group'] === ')' ) {
 776:                 // Nothing
 777:             }
 778:             else if ( $this->_where[$i-1]['group'] === '(' ) {
 779:                 // Nothing
 780:             }
 781:             else {
 782:                 $condition .= $this->_where[$i]['operator'];
 783:             }
 784: 
 785:             if ( $this->_where[$i]['group'] !== null ) {
 786:                 $condition .= $this->_where[$i]['group'];
 787:             }
 788:             else {
 789:                 $condition .= $this->_where[$i]['query'] .' ';
 790:             }
 791:         }
 792: 
 793:         return $condition;
 794:     }
 795: 
 796:     /**
 797:      * Create a DELETE statement
 798:      *  @return Result
 799:      *  @internal
 800:      */
 801:     protected function _delete()
 802:     {
 803:         $this->_prepare( 
 804:             'DELETE FROM '
 805:             .$this->_build_table()
 806:             .$this->_build_where()
 807:         );
 808: 
 809:         return $this->_exec();
 810:     }
 811: 
 812:     /**
 813:      * Execute the query. Provided by the driver
 814:      *  @return Result
 815:      *  @internal
 816:      */
 817:     protected function _exec()
 818:     {}
 819: 
 820:     /**
 821:      * Create an INSERT statement
 822:      *  @return Result
 823:      *  @internal
 824:      */
 825:     protected function _insert()
 826:     {
 827:         $this->_prepare( 
 828:             'INSERT INTO '
 829:                 .$this->_build_table().' ('
 830:                     .$this->_build_field()
 831:                 .') '
 832:             .'VALUES ('
 833:                 .$this->_build_value()
 834:             .')'
 835:         );
 836: 
 837:         return $this->_exec();
 838:     }
 839: 
 840:     /**
 841:      * Prepare the SQL query by populating the bound variables.
 842:      * Provided by the driver
 843:      *  @return void
 844:      *  @internal
 845:      */
 846:     protected function _prepare( $sql )
 847:     {}
 848: 
 849:     /**
 850:      * Protect field names
 851:      * @param string $identifier String to be protected
 852:      * @return string
 853:      * @internal
 854:      */
 855:     protected function _protect_identifiers( $identifier )
 856:     {
 857:         $idl = $this->_identifier_limiter;
 858: 
 859:         // No escaping character
 860:         if ( $idl === '' ) {
 861:             return $identifier;
 862:         }
 863: 
 864:         // Dealing with a function or other expression? Just return immediately
 865:         if (strpos($identifier, '(') !== FALSE || strpos($identifier, '*') !== FALSE || strpos($identifier, ' ') !== FALSE)
 866:         {
 867:             return $identifier;
 868:         }
 869: 
 870:         // Going to be operating on the spaces in strings, to simplify the white-space
 871:         $identifier = preg_replace('/[\t ]+/', ' ', $identifier);
 872: 
 873:         // Find if our identifier has an alias, so we don't escape that
 874:         if ( strpos($identifier, ' as ') !== false ) {
 875:             $alias = strstr($identifier, ' as ');
 876:             $identifier = substr($identifier, 0, - strlen($alias));
 877:         }
 878:         else {
 879:             $alias = '';
 880:         }
 881: 
 882:         $a = explode('.', $identifier);
 883:         return $idl . implode($idl.'.'.$idl, $a) . $idl . $alias;
 884:     }
 885: 
 886:     /**
 887:      * Passed in SQL statement
 888:      *  @return Result
 889:      *  @internal
 890:      */
 891:     protected function _raw( $sql )
 892:     {
 893:         $this->_prepare( $sql );
 894: 
 895:         return $this->_exec();
 896:     }
 897: 
 898:     /**
 899:      * The characters that can be used for the PDO bindValue name are quite
 900:      * limited (`[a-zA-Z0-9_]+`). We need to abstract this out to allow slightly
 901:      * more complex expressions including dots for easy aliasing
 902:      * @param string $name Field name
 903:      * @return string
 904:      * @internal
 905:      */
 906:     protected function _safe_bind ( $name )
 907:     {
 908:         $name = str_replace('.', '_1_', $name);
 909:         $name = str_replace('-', '_2_', $name);
 910: 
 911:         return $name;
 912:     }
 913: 
 914:     /**
 915:      * Create a SELECT statement
 916:      *  @return Result
 917:      *  @internal
 918:      */
 919:     protected function _select()
 920:     {
 921:         $this->_prepare( 
 922:             'SELECT '.($this->_distinct ? 'DISTINCT ' : '')
 923:             .$this->_build_field( true )
 924:             .'FROM '.$this->_build_table()
 925:             .$this->_build_join()
 926:             .$this->_build_where()
 927:             .$this->_build_order()
 928:             .$this->_build_limit()
 929:         );
 930: 
 931:         return $this->_exec();
 932:     }
 933: 
 934:     /**
 935:      * Create an UPDATE statement
 936:      *  @return Result
 937:      *  @internal
 938:      */
 939:     protected function _update()
 940:     {
 941:         $this->_prepare( 
 942:             'UPDATE '
 943:             .$this->_build_table()
 944:             .'SET '.$this->_build_set()
 945:             .$this->_build_where()
 946:         );
 947: 
 948:         return $this->_exec();
 949:     }
 950: 
 951:     /**
 952:      * Add an individual where condition to the query.
 953:      * @internal
 954:      * @param $where
 955:      * @param null $value
 956:      * @param string $type
 957:      * @param string $op
 958:      * @param bool $bind
 959:      */
 960:     protected function _where ( $where, $value=null, $type='AND ', $op="=", $bind=true )
 961:     {
 962:         $idl = $this->_identifier_limiter;
 963: 
 964:         if ( $where === null ) {
 965:             return;
 966:         }
 967:         else if ( !is_array($where) ) {
 968:             $where = array( $where => $value );
 969:         }
 970: 
 971:         foreach ($where as $key => $value) {
 972:             $i = count( $this->_where );
 973: 
 974:             if ( $value === null ) {
 975:                 // Null query
 976:                 $this->_where[] = array(
 977:                     'operator' => $type,
 978:                     'group'    => null,
 979:                     'field'    => $this->_protect_identifiers($key),
 980:                     'query'    => $this->_protect_identifiers($key) .( $op === '=' ?
 981:                         ' IS NULL' :
 982:                         ' IS NOT NULL')
 983:                 );
 984:             }
 985:             else if ( $bind ) {
 986:                 // Binding condition (i.e. escape data)
 987:                 $this->_where[] = array(
 988:                     'operator' => $type,
 989:                     'group'    => null,
 990:                     'field'    => $this->_protect_identifiers($key),
 991:                     'query'    => $this->_protect_identifiers($key) .' '.$op.' '.$this->_safe_bind(':where_'.$i)
 992:                 );
 993:                 $this->bind( ':where_'.$i, $value );
 994:             }
 995:             else {
 996:                 // Non-binding condition
 997:                 $this->_where[] = array(
 998:                     'operator' => $type,
 999:                     'group'    => null,
1000:                     'field'    => null,
1001:                     'query'    => $this->_protect_identifiers($key) .' '. $op .' '. $this->_protect_identifiers($value)
1002:                 );
1003:             }
1004:         }
1005:     }
1006: 
1007:     /**
1008:      * Add parentheses to a where condition
1009:      *  @return string
1010:      *  @internal
1011:      */
1012:     protected function _where_group ( $inOut, $op )
1013:     {
1014:         $this->_where[] = array(
1015:             "group"    => $inOut ? '(' : ')',
1016:             "operator" => $op
1017:         );
1018:     }
1019: };
1020: 
1021: 
1022: 
DataTables Editor 1.5.6 - PHP 5.3+ libraries API documentation generated by ApiGen