Example #1
0
 protected function bindEncodedParams()
 {
     foreach ($this->params as $k => $v) {
         $encoded = false;
         foreach ($this->encoders as $encoder) {
             $result = $encoder->encodeParam($this->conn, $v, $encoded);
             if ($encoded) {
                 $v = $result;
                 break;
             }
         }
         if ($v instanceof StreamInterface) {
             if (!$v->isReadable()) {
                 throw new \InvalidArgumentException('Input stream must be readable to be used as DB input param');
             }
             // FIXME: This is a workaround for PHP7 crashing with Sqlite LOB params bound to input streams...
             if ($this->conn->getDriverName() == DB::DRIVER_SQLITE && defined('PHP_MAJOR_VERSION') && PHP_MAJOR_VERSION > 5) {
                 $this->stmt->bindValue($k, $v->getContents());
             } else {
                 $this->stmt->bindValue($k, (new StreamWrapper($v))->getResource(), \PDO::PARAM_LOB);
             }
         } elseif ($v instanceof UUID) {
             switch ($this->conn->getDriverName()) {
                 case DB::DRIVER_MSSQL:
                 case DB::DRIVER_POSTGRESQL:
                     $this->stmt->bindValue($k, (string) $v);
                     break;
                 default:
                     $this->stmt->bindValue($k, $v->toBinary());
             }
         } else {
             $this->stmt->bindValue($k, $v);
         }
     }
 }
Example #2
0
 /**
  * {@inheritdoc}
  */
 public function findExecution(UUID $id)
 {
     static $injectVars = NULL;
     if ($injectVars === NULL) {
         $injectVars = new \ReflectionMethod(VirtualExecution::class, 'injectVariablesLocal');
         $injectVars->setAccessible(true);
     }
     $ref = (string) $id;
     if (isset($this->executions[$ref])) {
         return $this->executions[$ref];
     }
     // Need to select multiple rows as one process instance may span over different process definitions (using CallActivity)
     $sql = "\tSELECT DISTINCT e.`process_id`, d.`id` as definition_id, d.`definition`\r\n\t\t\t\t\tFROM `#__bpmn_execution` AS e\r\n\t\t\t\t\tINNER JOIN `#__bpmn_process_definition` AS d ON (d.`id` = e.`definition_id`)\r\n\t\t\t\t\tWHERE e.`process_id` = (\r\n\t\t\t\t\t\tSELECT `process_id` FROM `#__bpmn_execution` WHERE `id` = :eid\r\n\t\t\t\t\t)\r\n\t\t";
     $stmt = $this->conn->prepare($sql);
     $stmt->bindValue('eid', $id);
     $stmt->transform('process_id', new UUIDTransformer());
     $stmt->transform('definition_id', new UUIDTransformer());
     $stmt->execute();
     $rows = $stmt->fetchRows();
     if (empty($rows)) {
         throw new \OutOfBoundsException(sprintf('Execution not found: "%s"', $ref));
     }
     $processId = $rows[0]['process_id'];
     $definitions = [];
     foreach ($rows as $row) {
         $definitions[(string) $row['definition_id']] = unserialize(BinaryData::decode($row['definition']));
     }
     // Select (and lock) all execution rows of the process instance using a pessimistic lock.
     $sql = "\tSELECT e.*\r\n\t\t\t\t\tFROM `#__bpmn_execution` AS e\r\n\t\t\t\t\tWHERE e.`process_id` = :pid\r\n\t\t";
     switch ($this->conn->getDriverName()) {
         case DB::DRIVER_MYSQL:
         case DB::DRIVER_POSTGRESQL:
             $sql .= " FOR UPDATE";
     }
     $stmt = $this->conn->prepare($sql);
     $stmt->bindAll(['pid' => $processId]);
     $stmt->transform('id', new UUIDTransformer());
     $stmt->transform('pid', new UUIDTransformer());
     $stmt->transform('process_id', new UUIDTransformer());
     $stmt->transform('definition_id', new UUIDTransformer());
     $stmt->execute();
     $variables = [];
     $executions = [];
     $parents = [];
     while ($row = $stmt->fetchNextRow()) {
         $id = $row['id'];
         $pid = $row['pid'];
         $defId = (string) $row['definition_id'];
         if (empty($definitions[$defId])) {
             throw new \OutOfBoundsException(sprintf('Missing process definition "%s" referenced from execution "%s"', $defId, $id));
         }
         $definition = $definitions[$defId];
         if ($pid !== NULL) {
             $parents[(string) $id] = (string) $pid;
         }
         $state = (int) $row['state'];
         $active = (double) $row['active'];
         $node = $row['node'] === NULL ? NULL : $definition->findNode($row['node']);
         $transition = $row['transition'] === NULL ? NULL : $definition->findTransition($row['transition']);
         $businessKey = $row['business_key'];
         $variables[(string) $id] = [];
         $exec = $executions[(string) $id] = new VirtualExecution($id, $this, $definition);
         $exec->setBusinessKey($businessKey);
         $exec->setExecutionState($state);
         $exec->setNode($node);
         $exec->setTransition($transition);
         $exec->setTimestamp($active);
     }
     foreach ($parents as $id => $pid) {
         $executions[$id]->setParentExecution($executions[$pid]);
     }
     if (!empty($variables)) {
         $params = [];
         foreach (array_keys($variables) as $i => $k) {
             $params['p' . $i] = new UUID($k);
         }
         $placeholders = implode(', ', array_map(function ($p) {
             return ':' . $p;
         }, array_keys($params)));
         $sql = "\tSELECT `execution_id`, `name`, `value_blob`\r\n\t\t\t\t\t\tFROM `#__bpmn_execution_variables`\r\n\t\t\t\t\t\tWHERE `execution_id` IN ({$placeholders})\r\n\t\t\t";
         $stmt = $this->conn->prepare($sql);
         $stmt->bindAll($params);
         $stmt->transform('execution_id', new UUIDTransformer());
         $stmt->execute();
         while (false !== ($row = $stmt->fetchNextRow())) {
             $variables[(string) $row['execution_id']][$row['name']] = unserialize(BinaryData::decode($row['value_blob']));
         }
     }
     foreach ($variables as $id => $vars) {
         $injectVars->invoke($executions[$id], $vars);
     }
     foreach ($executions as $execution) {
         $execution->setSyncState(Execution::SYNC_STATE_NO_CHANGE);
         $this->executions[(string) $execution->getId()] = $execution;
     }
     if (empty($this->executions[$ref])) {
         throw new \OutOfBoundsException(sprintf('Execution not found: "%s"', $ref));
     }
     return $this->executions[$ref];
 }