PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/openerp/OOActiveRecord.php

https://bitbucket.org/satyanagara/codeigniter-openerp-library
PHP | 393 lines | 339 code | 51 blank | 3 comment | 57 complexity | 60032f3a622046fea44e68606b0d5df5 MD5 | raw file
  1. <?php
  2. abstract class OOActiveRecord extends CModel
  3. {
  4. private static $_models = array(); // class name => model
  5. private static $_mappings = array();
  6. private $_md; // meta data
  7. private $_new=false; // whether this instance is new or not
  8. private $_attributes=array(); // attribute name => attribute value
  9. private $_related=array(); // attribute name => related objects
  10. private $_c; // query criteria (used by finder only)
  11. private $_pk; // old primary key value
  12. private $_alias='t'; // the table alias being used for query
  13. public $isComplete = true;
  14. public $relations;
  15. public $objectToStringField = 'name';
  16. public function __construct($scenario='insert')
  17. {
  18. if ($scenario == null) {// internally used by populateRecord() and model()
  19. return;
  20. }
  21. $this->setScenario($scenario);
  22. $this->setIsNewRecord(true);
  23. $this->init();
  24. $this->attachBehaviors($this->behaviors());
  25. $this->afterConstruct();
  26. }
  27. public function __get($name)
  28. {
  29. if(!$this->isComplete && $name !== $this->objectToStringField) {
  30. $this->makeComplete();
  31. }
  32. if (isset($this->_attributes[$name])) {
  33. return $this->_attributes[$name];
  34. } else if (isset($this->getMetaData()->fields[$name])){
  35. return null;
  36. } else if (isset($this->_related[$name])){
  37. return $this->_related[$name];
  38. } else if (isset($this->getMetaData()->relations[$name])) {
  39. return $this->getRelated($name);
  40. } else {
  41. return parent::__get($name);
  42. }
  43. }
  44. public function __set($name, $value)
  45. {
  46. if($this->setAttribute($name, $value) === false){
  47. if(isset($this->getMetaData()->relations[$name])) {
  48. $this->relations[$name] = $value;
  49. } else {
  50. parent::__set($name,$value);
  51. }
  52. }
  53. }
  54. public function makeComplete()
  55. {
  56. $data = Yii::app()->openerp->read($this->modelName(), array($this->_attributes['id']));
  57. $md = $this->getMetaData();
  58. foreach ($data[0] as $name => $value) {
  59. if(property_exists($this, $name)) {
  60. $this->$name = $value;
  61. } else if(isset($md->fields[$name])) {
  62. $this->_attributes[$name] = $value;
  63. } else if(isset($md->relations[$name])) {
  64. $this->relations[$name] = $value;
  65. }
  66. }
  67. $this->isComplete = true;
  68. }
  69. public function __toString()
  70. {
  71. return "{$this->{$this->objectToStringField}}";
  72. }
  73. public function init()
  74. {
  75. }
  76. private static function updateMapping($modelsPath)
  77. {
  78. $files = scandir($modelsPath);
  79. foreach ($files as $file) {
  80. if ((substr($file, -4) === '.php')) {
  81. $class = str_replace('.php','',$file);
  82. $reflection = new ReflectionClass($class);
  83. $parent = $reflection->getParentClass()->name;
  84. $parent2 = $reflection->getParentClass()->getParentClass()->name;
  85. if(in_array('OOActiveRecord',compact('parent','parent2'))) {
  86. self::$_mappings[self::model($class)->modelName()] = $class;
  87. }
  88. }
  89. }
  90. }
  91. /**
  92. * return class from model
  93. */
  94. public static function getClassName($model)
  95. {
  96. if (empty(self::$_mappings)) {
  97. $fileMapping = Yii::app()->runtimePath . '/openerp/mapping.php';
  98. $modelsPath = Yii::app()->getComponent('openerp')->getModelsFullPath();
  99. if (!file_exists($fileMapping)) {
  100. mkdir(Yii::app()->runtimePath . '/openerp',0700);
  101. self::updateMapping($modelsPath);
  102. file_put_contents($fileMapping, serialize(self::$_mappings));
  103. } else {
  104. $fileMappingDate = date("F d Y H:i:s.", filemtime($fileMapping));
  105. $modelsPathDate = date("F d Y H:i:s.", filemtime($modelsPath));
  106. if ($modelsPathDate > $fileMappingDate) {
  107. self::updateMapping($modelsPath);
  108. file_put_contents($fileMapping, serialize(self::$_mappings));
  109. } else {
  110. self::$_mappings = unserialize(file_get_contents($fileMapping));
  111. }
  112. }
  113. }
  114. return self::$_mappings[$model];
  115. }
  116. public function getRelated($name, $complete=false)
  117. {
  118. if (!isset($this->_related[$name])) {
  119. $md = $this->getMetaData();
  120. if ($md->relations[$name]['type'] === 'many2one') {
  121. if ($complete) {
  122. $listData = $this->getOpenerp()->read(
  123. $md->relations[$name]['relationModel'],
  124. array($this->relations[$name][0]));
  125. $this->_related[$name] = self::model(self::getClassName(
  126. $md->relations[$name]['relationModel']))
  127. ->populateRecord($listData[0]);
  128. } else {
  129. $this->_related[$name] = self::model(self::getClassName(
  130. $md->relations[$name]['relationModel']))
  131. ->populateRecord(array(
  132. 'id' => $this->relations[$name][0],
  133. $this->objectToStringField => $this->relations[$name][1],
  134. ));
  135. $this->_related[$name]->isComplete = false;
  136. }
  137. } else {
  138. $listData = $this->getOpenerp()->read(
  139. $md->relations[$name]['relationModel'],
  140. $this->relations[$name]);
  141. $this->_related[$name] = self::model(self::getClassName($md->relations[$name]['relationModel']))->populateRecords($listData);
  142. }
  143. }
  144. return $this->_related[$name];
  145. }
  146. public function getIsNewRecord()
  147. {
  148. return $this->_new;
  149. }
  150. public function setIsNewRecord($value)
  151. {
  152. $this->_new=$value;
  153. }
  154. public function setAttribute($name, $value)
  155. {
  156. if(property_exists($this,$name)) {
  157. $this->$name=$value;
  158. } else if(isset($this->getMetaData()->fields[$name])) {
  159. $this->_attributes[$name]=$value;
  160. } else {
  161. return false;
  162. }
  163. return true;
  164. }
  165. public function getPrimaryKey()
  166. {
  167. return $this->id;
  168. }
  169. public function getMetaData()
  170. {
  171. if ($this->_md !== null) {
  172. return $this->_md;
  173. } else {
  174. return $this->_md=self::model(get_class($this))->_md;
  175. }
  176. }
  177. public function rules()
  178. {
  179. return array(
  180. array(implode(',', $this->getMetaData()->requiredFields),'required'),
  181. array(implode(',', $this->getMetaData()->numericalFields),'numerical'),
  182. array(implode(',', $this->attributeNames()), 'safe', 'on' => 'search'),
  183. );
  184. }
  185. public function attributeLabels()
  186. {
  187. return $this->getMetaData()->attributeLabels;
  188. }
  189. public function attributeNames()
  190. {
  191. return array_keys($this->getMetaData()->fields);
  192. }
  193. public function getOpenerp()
  194. {
  195. return Yii::app()->getComponent('openerp');
  196. }
  197. protected function instantiate()
  198. {
  199. $class=get_class($this);
  200. $model=new $class(null);
  201. return $model;
  202. }
  203. public function populateRecord(array $attributes, $callAfterFind=true)
  204. {
  205. $record=$this->instantiate($attributes);
  206. $record->setScenario('update');
  207. $record->init();
  208. $md = $record->getMetaData();
  209. foreach ($attributes as $name => $value) {
  210. if(property_exists($record, $name)) {
  211. $record->$name = $value;
  212. } else if(isset($md->fields[$name])) {
  213. $record->_attributes[$name] = $value;
  214. } else if(isset($md->relations[$name])) {
  215. $record->relations[$name] = $value;
  216. }
  217. }
  218. $record->_pk = $record->getPrimaryKey();
  219. $record->attachBehaviors($record->behaviors());
  220. if ($callAfterFind) {
  221. $record->afterFind();
  222. }
  223. return $record;
  224. }
  225. public function populateRecords($data, $callAfterFind=true, $index=null)
  226. {
  227. $records=array();
  228. foreach($data as $attributes)
  229. {
  230. if(($record=$this->populateRecord($attributes,$callAfterFind))!==null)
  231. {
  232. if($index === null) {
  233. $records[] = $record;
  234. } else {
  235. $records[$record->$index]=$record;
  236. }
  237. }
  238. }
  239. return $records;
  240. }
  241. protected function query($criteria, $all=false)
  242. {
  243. if (!$all) {
  244. $criteria->limit = 1;
  245. }
  246. $listData = $this->getOpenerp()->query($this->modelName(), $criteria);
  247. return $all ? $this->populateRecords($listData, true, $criteria->index) : $this->populateRecord($listData[0]);
  248. }
  249. public function findAll($value)
  250. {
  251. $criteria = is_array($value) ? OOCriteria($value): $value;
  252. return $this->query($criteria, true);
  253. }
  254. public function find($criteria)
  255. {
  256. $criteria = is_array($value) ? OOCriteria($value): $value;
  257. return $this->query($criteria);
  258. }
  259. public function count($value)
  260. {
  261. $criteria = is_array($value) ? OOCriteria($value): $value;
  262. return $this->getOpenerp()->query($this->modelName(), $criteria, true);
  263. }
  264. public function findByPk($pk)
  265. {
  266. $data = $this->getOpenerp()->read($this->modelName(), array($pk));
  267. return $this->populateRecord($data[0]);
  268. }
  269. public static function model($className=__CLASS__)
  270. {
  271. if(isset(self::$_models[$className]))
  272. return self::$_models[$className];
  273. else
  274. {
  275. $model=self::$_models[$className]=new $className(null);
  276. $model->_md=new OOActiveRecordMetaData($model);
  277. $model->attachBehaviors($model->behaviors());
  278. return $model;
  279. }
  280. }
  281. public function defaultScope()
  282. {
  283. return array();
  284. }
  285. public function getOOCriteria($createIfNull=true)
  286. {
  287. if ($this->_c===null) {
  288. if (($c = $this->defaultScope()) !== array() || $createIfNull) {
  289. $this->_c = new OOCriteria($c);
  290. }
  291. }
  292. return $this->_c;
  293. }
  294. public function setOOCriteria($criteria)
  295. {
  296. $this->_c=$criteria;
  297. }
  298. public function onAfterFind($event)
  299. {
  300. $this->raiseEvent('onAfterFind',$event);
  301. }
  302. protected function afterFind()
  303. {
  304. if ($this->hasEventHandler('onAfterFind')) {
  305. $this->onAfterFind(new CEvent($this));
  306. }
  307. }
  308. abstract public function modelName();
  309. }
  310. class OOActiveRecordMetaData
  311. {
  312. public $fields = array();
  313. public $attributeLabels = array();
  314. public $relations = array();
  315. public $requiredFields = array();
  316. public $numericalFields = array();
  317. public function __construct($model)
  318. {
  319. $metadatas = $model->getOpenerp()->getMetaData($model->modelName());
  320. $metadatas['id'] = array(
  321. 'required' => true,
  322. 'type' => 'integer',
  323. 'label' => 'Id',
  324. 'relationModel' => '',
  325. 'foreignKeyField' => '',
  326. );
  327. foreach($metadatas as $name => $md) {
  328. if ($md['required']) {
  329. $this->requiredFields[] = $name;
  330. }
  331. if (in_array($md['type'], array('integer','float','many2one'))) {
  332. $this->numericalFields[] = $name;
  333. }
  334. if (in_array($md['type'], array('many2one','one2many','many2many'))) {
  335. $this->relations[$name] = $md;
  336. } else {
  337. $this->fields[$name] = $md;
  338. }
  339. $this->attributeLabels[$name] = $md['label'];
  340. }
  341. }
  342. }