Lançado Adianti Framework 7.6!
Clique aqui para saber mais
menu

Adianti Solutions

API

Adianti, Framework, PHP, MVC, Active record, Front controller, IDE, RAD, Web, multiplataforma, geração de código, desenvolvimento rápido, relatórios, formulários, listagens, datagrids, gráficos, banco de dados, padrões de projeto, design patterns API do Adianti Framework.
API Docs
code
Selecione a classe

Source for file TRecord.php

Documentation is available at TRecord.php

  1. <?php
  2. namespace Adianti\Database;
  3.  
  4. use Adianti\Core\AdiantiCoreTranslator;
  5. use Adianti\Database\TTransaction;
  6. use Adianti\Database\TCriteria;
  7. use Adianti\Database\TFilter;
  8. use Adianti\Database\TRepository;
  9. use Adianti\Database\TSqlSelect;
  10. use Adianti\Database\TSqlInsert;
  11. use Adianti\Database\TSqlUpdate;
  12. use Adianti\Database\TSqlDelete;
  13.  
  14. use Math\Parser;
  15. use PDO;
  16. use Exception;
  17. use IteratorAggregate;
  18. use ArrayIterator;
  19. use Traversable;
  20.  
  21. /**
  22.  * Base class for Active Records
  23.  *
  24.  * @version    7.4
  25.  * @package    database
  26.  * @author     Pablo Dall'Oglio
  27.  * @copyright  Copyright (c) 2006 Adianti Solutions Ltd. (http://www.adianti.com.br)
  28.  * @license    http://www.adianti.com.br/framework-license
  29.  */
  30. abstract class TRecord implements IteratorAggregate
  31. {
  32.     protected $data;  // array containing the data of the object
  33.     protected $vdata// array with virtual data (non-persistant properties)
  34.     protected $attributes// array of attributes
  35.     protected $trashed;
  36.     
  37.     /**
  38.      * Class Constructor
  39.      * Instantiates the Active Record
  40.      * @param [$id] Optional Object ID, if passed, load this object
  41.      */
  42.     public function __construct($id NULL$callObjectLoad TRUE)
  43.     {
  44.         $this->attributes = array();
  45.         $this->trashed = FALSE;
  46.         
  47.         if ($id// if the user has informed the $id
  48.         {
  49.             // load the object identified by ID
  50.             if ($callObjectLoad)
  51.             {
  52.                 $object $this->load($id);
  53.             }
  54.             else
  55.             {
  56.                 $object self::load($id);
  57.             }
  58.             
  59.             if ($object)
  60.             {
  61.                 $this->fromArray($object->toArray());
  62.             }
  63.             else
  64.             {
  65.                 throw new Exception(AdiantiCoreTranslator::translate('Object ^1 not found in ^2'$idconstant(get_class($this).'::TABLENAME')));
  66.             }
  67.         }
  68.     }
  69.     
  70.     /**
  71.      * Returns iterator
  72.      */
  73.     public function getIterator (Traversable
  74.     {
  75.         return new ArrayIterator$this->data );
  76.     }
  77.     
  78.     /**
  79.      * Create a new TRecord and returns the instance
  80.      * @param $data indexed array
  81.      */
  82.     public static function create($data)
  83.     {
  84.         $object new static;
  85.         $object->fromArray($data);
  86.         $object->store();
  87.         return $object;
  88.     }
  89.     
  90.     /**
  91.      * Executed when the programmer clones an Active Record
  92.      * In this case, we have to clear the ID, to generate a new one
  93.      */
  94.     public function __clone()
  95.     {
  96.         $pk $this->getPrimaryKey();
  97.         unset($this->$pk);
  98.     }
  99.     
  100.     /**
  101.      * Executed whenever an unknown method is executed
  102.      * @param $method Method name
  103.      * @param $parameter Method parameters
  104.      */
  105.     public static function __callStatic($method$parameters)
  106.     {
  107.         $class_name get_called_class();
  108.         if (substr($method,-13== 'InTransaction')
  109.         {
  110.             $method substr($method,0,-13);
  111.             if (method_exists($class_name$method))
  112.             {
  113.                 $database array_shift($parameters);
  114.                 TTransaction::open($database);
  115.                 $content forward_static_call_arrayarray($class_name$method)$parameters);
  116.                 TTransaction::close();
  117.                 return $content;
  118.             }
  119.             else
  120.             {
  121.                 throw new Exception(AdiantiCoreTranslator::translate('Method ^1 not found'$class_name.'::'.$method.'()'));
  122.             }
  123.         }
  124.         else if (method_exists('TRepository'$method))
  125.         {
  126.             $class get_called_class()// get the Active Record class name
  127.             $repository new TRepository$class )// create the repository
  128.             return call_user_func_arrayarray($repository$method)$parameters );
  129.         }
  130.         else
  131.         {
  132.             throw new Exception(AdiantiCoreTranslator::translate('Method ^1 not found'$class_name.'::'.$method.'()'));
  133.         }
  134.     }
  135.     
  136.     /**
  137.      * Executed whenever a property is accessed
  138.      * @param $property Name of the object property
  139.      * @return          The value of the property
  140.      */
  141.     public function __get($property)
  142.     {
  143.         // check if exists a method called get_<property>
  144.         if (method_exists($this'get_'.$property))
  145.         {
  146.             // execute the method get_<property>
  147.             return call_user_func(array($this'get_'.$property));
  148.         }
  149.         else
  150.         {
  151.             if (strpos($property'->'!== FALSE)
  152.             {
  153.                 $parts explode('->'$property);
  154.                 $container $this;
  155.                 foreach ($parts as $part)
  156.                 {
  157.                     if (is_object($container))
  158.                     {
  159.                         $result $container->$part;
  160.                         $container $result;
  161.                     }
  162.                     else
  163.                     {
  164.                         throw new Exception(AdiantiCoreTranslator::translate('Trying to access a non-existent property (^1)'$property));
  165.                     }
  166.                 }
  167.                 return $result;
  168.             }
  169.             else
  170.             {
  171.                 // returns the property value
  172.                 if (isset($this->data[$property]))
  173.                 {
  174.                     return $this->data[$property];
  175.                 }
  176.                 else if (isset($this->vdata[$property]))
  177.                 {
  178.                     return $this->vdata[$property];
  179.                 }
  180.             }
  181.         }
  182.     }
  183.     
  184.     /**
  185.      * Executed whenever a property is assigned
  186.      * @param $property Name of the object property
  187.      * @param $value    Value of the property
  188.      */
  189.     public function __set($property$value)
  190.     {
  191.         if ($property == 'data')
  192.         {
  193.             throw new Exception(AdiantiCoreTranslator::translate('Reserved property name (^1) in class ^2'$propertyget_class($this)));
  194.         }
  195.         
  196.         // check if exists a method called set_<property>
  197.         if (method_exists($this'set_'.$property))
  198.         {
  199.             // executed the method called set_<property>
  200.             call_user_func(array($this'set_'.$property)$value);
  201.         }
  202.         else
  203.         {
  204.             if ($value === NULL)
  205.             {
  206.                 $this->data[$propertyNULL;
  207.             }
  208.             else if (is_scalar($value))
  209.             {
  210.                 // assign the property's value
  211.                 $this->data[$property$value;
  212.                 unset($this->vdata[$property]);
  213.             }
  214.             else
  215.             {
  216.                 // other non-scalar properties that won't be persisted
  217.                 $this->vdata[$property$value;
  218.                 unset($this->data[$property]);
  219.             }
  220.         }
  221.     }
  222.     
  223.     /**
  224.      * Returns if a property is assigned
  225.      * @param $property Name of the object property
  226.      */
  227.     public function __isset($property)
  228.     {
  229.         return isset($this->data[$property]or
  230.                isset($this->vdata[$property]or
  231.                method_exists($this'get_'.$property);
  232.     }
  233.     
  234.     /**
  235.      * Unset a property
  236.      * @param $property Name of the object property
  237.      */
  238.     public function __unset($property)
  239.     {
  240.         unset($this->data[$property]);
  241.         unset($this->vdata[$property]);
  242.     }
  243.     
  244.     /**
  245.      * Returns the cache control
  246.      */
  247.     public function getCacheControl()
  248.     {
  249.         $class get_class($this);
  250.         $cache_name "{$class}::CACHECONTROL";
  251.         
  252.         if defined$cache_name ) )
  253.         {
  254.             $cache_control constant($cache_name);
  255.             $implements class_implements($cache_control);
  256.             
  257.             if (in_array('Adianti\Registry\AdiantiRegistryInterface'$implements))
  258.             {
  259.                 if ($cache_control::enabled())
  260.                 {
  261.                     return $cache_control;
  262.                 }
  263.             }
  264.         }
  265.         
  266.         return FALSE;
  267.     }
  268.     
  269.     /**
  270.      * Returns the name of database entity
  271.      * @return String containing the name of the entity
  272.      */
  273.     public function getEntity()
  274.     {
  275.         // get the Active Record class name
  276.         $class get_class($this);
  277.         // return the TABLENAME Active Record class constant
  278.         return constant("{$class}::TABLENAME");
  279.     }
  280.     
  281.     /**
  282.      * Returns the the name of the primary key for that Active Record
  283.      * @return String containing the primary key name
  284.      */
  285.     public function getPrimaryKey()
  286.     {
  287.         // get the Active Record class name
  288.         $class get_class($this);
  289.         // returns the PRIMARY KEY Active Record class constant
  290.         return constant("{$class}::PRIMARYKEY");
  291.     }
  292.     
  293.     /**
  294.      * Returns the the name of the created at column
  295.      * @return String containing the created at column
  296.      */
  297.     public function getCreatedAtColumn()
  298.     {
  299.         // get the Active Record class name
  300.         $class get_class($this);
  301.         
  302.         if (defined("{$class}::CREATEDAT"))
  303.         {
  304.             // returns the CREATEDAT Active Record class constant
  305.             return constant("{$class}::CREATEDAT");
  306.         }
  307.     }
  308.     
  309.     /**
  310.      * Returns the the name of the updated at column
  311.      * @return String containing the updated at column
  312.      */
  313.     public function getUpdatedAtColumn()
  314.     {
  315.         // get the Active Record class name
  316.         $class get_class($this);
  317.         
  318.         if (defined("{$class}::UPDATEDAT"))
  319.         {
  320.             // returns the UPDATEDAT Active Record class constant
  321.             return constant("{$class}::UPDATEDAT");
  322.         }
  323.     }
  324.     
  325.     /**
  326.      * Returns the the name of the deleted at column
  327.      * @return String containing the deleted at column
  328.      */
  329.     public static function getDeletedAtColumn()
  330.     {
  331.         // get the Active Record class name
  332.         $class get_called_class();
  333.         if(defined("{$class}::DELETEDAT"))
  334.         {
  335.             // returns the DELETEDAT Active Record class constant
  336.             return constant("{$class}::DELETEDAT");
  337.         }
  338.  
  339.         return NULL;
  340.     }
  341.     
  342.     /**
  343.      * Returns the the name of the sequence for primary key
  344.      * @return String containing the sequence name
  345.      */
  346.     private function getSequenceName()
  347.     {
  348.         $conn TTransaction::get();
  349.         $driver $conn->getAttribute(PDO::ATTR_DRIVER_NAME);
  350.         
  351.         // get the Active Record class name
  352.         $class get_class($this);
  353.         
  354.         if (defined("{$class}::SEQUENCE"))
  355.         {
  356.             return constant("{$class}::SEQUENCE");
  357.         }
  358.         else if (in_array($driverarray('oci''oci8')))
  359.         {
  360.             return $this->getEntity().'_seq';
  361.         }
  362.         else
  363.         {
  364.             return $this->getEntity().'_'$this->getPrimaryKey().'_seq';
  365.         }
  366.     }
  367.     
  368.     /**
  369.      * Fill the Active Record properties from another Active Record
  370.      * @param $object An Active Record
  371.      */
  372.     public function mergeObject(TRecord $object)
  373.     {
  374.         $data $object->toArray();
  375.         foreach ($data as $key => $value)
  376.         {
  377.             $this->data[$key$value;
  378.         }
  379.     }
  380.     
  381.     /**
  382.      * Fill the Active Record properties from an indexed array
  383.      * @param $data An indexed array containing the object properties
  384.      */
  385.     public function fromArray($data)
  386.     {
  387.         if (count($this->attributes0)
  388.         {
  389.             $pk $this->getPrimaryKey();
  390.             foreach ($data as $key => $value)
  391.             {
  392.                 // set just attributes defined by the addAttribute()
  393.                 if ((in_array($key$this->attributesAND is_string($key)) OR ($key === $pk))
  394.                 {
  395.                     $this->data[$key$data[$key];
  396.                 }
  397.             }
  398.         }
  399.         else
  400.         {
  401.             foreach ($data as $key => $value)
  402.             {
  403.                 $this->data[$key$data[$key];
  404.             }
  405.         }
  406.     }
  407.     
  408.     /**
  409.      * Return the Active Record properties as an indexed array
  410.      * @param $filter_attributes Array of attributes to be returned.
  411.      * @return An indexed array containing the object properties
  412.      */
  413.     public function toArray$filter_attributes null )
  414.     {
  415.         $attributes $filter_attributes $filter_attributes $this->attributes;
  416.         
  417.         $data array();
  418.         if (count($attributes0)
  419.         {
  420.             $pk $this->getPrimaryKey();
  421.             if (!empty($this->data))
  422.             {
  423.                 foreach ($this->data as $key => $value)
  424.                 {
  425.                     if ((in_array($key$attributesAND is_string($key)) OR ($key === $pk))
  426.                     {
  427.                         $data[$key$this->data[$key];
  428.                     }
  429.                 }
  430.             }
  431.         }
  432.         else
  433.         {
  434.             $data $this->data;
  435.         }
  436.         return $data;
  437.     }
  438.     
  439.     /**
  440.      * Return virtual data (non-persistant properties)
  441.      */
  442.     public function getVirtualData()
  443.     {
  444.         return $this->vdata;
  445.     }
  446.     
  447.     /**
  448.      * Return the Active Record properties as a json string
  449.      * @return JSON String
  450.      */
  451.     public function toJson()
  452.     {
  453.         return json_encode($this->toArray());
  454.     }
  455.     
  456.     /**
  457.      * Render variables inside brackets
  458.      */
  459.     public function render($pattern$cast null)
  460.     {
  461.         $content $pattern;
  462.         if (preg_match_all('/\{(.*?)\}/'$pattern$matches) )
  463.         {
  464.             foreach ($matches[0as $match)
  465.             {
  466.                 $property substr($match1-1);
  467.                 if (substr($property01== '$')
  468.                 {
  469.                     $property substr($property1);
  470.                 }
  471.                 $value $this->$property;
  472.                 if ($cast)
  473.                 {
  474.                     settype($value$cast);
  475.                 }
  476.                 $content  str_replace($match(string) $value$content);
  477.             }
  478.         }
  479.         
  480.         return $content;
  481.     }
  482.     
  483.     /**
  484.      * Evaluate variables inside brackets
  485.      */
  486.     public function evaluate($pattern)
  487.     {
  488.         $content $this->render($pattern'float');
  489.         $content str_replace('+'' + '$content);
  490.         $content str_replace('-'' - '$content);
  491.         $content str_replace('*'' * '$content);
  492.         $content str_replace('/'' / '$content);
  493.         $content str_replace('('' ( '$content);
  494.         $content str_replace(')'' ) '$content);
  495.         
  496.         // fix sintax for operator followed by signal
  497.         foreach (['+''-''*''/'as $operator)
  498.         {
  499.             foreach (['+''-'as $signal)
  500.             {
  501.                 $content str_replace(" {$operator} {$signal} "" {$operator} {$signal}"$content);
  502.                 $content str_replace(" {$operator}  {$signal} "" {$operator} {$signal}"$content);
  503.                 $content str_replace(" {$operator}   {$signal} "" {$operator} {$signal}"$content);
  504.             }
  505.         }
  506.         
  507.         $parser new Parser;
  508.         $content $parser->evaluate(substr($content,1));
  509.         return $content;
  510.     }
  511.     
  512.     /**
  513.      * Register an persisted attribute
  514.      */
  515.     public function addAttribute($attribute)
  516.     {
  517.         if ($attribute == 'data')
  518.         {
  519.             throw new Exception(AdiantiCoreTranslator::translate('Reserved property name (^1) in class ^2'$attributeget_class($this)));
  520.         }
  521.         
  522.         $this->attributes[$attribute;
  523.     }
  524.     
  525.     /**
  526.      * Return the persisted attributes
  527.      */
  528.     public function getAttributes()
  529.     {
  530.         return $this->attributes;
  531.     }
  532.     
  533.     /**
  534.      * Get attribute list
  535.      */
  536.     public function getAttributeList()
  537.     {
  538.         if (count($this->attributes0)
  539.         {
  540.             $attributes $this->attributes;
  541.             array_unshift($attributes$this->getPrimaryKey());
  542.             return implode(', 'array_unique($attributes));
  543.         }
  544.         
  545.         return '*';
  546.     }
  547.     
  548.     /**
  549.      * Store the objects into the database
  550.      * @return      The number of affected rows
  551.      * @exception   Exception if there's no active transaction opened
  552.      */
  553.     public function store()
  554.     {
  555.         $conn TTransaction::get();
  556.         
  557.         if (!$conn)
  558.         {
  559.             // if there's no active transaction opened
  560.             throw new Exception(AdiantiCoreTranslator::translate('No active transactions'': ' . __METHOD__ .' '$this->getEntity());
  561.         }
  562.         
  563.         $driver $conn->getAttribute(PDO::ATTR_DRIVER_NAME);
  564.         
  565.         // get the Active Record class name
  566.         $class get_class($this);
  567.         
  568.         // check if the object has an ID or exists in the database
  569.         $pk $this->getPrimaryKey();
  570.         $createdat $this->getCreatedAtColumn();
  571.         $updatedat $this->getUpdatedAtColumn();
  572.         
  573.         if (method_exists($this'onBeforeStore'))
  574.         {
  575.             $virtual_object = (object) $this->data;
  576.             $this->onBeforeStore$virtual_object );
  577.             $this->data = (array) $virtual_object;
  578.         }
  579.         
  580.         if (empty($this->data[$pk]or (!self::exists($this->$pk)))
  581.         {
  582.             // increments the ID
  583.             if (empty($this->data[$pk]))
  584.             {
  585.                 if ((defined("{$class}::IDPOLICY")) AND (constant("{$class}::IDPOLICY"== 'serial'))
  586.                 {
  587.                     unset($this->$pk);
  588.                 }
  589.                 else if ((defined("{$class}::IDPOLICY")) AND (constant("{$class}::IDPOLICY"== 'uuid'))
  590.                 {
  591.                     $this->$pk implode('-'[
  592.                                      bin2hex(random_bytes(4)),
  593.                                      bin2hex(random_bytes(2)),
  594.                                      bin2hex(chr((ord(random_bytes(1)) 0x0F0x40)) bin2hex(random_bytes(1)),
  595.                                      bin2hex(chr((ord(random_bytes(1)) 0x3F0x80)) bin2hex(random_bytes(1)),
  596.                                      bin2hex(random_bytes(6))
  597.                                  ]);
  598.                 }
  599.                 else
  600.                 {
  601.                     $this->$pk $this->getLastID(+1;
  602.                 }
  603.             }
  604.             // creates an INSERT instruction
  605.             $sql new TSqlInsert;
  606.             $sql->setEntity($this->getEntity());
  607.             // iterate the object data
  608.             foreach ($this->data as $key => $value)
  609.             {
  610.                 // check if the field is a calculated one
  611.                 if !method_exists($this'get_' $keyOR (count($this->attributes0) )
  612.                 {
  613.                     if (count($this->attributes0)
  614.                     {
  615.                         // set just attributes defined by the addAttribute()
  616.                         if ((in_array($key$this->attributesAND is_string($key)) OR ($key === $pk))
  617.                         {
  618.                             // pass the object data to the SQL
  619.                             $sql->setRowData($key$this->data[$key]);
  620.                         }
  621.                     }
  622.                     else
  623.                     {
  624.                         // pass the object data to the SQL
  625.                         $sql->setRowData($key$this->data[$key]);
  626.                     }
  627.                 }
  628.             }
  629.             
  630.             if (!empty($createdat))
  631.             {
  632.                 $info TTransaction::getDatabaseInfo();
  633.                 $date_mask (in_array($info['type']['sqlsrv''dblib''mssql'])) 'Ymd H:i:s' 'Y-m-d H:i:s';
  634.                 $sql->setRowData($createdatdate($date_mask));
  635.             }
  636.         }
  637.         else
  638.         {
  639.             // creates an UPDATE instruction
  640.             $sql new TSqlUpdate;
  641.             $sql->setEntity($this->getEntity());
  642.             // creates a select criteria based on the ID
  643.             $criteria new TCriteria;
  644.             $criteria->add(new TFilter($pk'='$this->$pk));
  645.             $sql->setCriteria($criteria);
  646.             // interate the object data
  647.             foreach ($this->data as $key => $value)
  648.             {
  649.                 if ($key !== $pk// there's no need to change the ID value
  650.                 {
  651.                     // check if the field is a calculated one
  652.                     if !method_exists($this'get_' $keyOR (count($this->attributes0) )
  653.                     {
  654.                         if (count($this->attributes0)
  655.                         {
  656.                             // set just attributes defined by the addAttribute()
  657.                             if ((in_array($key$this->attributesAND is_string($key)) OR ($key === $pk))
  658.                             {
  659.                                 // pass the object data to the SQL
  660.                                 $sql->setRowData($key$this->data[$key]);
  661.                             }
  662.                         }
  663.                         else
  664.                         {
  665.                             // pass the object data to the SQL
  666.                             $sql->setRowData($key$this->data[$key]);
  667.                         }
  668.                     }
  669.                 }
  670.             }
  671.             
  672.             if (!empty($createdat))
  673.             {
  674.                 $sql->unsetRowData($createdat);
  675.             }
  676.             
  677.             if (!empty($updatedat))
  678.             {
  679.                 $info TTransaction::getDatabaseInfo();
  680.                 $date_mask (in_array($info['type']['sqlsrv''dblib''mssql'])) 'Ymd H:i:s' 'Y-m-d H:i:s';
  681.                 $sql->setRowData($updatedatdate($date_mask));
  682.             }
  683.         }
  684.         
  685.         // register the operation in the LOG file
  686.         TTransaction::log($sql->getInstruction());
  687.         
  688.         $dbinfo TTransaction::getDatabaseInfo()// get dbinfo
  689.         if (isset($dbinfo['prep']AND $dbinfo['prep'== '1'// prepared ON
  690.         {
  691.             $command $sql->getInstructionTRUE );
  692.             
  693.             if ($driver == 'firebird')
  694.             {
  695.                 $command str_replace('{{primary_key}}'$pk$command);
  696.             }
  697.             else if ($driver == 'sqlsrv')
  698.             {
  699.                 $command .= ";SELECT SCOPE_IDENTITY() as 'last_inserted_id'";
  700.             }
  701.             
  702.             $result $conn-> prepare $command array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
  703.             $result-> execute $sql->getPreparedVars() );
  704.         }
  705.         else
  706.         {
  707.             $command $sql->getInstruction();
  708.             
  709.             if ($driver == 'firebird')
  710.             {
  711.                 $command str_replace('{{primary_key}}'$pk$command);
  712.             }
  713.             else if ($driver == 'sqlsrv')
  714.             {
  715.                 $command .= ";SELECT SCOPE_IDENTITY() as 'last_inserted_id'";
  716.             }
  717.             
  718.             // execute the query
  719.             $result $conn-> query($command);
  720.         }
  721.         
  722.         if ((defined("{$class}::IDPOLICY")) AND (constant("{$class}::IDPOLICY"== 'serial'))
  723.         {
  724.             if ( ($sql instanceof TSqlInsertAND empty($this->data[$pk]) )
  725.             {
  726.                 if ($driver == 'firebird')
  727.                 {
  728.                     $this->$pk $result-> fetchColumn();
  729.                 }
  730.                 else if ($driver == 'sqlsrv')
  731.                 {
  732.                     $result->nextRowset();
  733.                     $this->$pk $result-> fetchColumn();
  734.                 }
  735.                 else if (in_array($driverarray('oci''oci8')))
  736.                 {
  737.                     $result_id $conn-> query('SELECT ' $this->getSequenceName(".currval FROM dual");
  738.                     $this->$pk $result_id-> fetchColumn();
  739.                 }
  740.                 else
  741.                 {
  742.                     $this->$pk $conn->lastInsertId$this->getSequenceName() );
  743.                 }
  744.             }
  745.         }
  746.         
  747.         if $cache $this->getCacheControl() )
  748.         {
  749.             $record_key $class '['$this->$pk ']';
  750.             if ($cache::setValue$record_key$this->toArray() ))
  751.             {
  752.                 TTransaction::log($record_key ' stored in cache');
  753.             }
  754.         }
  755.         
  756.         if (method_exists($this'onAfterStore'))
  757.         {
  758.             $this->onAfterStore(object) $this->toArray() );
  759.         }
  760.         
  761.         // return the result of the exec() method
  762.         return $result;
  763.     }
  764.     
  765.     /**
  766.      * Tests if an ID exists
  767.      * @param $id  The object ID
  768.      * @exception  Exception if there's no active transaction opened
  769.      */
  770.     public function exists($id)
  771.     {
  772.         if (empty($id))
  773.         {
  774.             return FALSE;
  775.         }
  776.         
  777.         $class get_class($this);     // get the Active Record class name
  778.         $pk $this->getPrimaryKey();  // discover the primary key name
  779.         
  780.         // creates a SELECT instruction
  781.         $sql new TSqlSelect;
  782.         $sql->setEntity($this->getEntity());
  783.         $sql->addColumn($this->getAttributeList());
  784.         
  785.         // creates a select criteria based on the ID
  786.         $criteria new TCriteria;
  787.         $criteria->add(new TFilter($pk'='$id));
  788.         $sql->setCriteria($criteria);
  789.         
  790.         // get the connection of the active transaction
  791.         if ($conn TTransaction::get())
  792.         {
  793.             $dbinfo TTransaction::getDatabaseInfo()// get dbinfo
  794.             if (isset($dbinfo['prep']AND $dbinfo['prep'== '1'// prepared ON
  795.             {
  796.                 $result $conn-> prepare $sql->getInstructionTRUE array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
  797.                 $result-> execute $criteria->getPreparedVars() );
  798.             }
  799.             else
  800.             {
  801.                 $result $conn-> query($sql->getInstruction());
  802.             }
  803.             
  804.             // if there's a result
  805.             if ($result)
  806.             {
  807.                 // returns the data as an object of this class
  808.                 $object $result-> fetchObject(get_class($this));
  809.             }
  810.             
  811.             return is_object($object);
  812.         }
  813.         else
  814.         {
  815.             // if there's no active transaction opened
  816.             throw new Exception(AdiantiCoreTranslator::translate('No active transactions'': ' . __METHOD__ .' '$this->getEntity());
  817.         }
  818.     }
  819.     
  820.     /**
  821.      * ReLoad an Active Record Object from the database
  822.      */
  823.     public function reload()
  824.     {
  825.         // discover the primary key name 
  826.         $pk $this->getPrimaryKey();
  827.         
  828.         return $this->load($this->$pk);
  829.     }
  830.     
  831.     /**
  832.      * Load an Active Record Object from the database
  833.      * @param $id  The object ID
  834.      * @return     The Active Record Object
  835.      * @exception  Exception if there's no active transaction opened
  836.      */
  837.     public function load($id)
  838.     {
  839.         $class get_class($this);     // get the Active Record class name
  840.         $pk $this->getPrimaryKey();  // discover the primary key name
  841.         
  842.         if (method_exists($this'onBeforeLoad'))
  843.         {
  844.             $this->onBeforeLoad$id );
  845.         }
  846.         
  847.         if $cache $this->getCacheControl() )
  848.         {
  849.             $record_key $class '['$id ']';
  850.             if ($fetched_data $cache::getValue$record_key ))
  851.             {
  852.                 $fetched_object = (object) $fetched_data;
  853.                 $loaded_object  clone $this;
  854.                 if (method_exists($this'onAfterLoad'))
  855.                 {
  856.                     $this->onAfterLoad$fetched_object );
  857.                     $loaded_object->fromArray(array) $fetched_object);
  858.                 }
  859.                 else
  860.                 {
  861.                     $loaded_object->fromArray($fetched_data);
  862.                 }
  863.                 TTransaction::log($record_key ' loaded from cache');
  864.                 return $loaded_object;
  865.             }
  866.         }
  867.         
  868.         // creates a SELECT instruction
  869.         $sql new TSqlSelect;
  870.         $sql->setEntity($this->getEntity());
  871.         // use *, once this is called before addAttribute()s
  872.         $sql->addColumn($this->getAttributeList());
  873.         
  874.         // creates a select criteria based on the ID
  875.         $criteria new TCriteria;
  876.         $criteria->add(new TFilter($pk'='$id));
  877.  
  878.         $deletedat self::getDeletedAtColumn();
  879.         if (!$this->trashed && $deletedat)
  880.         {
  881.             $criteria->add(new TFilter($deletedat'IS'NULL));
  882.         }
  883.  
  884.         // define the select criteria
  885.         $sql->setCriteria($criteria);
  886.         // get the connection of the active transaction
  887.         if ($conn TTransaction::get())
  888.         {
  889.             // register the operation in the LOG file
  890.             TTransaction::log($sql->getInstruction());
  891.             
  892.             $dbinfo TTransaction::getDatabaseInfo()// get dbinfo
  893.             if (isset($dbinfo['prep']AND $dbinfo['prep'== '1'// prepared ON
  894.             {
  895.                 $result $conn-> prepare $sql->getInstructionTRUE array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
  896.                 $result-> execute $criteria->getPreparedVars() );
  897.             }
  898.             else
  899.             {
  900.                 // execute the query
  901.                 $result $conn-> query($sql->getInstruction());
  902.             }
  903.             
  904.             // if there's a result
  905.             if ($result)
  906.             {
  907.                 $activeClass get_class($this);
  908.                 $fetched_object $result-> fetchObject();
  909.                 if ($fetched_object)
  910.                 {
  911.                     if (method_exists($this'onAfterLoad'))
  912.                     {
  913.                         $this->onAfterLoad($fetched_object);
  914.                     }
  915.                     $object new $activeClass;
  916.                     $object->fromArray(array) $fetched_object );
  917.                 }
  918.                 else
  919.                 {
  920.                     $object NULL;
  921.                 }
  922.                 
  923.                 if ($object)
  924.                 {
  925.                     if $cache $this->getCacheControl() )
  926.                     {
  927.                         $record_key $class '['$id ']';
  928.                         if ($cache::setValue$record_key$object->toArray() ))
  929.                         {
  930.                             TTransaction::log($record_key ' stored in cache');
  931.                         }
  932.                     }
  933.                 }
  934.             }
  935.             
  936.             return $object;
  937.         }
  938.         else
  939.         {
  940.             // if there's no active transaction opened
  941.             throw new Exception(AdiantiCoreTranslator::translate('No active transactions'': ' . __METHOD__ .' '$this->getEntity());
  942.         }
  943.     }
  944.     
  945.     /**
  946.      * Load trashed records
  947.      */
  948.     public function loadTrashed($id)
  949.     {
  950.         $this->trashed = TRUE;
  951.         return $this->load($id);
  952.     }
  953.     
  954.     /**
  955.      * Delete an Active Record object from the database
  956.      * @param [$id]     The Object ID
  957.      * @exception       Exception if there's no active transaction opened
  958.      */
  959.     public function delete($id NULL)
  960.     {
  961.         $class get_class($this);
  962.         
  963.         if (method_exists($this'onBeforeDelete'))
  964.         {
  965.             $this->onBeforeDelete(object) $this->toArray() );
  966.         }
  967.         
  968.         // discover the primary key name
  969.         $pk $this->getPrimaryKey();
  970.         // if the user has not passed the ID, take the object ID
  971.         $id $id $id $this->$pk;
  972.  
  973.         $deletedat self::getDeletedAtColumn();
  974.         if ($deletedat)
  975.         {
  976.             // creates a Update instruction
  977.             $sql new TSqlUpdate;
  978.             $sql->setEntity($this->getEntity());
  979.  
  980.             $info TTransaction::getDatabaseInfo();
  981.             $date_mask (in_array($info['type']['sqlsrv''dblib''mssql'])) 'Ymd H:i:s' 'Y-m-d H:i:s';
  982.             $sql->setRowData($deletedatdate($date_mask));
  983.         }
  984.         else
  985.         {
  986.             // creates a DELETE instruction
  987.             $sql new TSqlDelete;
  988.             $sql->setEntity($this->getEntity());
  989.         }
  990.  
  991.         // creates a select criteria
  992.         $criteria new TCriteria;
  993.         $criteria->add(new TFilter($pk'='$id));
  994.         // assign the criteria to the delete instruction
  995.         $sql->setCriteria($criteria);
  996.         
  997.         // get the connection of the active transaction
  998.         if ($conn TTransaction::get())
  999.         {
  1000.             // register the operation in the LOG file
  1001.             TTransaction::log($sql->getInstruction());
  1002.             
  1003.             $dbinfo TTransaction::getDatabaseInfo()// get dbinfo
  1004.             if (isset($dbinfo['prep']AND $dbinfo['prep'== '1'// prepared ON
  1005.             {
  1006.                 $result $conn-> prepare $sql->getInstructionTRUE array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
  1007.                 if ($sql instanceof TSqlUpdate)
  1008.                 {
  1009.                     $result-> execute ($sql->getPreparedVars());
  1010.                 }
  1011.                 else
  1012.                 {
  1013.                     $result-> execute ($criteria->getPreparedVars());
  1014.                 }
  1015.             }
  1016.             else
  1017.             {
  1018.                 // execute the query
  1019.                 $result $conn-> query($sql->getInstruction());
  1020.             }
  1021.             
  1022.             if $cache $this->getCacheControl() )
  1023.             {
  1024.                 $record_key $class '['$id ']';
  1025.                 if ($cache::delValue$record_key ))
  1026.                 {
  1027.                     TTransaction::log($record_key ' deleted from cache');
  1028.                 }
  1029.             }
  1030.             
  1031.             if (method_exists($this'onAfterDelete'))
  1032.             {
  1033.                 $this->onAfterDelete(object) $this->toArray() );
  1034.             }
  1035.             
  1036.             unset($this->data);
  1037.             
  1038.             // return the result of the exec() method
  1039.             return $result;
  1040.         }
  1041.         else
  1042.         {
  1043.             // if there's no active transaction opened
  1044.             throw new Exception(AdiantiCoreTranslator::translate('No active transactions'': ' . __METHOD__ .' '$this->getEntity());
  1045.         }
  1046.     }
  1047.     /**
  1048.      * Restore soft deleted object
  1049.      */
  1050.     public function restore()
  1051.     {
  1052.         $deletedat self::getDeletedAtColumn();
  1053.         
  1054.         if ($deletedat)
  1055.         {
  1056.             $pk $this->getPrimaryKey();
  1057.             $this->withTrashed()->where($pk'='$this->$pk)->set($deletedatnull)->update();
  1058.             
  1059.             return $this;
  1060.         }
  1061.         else
  1062.         {
  1063.             throw new Exception(AdiantiCoreTranslator::translate('Softdelete is not active'' : '$this->getEntity());
  1064.         }
  1065.     }
  1066.  
  1067.     /**
  1068.      * Returns the FIRST Object ID from database
  1069.      * @return      An Integer containing the FIRST Object ID from database
  1070.      * @exception   Exception if there's no active transaction opened
  1071.      */
  1072.     public function getFirstID()
  1073.     {
  1074.         $pk $this->getPrimaryKey();
  1075.         
  1076.         // get the connection of the active transaction
  1077.         if ($conn TTransaction::get())
  1078.         {
  1079.             // instancia instrução de SELECT
  1080.             $sql new TSqlSelect;
  1081.             $sql->addColumn("min({$pk}) as {$pk}");
  1082.             $sql->setEntity($this->getEntity());
  1083.             // register the operation in the LOG file
  1084.             TTransaction::log($sql->getInstruction());
  1085.             $result$conn->Query($sql->getInstruction());
  1086.             // retorna os dados do banco
  1087.             $row $result-> fetch();
  1088.             return $row[0];
  1089.         }
  1090.         else
  1091.         {
  1092.             // if there's no active transaction opened
  1093.             throw new Exception(AdiantiCoreTranslator::translate('No active transactions'': ' . __METHOD__ .' '$this->getEntity());
  1094.         }
  1095.     }
  1096.     
  1097.     /**
  1098.      * Returns the LAST Object ID from database
  1099.      * @return      An Integer containing the LAST Object ID from database
  1100.      * @exception   Exception if there's no active transaction opened
  1101.      */
  1102.     public function getLastID()
  1103.     {
  1104.         $pk $this->getPrimaryKey();
  1105.         
  1106.         // get the connection of the active transaction
  1107.         if ($conn TTransaction::get())
  1108.         {
  1109.             // instancia instrução de SELECT
  1110.             $sql new TSqlSelect;
  1111.             $sql->addColumn("max({$pk}) as {$pk}");
  1112.             $sql->setEntity($this->getEntity());
  1113.             // register the operation in the LOG file
  1114.             TTransaction::log($sql->getInstruction());
  1115.             $result$conn->Query($sql->getInstruction());
  1116.             // retorna os dados do banco
  1117.             $row $result-> fetch();
  1118.             return $row[0];
  1119.         }
  1120.         else
  1121.         {
  1122.             // if there's no active transaction opened
  1123.             throw new Exception(AdiantiCoreTranslator::translate('No active transactions'': ' . __METHOD__ .' '$this->getEntity());
  1124.         }
  1125.     }
  1126.     
  1127.     /**
  1128.      * Method getObjects
  1129.      * @param $criteria        Optional criteria
  1130.      * @param $callObjectLoad  If load() method from Active Records must be called to load object parts
  1131.      * @return                 An array containing the Active Records
  1132.      */
  1133.     public static function getObjects($criteria NULL$callObjectLoad TRUE$withTrashed FALSE)
  1134.     {
  1135.         // get the Active Record class name
  1136.         $class get_called_class();
  1137.         
  1138.         // create the repository
  1139.         $repository new TRepository($class$withTrashed);
  1140.         
  1141.         if (!$criteria)
  1142.         {
  1143.             $criteria new TCriteria;
  1144.         }
  1145.         
  1146.         return $repository->load$criteria$callObjectLoad );
  1147.     }
  1148.     
  1149.     /**
  1150.      * Method countObjects
  1151.      * @param $criteria        Optional criteria
  1152.      * @param $withTrashed 
  1153.      * @return                 An array containing the Active Records
  1154.      */
  1155.     public static function countObjects($criteria NULL$withTrashed FALSE)
  1156.     {
  1157.         // get the Active Record class name
  1158.         $class get_called_class();
  1159.         
  1160.         // create the repository
  1161.         $repository new TRepository($class$withTrashed);
  1162.         if (!$criteria)
  1163.         {
  1164.             $criteria new TCriteria;
  1165.         }
  1166.         
  1167.         return $repository->count$criteria );
  1168.     }
  1169.     
  1170.     /**
  1171.      * Load composite objects (parts in composition relationship)
  1172.      * @param $composite_class Active Record Class for composite objects
  1173.      * @param $foreign_key Foreign key in composite objects
  1174.      * @param $id Primary key of parent object
  1175.      * @returns Array of Active Records
  1176.      */
  1177.     public function loadComposite($composite_class$foreign_key$id NULL$order NULL)
  1178.     {
  1179.         $pk $this->getPrimaryKey()// discover the primary key name
  1180.         $id $id $id $this->$pk// if the user has not passed the ID, take the object ID
  1181.         $criteria TCriteria::create[$foreign_key => $id ]['order' => $order);
  1182.         $repository new TRepository($composite_class);
  1183.         return $repository->load($criteria);
  1184.     }
  1185.     
  1186.     /**
  1187.      * Load composite objects. Shortcut for loadComposite
  1188.      * @param $composite_class Active Record Class for composite objects
  1189.      * @param $foreign_key Foreign key in composite objects
  1190.      * @param $primary_key Primary key of parent object
  1191.      * @returns Array of Active Records
  1192.      */
  1193.     public function hasMany($composite_class$foreign_key NULL$primary_key NULL$order NULL)
  1194.     {
  1195.         $foreign_key = isset($foreign_key$foreign_key $this->underscoreFromCamelCase(get_class($this)) '_id';
  1196.         $primary_key $primary_key $primary_key $this->getPrimaryKey();
  1197.         return $this->loadComposite($composite_class$foreign_key$this->$primary_key$order);
  1198.     }
  1199.     
  1200.     /**
  1201.      * Create a criteria to load composite objects
  1202.      * @param $composite_class Active Record Class for composite objects
  1203.      * @param $foreign_key Foreign key in composite objects
  1204.      * @param $primary_key Primary key of parent object
  1205.      * @returns TRepository instance
  1206.      */
  1207.     public function filterMany($composite_class$foreign_key NULL$primary_key NULL$order NULL)
  1208.     {
  1209.         $foreign_key = isset($foreign_key$foreign_key $this->underscoreFromCamelCase(get_class($this)) '_id';
  1210.         $primary_key $primary_key $primary_key $this->getPrimaryKey();
  1211.         
  1212.         $criteria TCriteria::create[$foreign_key => $this->$primary_key ]['order' => $order);
  1213.         $repository new TRepository($composite_class);
  1214.         $repository->setCriteria($criteria);
  1215.         return $repository;
  1216.     }
  1217.     
  1218.     /**
  1219.      * Delete composite objects (parts in composition relationship)
  1220.      * @param $composite_class Active Record Class for composite objects
  1221.      * @param $foreign_key Foreign key in composite objects
  1222.      * @param $id Primary key of parent object
  1223.      */
  1224.     public function deleteComposite($composite_class$foreign_key$id$callObjectLoad FALSE)
  1225.     {
  1226.         $criteria new TCriteria;
  1227.         $criteria->add(new TFilter($foreign_key'='$id));
  1228.         
  1229.         $repository new TRepository($composite_class);
  1230.         return $repository->delete($criteria$callObjectLoad);
  1231.     }
  1232.     
  1233.     /**
  1234.      * Save composite objects (parts in composition relationship)
  1235.      * @param $composite_class Active Record Class for composite objects
  1236.      * @param $foreign_key Foreign key in composite objects
  1237.      * @param $id Primary key of parent object
  1238.      * @param $objects Array of Active Records to be saved
  1239.      */
  1240.     public function saveComposite($composite_class$foreign_key$id$objects$callObjectLoad FALSE)
  1241.     {
  1242.         $this->deleteComposite($composite_class$foreign_key$id$callObjectLoad);
  1243.         
  1244.         if ($objects)
  1245.         {
  1246.             foreach ($objects as $object)
  1247.             {
  1248.                 $object-> $foreign_key  $id;
  1249.                 $object->store();
  1250.             }
  1251.         }
  1252.     }
  1253.     
  1254.     /**
  1255.      * Load aggregated objects (parts in aggregation relationship)
  1256.      * @param $aggregate_class Active Record Class for aggregated objects
  1257.      * @param $join_class Active Record Join Class (Parent / Aggregated)
  1258.      * @param $foreign_key_parent Foreign key in Join Class to parent object
  1259.      * @param $foreign_key_child Foreign key in Join Class to child object
  1260.      * @param $id Primary key of parent object
  1261.      * @returns Array of Active Records
  1262.      */
  1263.     public function loadAggregate($aggregate_class$join_class$foreign_key_parent$foreign_key_child$id NULL)
  1264.     {
  1265.         // discover the primary key name
  1266.         $pk $this->getPrimaryKey();
  1267.         // if the user has not passed the ID, take the object ID
  1268.         $id $id $id $this->$pk;
  1269.         
  1270.         $criteria   new TCriteria;
  1271.         $criteria->add(new TFilter($foreign_key_parent'='$id));
  1272.         
  1273.         $repository new TRepository($join_class);
  1274.         $objects $repository->load($criteria);
  1275.         
  1276.         $aggregates array();
  1277.         if ($objects)
  1278.         {
  1279.             foreach ($objects as $object)
  1280.             {
  1281.                 $aggregates[new $aggregate_class($object-> $foreign_key_child);
  1282.             }
  1283.         }
  1284.         return $aggregates;
  1285.     }
  1286.     
  1287.     /**
  1288.      * Load aggregated objects. Shortcut to loadAggregate
  1289.      * @param $aggregate_class Active Record Class for aggregated objects
  1290.      * @param $join_class Active Record Join Class (Parent / Aggregated)
  1291.      * @param $foreign_key_parent Foreign key in Join Class to parent object
  1292.      * @param $foreign_key_child Foreign key in Join Class to child object
  1293.      * @returns Array of Active Records
  1294.      */
  1295.     public function belongsToMany($aggregate_class$join_class NULL$foreign_key_parent NULL$foreign_key_child NULL)
  1296.     {
  1297.         $class get_class($this);
  1298.         $join_class = isset($join_class$join_class $class.$aggregate_class;
  1299.         $foreign_key_parent = isset($foreign_key_parent$foreign_key_parent $this->underscoreFromCamelCase($class'_id';
  1300.         $foreign_key_child  = isset($foreign_key_child)  $foreign_key_child  $this->underscoreFromCamelCase($aggregate_class'_id';
  1301.         
  1302.         return $this->loadAggregate($aggregate_class$join_class$foreign_key_parent$foreign_key_child);
  1303.     }
  1304.     
  1305.     /**
  1306.      * Save aggregated objects (parts in aggregation relationship)
  1307.      * @param $join_class Active Record Join Class (Parent / Aggregated)
  1308.      * @param $foreign_key_parent Foreign key in Join Class to parent object
  1309.      * @param $foreign_key_child Foreign key in Join Class to child object
  1310.      * @param $id Primary key of parent object
  1311.      * @param $objects Array of Active Records to be saved
  1312.      */
  1313.     public function saveAggregate($join_class$foreign_key_parent$foreign_key_child$id$objects)
  1314.     {
  1315.         $this->deleteComposite($join_class$foreign_key_parent$id);
  1316.         
  1317.         if ($objects)
  1318.         {
  1319.             foreach ($objects as $object)
  1320.             {
  1321.                 $join new $join_class;
  1322.                 $join-> $foreign_key_parent $id;
  1323.                 $join-> $foreign_key_child  $object->id;
  1324.                 $join->store();
  1325.             }
  1326.         }
  1327.     }
  1328.     
  1329.     /**
  1330.      * Returns the first object
  1331.      */
  1332.     public static function first($withTrashed FALSE)
  1333.     {
  1334.         $object new static;
  1335.         $id $object->getFirstID();
  1336.  
  1337.         return self::find($id$withTrashed);
  1338.     }
  1339.     
  1340.     /**
  1341.      * First record or a new one
  1342.      */
  1343.     public static function firstOrNew($filters NULL)
  1344.     {
  1345.         $criteria TCriteria::create($filters);
  1346.         $criteria->setProperty('limit'1);
  1347.         $objects self::getObjects$criteria );
  1348.         
  1349.         if (isset($objects[0]))
  1350.         {
  1351.             return $objects[0];
  1352.         }
  1353.         else
  1354.         {
  1355.             $created new static;
  1356.             if (is_array($filters))
  1357.             {
  1358.                 $created->fromArray($filters);
  1359.             }
  1360.             return $created;
  1361.         }
  1362.     }
  1363.     
  1364.     /**
  1365.      * First record or persist a new one
  1366.      */
  1367.     public static function firstOrCreate($filters NULL)
  1368.     {
  1369.         $obj self::firstOrNew($filters);
  1370.         $obj->store();
  1371.         return $obj;
  1372.     }
  1373.     
  1374.     /**
  1375.      * Returns the last object
  1376.      */
  1377.     public static function last($withTrashed FALSE)
  1378.     {
  1379.         $object new static;
  1380.         $id $object->getLastID();
  1381.  
  1382.         return self::find($id$withTrashed);
  1383.     }
  1384.     
  1385.     /**
  1386.      * Find a Active Record and returns it
  1387.      * @return The Active Record itself or NULL when not found
  1388.      */
  1389.     public static function find($id$withTrashed FALSE)
  1390.     {
  1391.         $classname get_called_class();
  1392.         $ar new $classname;
  1393.         
  1394.         if ($withTrashed)
  1395.         {
  1396.             return $ar->loadTrashed($id);
  1397.         }
  1398.         else
  1399.         {
  1400.             return $ar->load($id);
  1401.         }
  1402.     }
  1403.     
  1404.     /**
  1405.      * Returns all objects
  1406.      */
  1407.     public static function all($indexed false$withTrashed FALSE)
  1408.     {
  1409.         $objects self::getObjects(NULLFALSE$withTrashed);
  1410.         if ($indexed)
  1411.         {
  1412.             $list [];
  1413.             foreach ($objects as $object)
  1414.             {
  1415.                 $pk $object->getPrimaryKey();
  1416.                 $list$object->$pk $object;
  1417.             }
  1418.             return $list;
  1419.         }
  1420.         else
  1421.         {
  1422.             return $objects;
  1423.         }
  1424.     }
  1425.     
  1426.     /**
  1427.      * Save the object
  1428.      */
  1429.     public function save()
  1430.     {
  1431.         $this->store();
  1432.     }
  1433.     
  1434.     /**
  1435.      * Creates an indexed array
  1436.      * @returns the TRepository object with a filter
  1437.      */
  1438.     public static function getIndexedArray($indexColumn$valueColumn$criteria NULL$withTrashed FALSE)
  1439.     {
  1440.         $sort_array false;
  1441.         
  1442.         if (empty($criteria))
  1443.         {
  1444.             $criteria new TCriteria;
  1445.             $sort_array true;
  1446.         }
  1447.         
  1448.         $indexedArray array();
  1449.         $class get_called_class()// get the Active Record class name
  1450.         $repository new TRepository($class$withTrashed)// create the repository
  1451.         $objects $repository->load($criteriaFALSE);
  1452.         if ($objects)
  1453.         {
  1454.             foreach ($objects as $object)
  1455.             {
  1456.                 $key (isset($object->$indexColumn)) $object->$indexColumn $object->render($indexColumn);
  1457.                 $val (isset($object->$valueColumn)) $object->$valueColumn $object->render($valueColumn);
  1458.                 
  1459.                 $indexedArray$key $val;
  1460.             }
  1461.         }
  1462.         
  1463.         if ($sort_array)
  1464.         {
  1465.             asort($indexedArray);
  1466.         }
  1467.         return $indexedArray;
  1468.     }
  1469.     
  1470.     /**
  1471.      * Creates a Repository with filter
  1472.      * @returns the TRepository object with a filter
  1473.      */
  1474.     public static function select()
  1475.     {
  1476.         $repository new TRepositoryget_called_class() )// create the repository
  1477.         return $repository->selectfunc_get_args() );
  1478.     }
  1479.     
  1480.     /**
  1481.      * Creates a Repository with group
  1482.      * @returns the TRepository object with a group
  1483.      */
  1484.     public static function groupBy($group)
  1485.     {
  1486.         $repository new TRepositoryget_called_class() )// create the repository
  1487.         return $repository->groupBy($group);
  1488.     }
  1489.     
  1490.     /**
  1491.      * Creates a Repository with filter
  1492.      * @returns the TRepository object with a filter
  1493.      */
  1494.     public static function where($variable$operator$value$logicOperator TExpression::AND_OPERATOR)
  1495.     {
  1496.         $repository new TRepositoryget_called_class() )// create the repository
  1497.         return $repository->where($variable$operator$value$logicOperator);
  1498.     }
  1499.     
  1500.     /**
  1501.      * Creates a Repository with OR filter
  1502.      * @returns the TRepository object with an OR filter
  1503.      */
  1504.     public static function orWhere($variable$operator$value)
  1505.     {
  1506.         $repository new TRepositoryget_called_class() )// create the repository
  1507.         return $repository->orWhere($variable$operator$value);
  1508.     }
  1509.     
  1510.     /**
  1511.      * Creates an ordered repository
  1512.      * @param  $order = Order column
  1513.      * @param  $direction = Order direction (asc, desc)
  1514.      * @returns the ordered TRepository object
  1515.      */
  1516.     public static function orderBy($order$direction 'asc')
  1517.     {
  1518.         $repository new TRepositoryget_called_class() )// create the repository
  1519.         return $repository->orderBy$order$direction );
  1520.     }
  1521.     
  1522.     /**
  1523.      * Creates a Repository with limit
  1524.      * @returns the TRepository object
  1525.      */
  1526.     public static function take($limit)
  1527.     {
  1528.         $repository new TRepositoryget_called_class() )// create the repository
  1529.         return $repository->take($limit);
  1530.     }
  1531.     
  1532.     /**
  1533.      * Creates a Repository with offset
  1534.      * @returns the TRepository object
  1535.      */
  1536.     public static function skip($offset)
  1537.     {
  1538.         $repository new TRepositoryget_called_class() )// create the repository
  1539.         return $repository->skip($offset);
  1540.     }
  1541.  
  1542.     public static function withTrashed()
  1543.     {
  1544.         return new TRepository(get_called_class()TRUE);
  1545.     }
  1546.  
  1547.     private function underscoreFromCamelCase($string)
  1548.     {
  1549.         return strtolower(preg_replace('/([a-z])([A-Z])/''$'.'1_$'.'2'$string))
  1550.     }
  1551. }