Source for file sql_compatible.php

Documentation is available at sql_compatible.php

  1. <?php
  2. /**
  3.  * Sql Compatible.
  4.  *
  5.  * Attach this behavior to be able to query mongo DBs without using mongo specific syntax.
  6.  * If you don't need this behavior don't attach it and save a few cycles
  7.  *
  8.  * PHP version 5
  9.  *
  10.  * Copyright (c) 2010, Andy Dawson
  11.  *
  12.  * Licensed under The MIT License
  13.  * Redistributions of files must retain the above copyright notice.
  14.  *
  15.  * @filesource
  16.  * @copyright     Copyright (c) 2010, Andy Dawson
  17.  * @link          www.ad7six.com
  18.  * @package       mongodb
  19.  * @subpackage    mongodb.models.behaviors
  20.  * @since         v 1.0 (24-May-2010)
  21.  * @license       http://www.opensource.org/licenses/mit-license.php The MIT License
  22.  */
  23.  
  24. /**
  25.  * SqlCompatibleBehavior class
  26.  *
  27.  * @uses          ModelBehavior
  28.  * @package       mongodb
  29.  * @subpackage    mongodb.models.behaviors
  30.  */
  31. class SqlCompatibleBehavior extends ModelBehavior {
  32.  
  33. /**
  34.  * name property
  35.  *
  36.  * @var string 'SqlCompatible'
  37.  * @access public
  38.  */
  39.     public $name = 'SqlCompatible';
  40.  
  41. /**
  42.  * Runtime settings
  43.  *
  44.  * Keyed on model alias
  45.  *
  46.  * @var array 
  47.  * @access public
  48.  */
  49.     public $settings = array();
  50.  
  51. /**
  52.  * defaultSettings property
  53.  *
  54.  * @var array 
  55.  * @access protected
  56.  */
  57.     protected $_defaultSettings = array(
  58.         'convertDates' => true,
  59.         'operators' => array(
  60.             '!=' => '$ne',
  61.             '>' => '$gt',
  62.             '>=' => '$gte',
  63.             '<' => '$lt',
  64.             '<=' => '$lte',
  65.             'IN' => '$in',
  66.             'NOT' => '$not',
  67.             'NOT IN' => '$nin'
  68.         )
  69.     );
  70.  
  71. /**
  72.  * setup method
  73.  *
  74.  * Allow overriding the operator map
  75.  *
  76.  * @param mixed $Model 
  77.  * @param array $config array()
  78.  * @return void 
  79.  * @access public
  80.  */
  81.     public function setup(&$Model$config array()) {
  82.         $this->settings[$Model->aliasarray_merge($this->_defaultSettings$config);
  83.     }
  84.  
  85. /**
  86.  * If requested, convert dates from MongoDate objects to standard date strings
  87.  *
  88.  * @param mixed $Model 
  89.  * @param mixed $results 
  90.  * @param mixed $primary 
  91.  * @return void 
  92.  * @access public
  93.  */
  94.     public function afterFind(&$Model$results$primary{
  95.         if ($this->settings[$Model->alias]['convertDates']{
  96.             $this->convertDates($results);
  97.         }
  98.         return $results;
  99.     }
  100.  
  101. /**
  102.  * beforeFind method
  103.  *
  104.  * If conditions are an array ensure they are mongified
  105.  *
  106.  * @param mixed $Model 
  107.  * @param mixed $query 
  108.  * @return void 
  109.  * @access public
  110.  */
  111.     public function beforeFind(&$Model$query{
  112.         if (is_array($query['conditions']&& $this->_translateConditions($Model$query['conditions'])) {
  113.             return $query;
  114.         }
  115.         return true;
  116.     }
  117.  
  118. /**
  119.  * Convert MongoDate objects to strings for the purpose of view simplicity
  120.  *
  121.  * @param mixed $results 
  122.  * @return void 
  123.  * @access public
  124.  */
  125.     public function convertDates(&$results{
  126.         if (is_array($results)) {
  127.             foreach($results as &$row{
  128.                 $this->convertDates($row);
  129.             }
  130.         elseif (is_a($results'MongoDate')) {
  131.             $results date('Y-M-d h:i:s'$results->sec);
  132.         }
  133.     }
  134.  
  135. /**
  136.  * translateConditions method
  137.  *
  138.  * Loop on conditions and desqlify them
  139.  *
  140.  * @param mixed $Model 
  141.  * @param mixed $conditions 
  142.  * @return void 
  143.  * @access protected
  144.  */
  145.     protected function _translateConditions(&$Model&$conditions{
  146.         $return false;
  147.         foreach($conditions as $key => &$value{
  148.             $uKey strtoupper($key);
  149.             if (substr($uKey-5=== 'NOT IN'{
  150.                 // 'Special' case because it has a space in it, and it's the whole key
  151.                 $conditions[substr($key0-5)]['$nin'$value;
  152.                 unset($conditions[$key]);
  153.                 $return true;
  154.                 continue;
  155.             }
  156.             if ($uKey === 'OR'{
  157.                 unset($conditions[$key]);
  158.                 foreach($value as $key => $part{
  159.                     $part array($key => $part);
  160.                     $this->_translateConditions($Model$part);
  161.                     $conditions['$or'][$part;
  162.                 }
  163.                 $return true;
  164.                 continue;
  165.             }
  166.             if ($key === $Model->primaryKey && is_array($value)) {
  167.                 //_id=>array(1,2,3) pattern, set  $in operator
  168.                 $isMongoOperator false;
  169.                 foreach($value as $idKey => $idValue{
  170.                     //check a mongo operator exists
  171.                     if(substr($idKey,0,1=== '$'{
  172.                         $isMongoOperator true;
  173.                         continue;
  174.                     }
  175.                 }
  176.                 unset($idKey$idValue);
  177.                 if($isMongoOperator === false{
  178.                     $conditions[$keyarray('$in' => $value);
  179.                 }
  180.                 $return true;
  181.                 continue;
  182.             }
  183.             if (substr($uKey-3=== 'NOT'{
  184.                 // 'Special' case because it's awkward
  185.                 $childKey key($value);
  186.                 $childValue current($value);
  187.  
  188.                 if (in_array(substr($childKey-1)array('>''<''='))) {
  189.                     $parts explode(' '$childKey);
  190.                     $operator array_pop($parts);
  191.                     if ($operator $this->_translateOperator($Model$operator)) {
  192.                         $childKey implode(' '$parts);
  193.                     }
  194.                 else {
  195.                     $conditions[$childKey]['$nin'= (array)$childValue;
  196.                     unset($conditions['NOT']);
  197.                     $return true;
  198.                     continue;
  199.                 }
  200.  
  201.                 $conditions[$childKey]['$not'][$operator$childValue;
  202.                 unset($conditions['NOT']);
  203.                 $return true;
  204.                 continue;
  205.             }
  206.             if (substr($uKey-5=== ' LIKE'{
  207.                 // 'Special' case because it's awkward
  208.                 if ($value[0=== '%'{
  209.                     $value substr($value1);
  210.                 else {
  211.                     $value '^' $value;
  212.                 }
  213.                 if (substr($value-1=== '%'{
  214.                     $value substr($value0-1);
  215.                 else {
  216.                     $value .= '$';
  217.                 }
  218.                 $value str_replace('%''.*'$value);
  219.  
  220.                 $conditions[substr($key0-5)new MongoRegex("/$value/i");
  221.                 unset($conditions[$key]);
  222.                 $return true;
  223.                 continue;
  224.             }
  225.  
  226.             if (!in_array(substr($key-1)array('>''<''='))) {
  227.                 $return true;
  228.                 continue;
  229.             }
  230.             if (is_numeric($key && is_array($value))) {
  231.                 if ($this->_translateConditions($Model$value)) {
  232.                     $return true;
  233.                     continue;
  234.                 }
  235.             }
  236.             $parts explode(' '$key);
  237.             $operator array_pop($parts);
  238.             if ($operator $this->_translateOperator($Model$operator)) {
  239.                 $newKey implode(' '$parts);
  240.                 $conditions[$newKey][$operator$value;
  241.                 unset($conditions[$key]);
  242.                 $return true;
  243.             }
  244.             if (is_array($value)) {
  245.                 if ($this->_translateConditions($Model$value)) {
  246.                     $return true;
  247.                     continue;
  248.                 }
  249.             }
  250.         }
  251.         return $return;
  252.     }
  253.  
  254. /**
  255.  * translateOperator method
  256.  *
  257.  * Use the operator map for the model and return what the db really wants to hear
  258.  *
  259.  * @param mixed $Model 
  260.  * @param mixed $operator 
  261.  * @return string 
  262.  * @access protected
  263.  */
  264.     protected function _translateOperator($Model$operator{
  265.         if (!empty($this->settings[$Model->alias]['operators'][$operator])) {
  266.             return $this->settings[$Model->alias]['operators'][$operator];
  267.         }
  268.         return '';
  269.     }
  270. }

Documentation generated on Tue, 26 Jul 2011 01:09:02 +0900 by phpDocumentor 1.4.3