db instanceof Connection) { throw new InvalidConfigException('$db must be instance of ' . Connection::className()); } } /** * Executes this command. * * @return array result cursor. * @throws Exception on failure. */ public function execute() { $token = $this->log( [ $this->model, 'command', ], $this->parameters, __METHOD__ ); try { $this->beginProfile($token, __METHOD__); $this->db->open(); $result = $this->internalExecute(); $this->endProfile($token, __METHOD__); } catch (RuntimeException $e) { $this->endProfile($token, __METHOD__); throw new Exception($e->getMessage(), $e->getCode(), $e); } return $result; } /** * Executes this command as a Odoo query * * @param string $model model * @param array $parameters * * @return array result cursor. * @throws \artbox\odoo\components\Exception on failure */ public function query($model, $parameters = [ [] ]) { $this->model = $model; $this->parameters = $parameters; $token = $this->log( 'find', array_merge( [ 'model' => $model, ], $parameters ), __METHOD__ ); try { $this->beginProfile($token, __METHOD__); $this->db->open(); $result = $this->internalExecute(); $this->endProfile($token, __METHOD__); } catch (RuntimeException $e) { $this->endProfile($token, __METHOD__); throw new Exception($e->getMessage(), $e->getCode(), $e); } return $result; } /** * Executes this command as a Odoo find * * @param string $model model * @param array $parameters * @param array $mapping * * @return array result cursor. * @throws \artbox\odoo\components\Exception on failure */ public function find($model, $parameters = [ [] ], $mapping = []) { $this->model = $model; $this->parameters = $parameters; $this->mapping = $mapping; $token = $this->log( 'find', array_merge( [ 'model' => $model, ], $parameters, $mapping ), __METHOD__ ); try { $this->beginProfile($token, __METHOD__); $this->db->open(); $result = $this->internalExecute(); $this->endProfile($token, __METHOD__); } catch (RuntimeException $e) { $this->endProfile($token, __METHOD__); throw new Exception($e->getMessage(), $e->getCode(), $e); } return $result; } /** * Return ids from Odoo by filter parameters * * @param string $model model * @param array $parameters * @param array $options * * @return array result cursor. * @throws \artbox\odoo\components\Exception on failure */ public function search(string $model, array $parameters = [ [] ], array $options = []) { $token = $this->log( 'search', array_merge( [ 'model' => $model, ], $parameters, $options ), __METHOD__ ); try { $this->beginProfile($token, __METHOD__); $this->db->open(); $result = $this->internalRun($model, 'search', $parameters, $options); $this->endProfile($token, __METHOD__); } catch (RuntimeException $e) { $this->endProfile($token, __METHOD__); throw new Exception($e->getMessage(), $e->getCode(), $e); } return $result; } /** * Return count of records from Odoo by filter parameters * * @param string $model model * @param array $parameters * @param array $options * * @return integer result cursor. * @throws \artbox\odoo\components\Exception on failure */ public function count(string $model, array $parameters = [ [] ], array $options = []) { $token = $this->log( 'count', array_merge( [ 'model' => $model, ], $parameters, $options ), __METHOD__ ); try { $this->beginProfile($token, __METHOD__); $this->db->open(); $result = $this->internalRun($model, 'search_count', $parameters, $options); $this->endProfile($token, __METHOD__); } catch (RuntimeException $e) { $this->endProfile($token, __METHOD__); throw new Exception($e->getMessage(), $e->getCode(), $e); } return $result; } /** * Return records from Odoo by filter parameters * * @param string $model model * @param array $ids * @param array $fields * * @return array result cursor. * @throws \artbox\odoo\components\Exception on failure */ public function read(string $model, array $ids, array $fields = []) { $token = $this->log( 'read', array_merge( [ 'model' => $model, ], $ids ), __METHOD__ ); try { $this->beginProfile($token, __METHOD__); $this->db->open(); $result = $this->internalRun($model, 'read', $ids, $fields); $this->endProfile($token, __METHOD__); } catch (RuntimeException $e) { $this->endProfile($token, __METHOD__); throw new Exception($e->getMessage(), $e->getCode(), $e); } return $result; } /** * Return fields from Odoo by filter parameters * * @param string $model model * @param array $parameters * @param array $options * * @return array result cursor. * @throws \artbox\odoo\components\Exception on failure */ public function fields(string $model, array $parameters = [], array $options = []) { $token = $this->log( 'fields', array_merge( [ 'model' => $model, ], $parameters, $options ), __METHOD__ ); try { $this->beginProfile($token, __METHOD__); $this->db->open(); $result = $this->internalRun($model, 'fields_get', $parameters, $options); $this->endProfile($token, __METHOD__); } catch (RuntimeException $e) { $this->endProfile($token, __METHOD__); throw new Exception($e->getMessage(), $e->getCode(), $e); } return $result; } /** * Search and read records from Odoo by filter parameters * * @param string $model model * @param array $parameters * @param array $options * * @return array result cursor. * @throws \artbox\odoo\components\Exception on failure */ public function searchRead(string $model, array $parameters = [], array $options = []) { $token = $this->log( 'search_read', array_merge( [ 'model' => $model, ], $parameters, $options ), __METHOD__ ); try { $this->beginProfile($token, __METHOD__); $this->db->open(); $result = $this->internalRun($model, 'search_read', $parameters, $options); $this->endProfile($token, __METHOD__); } catch (RuntimeException $e) { $this->endProfile($token, __METHOD__); throw new Exception($e->getMessage(), $e->getCode(), $e); } return $result; } /** * Create record in Odoo and return id * * @param string $model model * @param array $parameters * * @return array result cursor. * @throws \artbox\odoo\components\Exception on failure * @internal param array $options */ public function create(string $model, array $parameters = []) { $token = $this->log( 'create', array_merge( [ 'model' => $model, ], $parameters ), __METHOD__ ); try { $this->beginProfile($token, __METHOD__); $this->db->open(); $result = $this->internalRun($model, 'create', $parameters); $this->endProfile($token, __METHOD__); } catch (RuntimeException $e) { $this->endProfile($token, __METHOD__); throw new Exception($e->getMessage(), $e->getCode(), $e); } return $result; } /** * Update record in Odoo * * @param string $model model * @param array $parameters * * @return array result cursor. * @throws \artbox\odoo\components\Exception on failure * @internal param array $options */ public function update(string $model, array $parameters = []) { $token = $this->log( 'update', array_merge( [ 'model' => $model, ], $parameters ), __METHOD__ ); try { $this->beginProfile($token, __METHOD__); $this->db->open(); $result = $this->internalRun($model, 'write', $parameters); $this->endProfile($token, __METHOD__); } catch (RuntimeException $e) { $this->endProfile($token, __METHOD__); throw new Exception($e->getMessage(), $e->getCode(), $e); } return $result; } /** * Delete records from Odoo * * @param string $model model * @param array $parameters * * @return array result cursor. * @throws \artbox\odoo\components\Exception on failure * @internal param array $options */ public function delete(string $model, array $parameters = []) { $token = $this->log( 'delete', array_merge( [ 'model' => $model, ], $parameters ), __METHOD__ ); try { $this->beginProfile($token, __METHOD__); $this->db->open(); $result = $this->internalRun($model, 'unlink', $parameters); $this->endProfile($token, __METHOD__); } catch (RuntimeException $e) { $this->endProfile($token, __METHOD__); throw new Exception($e->getMessage(), $e->getCode(), $e); } return $result; } /** * Logs the command data if logging is enabled at [[db]]. * * @param array|string $namespace command namespace. * @param array $data command data. * @param string $category log category * * @return string|false log token, `false` if log is not enabled. */ protected function log($namespace, $data, $category) { if ($this->db->enableLogging) { $token = $this->db->getLogBuilder() ->generateToken($namespace, $data); \Yii::info($token, $category); return $token; } return false; } /** * Marks the beginning of a code block for profiling. * * @param string $token token for the code block * @param string $category the category of this log message * * @see endProfile() */ protected function beginProfile($token, $category) { if ($token !== false && $this->db->enableProfiling) { \Yii::beginProfile($token, $category); } } /** * Marks the end of a code block for profiling. * * @param string $token token for the code block * @param string $category the category of this log message * * @see beginProfile() */ protected function endProfile($token, $category) { if ($token !== false && $this->db->enableProfiling) { \Yii::endProfile($token, $category); } } protected function internalExecute() { $client = $this->db->getFetchClient(); return call_user_func_array( [ $client, 'execute_kw', ], [ $this->db->db, $this->db->getUid(), $this->db->password, $this->model, $this->method, $this->parameters, $this->mapping, ] ); } /** * @param string $model * @param string $method * @param array $parameters * @param array $mapping * * @return mixed */ protected function internalRun(string $model, string $method, array $parameters, array $mapping = []) { $client = $this->db->getFetchClient(); return call_user_func_array( [ $client, 'execute_kw', ], [ $this->db->db, $this->db->getUid(), $this->db->password, $model, $method, $parameters, $mapping, ] ); } }