Esempio n. 1
0
 /**
  * Create a new SqlDbSvc
  *
  * @param array $settings
  *
  * @throws \InvalidArgumentException
  * @throws \Exception
  */
 public function __construct($settings = [])
 {
     parent::__construct($settings);
     $config = ArrayUtils::clean(ArrayUtils::get($settings, 'config'));
     Session::replaceLookups($config, true);
     $driver = isset($config['driver']) ? $config['driver'] : null;
     $this->dbConn = ConnectionFactory::createConnection($driver, $config);
     $this->dbConn->setCache($this);
     $this->dbConn->setExtraStore($this);
     $defaultSchemaOnly = ArrayUtils::getBool($config, 'default_schema_only');
     $this->dbConn->setDefaultSchemaOnly($defaultSchemaOnly);
     switch ($this->dbConn->getDBName()) {
         case SqlDbDriverTypes::MYSQL:
         case SqlDbDriverTypes::MYSQLI:
             $this->dbConn->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true);
             break;
         case SqlDbDriverTypes::DBLIB:
             $this->dbConn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
             break;
     }
     $attributes = ArrayUtils::clean(ArrayUtils::get($settings, 'attributes'));
     if (!empty($attributes)) {
         $this->dbConn->setAttributes($attributes);
     }
 }
Esempio n. 2
0
 public function getParameterAsBool($key, $default = false)
 {
     if (!is_null($this->parameters)) {
         return ArrayUtils::getBool($this->parameters, $key, $default);
     }
     return Scalar::boolval(Request::query($key, $default));
 }
Esempio n. 3
0
 /**
  * @param array $settings
  *
  * @throws ServiceUnavailableException
  */
 public function __construct(array $settings = [])
 {
     parent::__construct($settings);
     if (!extension_loaded('v8js')) {
         throw new ServiceUnavailableException("This instance cannot run server-side javascript scripts. The 'v8js' is not available.");
     }
     $name = ArrayUtils::get($settings, 'name', self::EXPOSED_OBJECT_NAME, true);
     $variables = ArrayUtils::get($settings, 'variables', [], true);
     $extensions = ArrayUtils::get($settings, 'extensions', [], true);
     // accept comma-delimited string
     $extensions = is_string($extensions) ? array_map('trim', explode(',', trim($extensions, ','))) : $extensions;
     $reportUncaughtExceptions = ArrayUtils::getBool($settings, 'report_uncaught_exceptions', false);
     $logMemoryUsage = ArrayUtils::getBool($settings, 'log_memory_usage', false);
     static::startup($settings);
     //  Set up our script mappings for module loading
     /** @noinspection PhpUndefinedClassInspection */
     $this->engine = new \V8Js($name, $variables, $extensions, $reportUncaughtExceptions);
     /**
      * This is the callback for the exposed "require()" function in the sandbox
      */
     if (static::$moduleLoaderAvailable) {
         /** @noinspection PhpUndefinedMethodInspection */
         $this->engine->setModuleLoader(function ($module) {
             return static::loadScriptingModule($module);
         });
     } else {
         /** @noinspection PhpUndefinedClassInspection */
         Log::debug('  * no "require()" support in V8 library v' . \V8Js::V8_VERSION);
     }
     if ($logMemoryUsage) {
         /** @noinspection PhpUndefinedMethodInspection */
         $loadedExtensions = $this->engine->getExtensions();
         Log::debug('  * engine created with the following extensions: ' . (!empty($loadedExtensions) ? implode(', ', array_keys($loadedExtensions)) : '**NONE**'));
     }
 }
Esempio n. 4
0
 /**
  * Create a new SqlDbSvc
  *
  * @param array $settings
  *
  * @throws \InvalidArgumentException
  * @throws \Exception
  */
 public function __construct($settings = [])
 {
     parent::__construct($settings);
     $config = ArrayUtils::clean(ArrayUtils::get($settings, 'config'));
     $this->cacheEnabled = ArrayUtils::getBool($config, 'cache_enabled');
     $this->cacheTTL = intval(ArrayUtils::get($config, 'cache_ttl', \Config::get('df.default_cache_ttl')));
     $this->cachePrefix = 'service_' . $this->id . ':';
 }
Esempio n. 5
0
 /**
  * Convert the model instance to an array.
  *
  * @return array
  */
 public function toArray()
 {
     $attributes = $this->attributesToArray();
     if (ArrayUtils::getBool($attributes, 'private')) {
         $attributes['value'] = self::PRIVATE_MASK;
     }
     return array_merge($attributes, $this->relationsToArray());
 }
Esempio n. 6
0
 /**
  * {@inheritdoc}
  */
 public function retrieveRecordsByFilter($table, $filter = null, $params = [], $extras = [])
 {
     $fields = ArrayUtils::get($extras, ApiOptions::FIELDS);
     $ssFilters = ArrayUtils::get($extras, 'ss_filters');
     $scanProperties = [static::TABLE_INDICATOR => $table];
     $fields = static::buildAttributesToGet($fields);
     if (!empty($fields)) {
         $scanProperties['AttributesToGet'] = $fields;
     }
     $parsedFilter = static::buildCriteriaArray($filter, $params, $ssFilters);
     if (!empty($parsedFilter)) {
         $scanProperties['ScanFilter'] = $parsedFilter;
     }
     $limit = intval(ArrayUtils::get($extras, ApiOptions::LIMIT));
     if ($limit > 0) {
         $scanProperties['Limit'] = $limit;
         $scanProperties['Count'] = true;
     }
     $offset = intval(ArrayUtils::get($extras, ApiOptions::OFFSET));
     if ($offset > 0) {
         $scanProperties['ExclusiveStartKey'] = $offset;
         $scanProperties['Count'] = true;
     }
     try {
         $result = $this->parent->getConnection()->scan($scanProperties);
         $items = ArrayUtils::clean($result['Items']);
         $out = [];
         foreach ($items as $item) {
             $out[] = $this->unformatAttributes($item);
         }
         $next = $this->unformatAttributes($result['LastEvaluatedKey']);
         $next = current($next);
         // todo handle more than one index here.
         $count = $result['Count'];
         $out = static::cleanRecords($out);
         $needMore = $count - $offset > $limit;
         $addCount = ArrayUtils::getBool($extras, ApiOptions::INCLUDE_COUNT);
         if ($addCount || $needMore) {
             $out['meta']['count'] = $count;
             if ($needMore) {
                 $out['meta']['next'] = $next;
             }
         }
         return $out;
     } catch (\Exception $ex) {
         throw new InternalServerErrorException("Failed to filter records from '{$table}'.\n{$ex->getMessage()}");
     }
 }
Esempio n. 7
0
 /**
  * {@inheritdoc}
  */
 protected function addToTransaction($record = null, $id = null, $extras = null, $rollback = false, $continue = false, $single = false)
 {
     $fields = ArrayUtils::get($extras, ApiOptions::FIELDS);
     $ssFilters = ArrayUtils::get($extras, 'ss_filters');
     $updates = ArrayUtils::get($extras, 'updates');
     $idFields = ArrayUtils::get($extras, 'id_fields');
     $needToIterate = $single || $continue || 1 < count($this->tableIdsInfo);
     $requireMore = ArrayUtils::getBool($extras, 'require_more');
     $client = $this->parent->getGuzzleClient();
     $out = [];
     switch ($this->getAction()) {
         case Verbs::POST:
             $parsed = $this->parseRecord($record, $this->tableFieldsInfo, $ssFilters);
             if (empty($parsed)) {
                 throw new BadRequestException('No valid fields were found in record.');
             }
             $native = json_encode($parsed);
             $result = $this->parent->callGuzzle('POST', 'sobjects/' . $this->transactionTable . '/', null, $native, $client);
             if (!ArrayUtils::getBool($result, 'success', false)) {
                 $msg = json_encode(ArrayUtils::get($result, 'errors'));
                 throw new InternalServerErrorException("Record insert failed for table '{$this->transactionTable}'.\n" . $msg);
             }
             $id = ArrayUtils::get($result, 'id');
             // add via record, so batch processing can retrieve extras
             return $requireMore ? parent::addToTransaction($id) : [$idFields => $id];
         case Verbs::PUT:
         case Verbs::MERGE:
         case Verbs::PATCH:
             if (!empty($updates)) {
                 $record = $updates;
             }
             $parsed = $this->parseRecord($record, $this->tableFieldsInfo, $ssFilters, true);
             if (empty($parsed)) {
                 throw new BadRequestException('No valid fields were found in record.');
             }
             static::removeIds($parsed, $idFields);
             $native = json_encode($parsed);
             $result = $this->parent->callGuzzle('PATCH', 'sobjects/' . $this->transactionTable . '/' . $id, null, $native, $client);
             if ($result && !ArrayUtils::getBool($result, 'success', false)) {
                 $msg = ArrayUtils::get($result, 'errors');
                 throw new InternalServerErrorException("Record update failed for table '{$this->transactionTable}'.\n" . $msg);
             }
             // add via record, so batch processing can retrieve extras
             return $requireMore ? parent::addToTransaction($id) : [$idFields => $id];
         case Verbs::DELETE:
             $result = $this->parent->callGuzzle('DELETE', 'sobjects/' . $this->transactionTable . '/' . $id, null, null, $client);
             if ($result && !ArrayUtils::getBool($result, 'success', false)) {
                 $msg = ArrayUtils::get($result, 'errors');
                 throw new InternalServerErrorException("Record delete failed for table '{$this->transactionTable}'.\n" . $msg);
             }
             // add via record, so batch processing can retrieve extras
             return $requireMore ? parent::addToTransaction($id) : [$idFields => $id];
         case Verbs::GET:
             if (!$needToIterate) {
                 return parent::addToTransaction(null, $id);
             }
             $fields = $this->buildFieldList($this->transactionTable, $fields, $idFields);
             $result = $this->parent->callGuzzle('GET', 'sobjects/' . $this->transactionTable . '/' . $id, ['fields' => $fields]);
             if (empty($result)) {
                 throw new NotFoundException("Record with identifier '" . print_r($id, true) . "' not found.");
             }
             $out = $result;
             break;
     }
     return $out;
 }
Esempio n. 8
0
 /**
  * @param array $data Merge some attributes from an array
  */
 public function mergeFromArray(array $data)
 {
     $this->setStatusCode(ArrayUtils::get($data, 'status_code'));
     if (ArrayUtils::getBool($data, 'payload_changed')) {
         $this->setContentType(ArrayUtils::get($data, 'content_type'));
         $this->setContent(ArrayUtils::get($data, 'content'));
     }
 }
Esempio n. 9
0
 /**
  * {@inheritdoc}
  */
 public function retrieveRecordsByFilter($table, $filter = null, $params = [], $extras = [])
 {
     $coll = $this->selectTable($table);
     $fields = ArrayUtils::get($extras, ApiOptions::FIELDS);
     $ssFilters = ArrayUtils::get($extras, 'ss_filters');
     $fieldArray = static::buildFieldArray($fields);
     $criteria = static::buildCriteriaArray($filter, $params, $ssFilters);
     $limit = intval(ArrayUtils::get($extras, ApiOptions::LIMIT, 0));
     $offset = intval(ArrayUtils::get($extras, ApiOptions::OFFSET, 0));
     $sort = static::buildSortArray(ArrayUtils::get($extras, ApiOptions::ORDER));
     $addCount = ArrayUtils::getBool($extras, ApiOptions::INCLUDE_COUNT, false);
     try {
         /** @var \MongoCursor $result */
         $result = $coll->find($criteria, $fieldArray);
         $count = $result->count();
         $maxAllowed = static::getMaxRecordsReturnedLimit();
         if ($offset) {
             $result = $result->skip($offset);
         }
         if ($sort) {
             $result = $result->sort($sort);
         }
         if ($limit < 1 || $limit > $maxAllowed) {
             $limit = $maxAllowed;
         }
         $result = $result->limit($limit);
         $out = iterator_to_array($result);
         $out = static::cleanRecords($out);
         $needMore = $count - $offset > $limit;
         if ($addCount || $needMore) {
             $out['meta']['count'] = $count;
             if ($needMore) {
                 $out['meta']['next'] = $offset + $limit;
             }
         }
         return $out;
     } catch (\Exception $ex) {
         throw new InternalServerErrorException("Failed to filter records from '{$table}'.\n{$ex->getMessage()}");
     }
 }
Esempio n. 10
0
 /**
  * @param array $data Merge some attributes from an array
  */
 public function mergeFromArray(array $data)
 {
     $this->setMethod(ArrayUtils::get($data, 'method'));
     $this->setParameters(ArrayUtils::get($data, 'parameters'));
     $this->setHeaders(ArrayUtils::get($data, 'headers'));
     $this->setPayloadData(ArrayUtils::get($data, 'payload'));
     if (ArrayUtils::getBool($data, 'content_changed')) {
         $this->setContent(ArrayUtils::get($data, 'content'), ArrayUtils::get($data, 'content_type'));
     }
 }
Esempio n. 11
0
 /**
  * @param array $data
  * @param bool  $extract
  * @param bool  $clean
  * @param bool  $checkExist
  *
  * @return array
  */
 protected function handleFolderContentFromData($data, $extract = false, $clean = false, $checkExist = false)
 {
     $out = [];
     if (!empty($data) && ArrayUtils::isArrayNumeric($data)) {
         foreach ($data as $key => $resource) {
             switch (ArrayUtils::get($resource, 'type')) {
                 case 'folder':
                     $name = ArrayUtils::get($resource, 'name', '');
                     $srcPath = ArrayUtils::get($resource, 'source_path');
                     if (!empty($srcPath)) {
                         $srcContainer = ArrayUtils::get($resource, 'source_container', $this->container);
                         // copy or move
                         if (empty($name)) {
                             $name = FileUtilities::getNameFromPath($srcPath);
                         }
                         $fullPathName = $this->folderPath . $name . '/';
                         $out[$key] = ['name' => $name, 'path' => $fullPathName, 'type' => 'folder'];
                         try {
                             $this->driver->copyFolder($this->container, $fullPathName, $srcContainer, $srcPath, true);
                             $deleteSource = ArrayUtils::getBool($resource, 'delete_source');
                             if ($deleteSource) {
                                 $this->driver->deleteFolder($this->container, $srcPath, true);
                             }
                         } catch (\Exception $ex) {
                             $out[$key]['error'] = ['message' => $ex->getMessage()];
                         }
                     } else {
                         $fullPathName = $this->folderPath . $name . '/';
                         $content = ArrayUtils::get($resource, 'content', '');
                         $isBase64 = ArrayUtils::getBool($resource, 'is_base64');
                         if ($isBase64) {
                             $content = base64_decode($content);
                         }
                         $out[$key] = ['name' => $name, 'path' => $fullPathName, 'type' => 'folder'];
                         try {
                             $this->driver->createFolder($this->container, $fullPathName, $content);
                         } catch (\Exception $ex) {
                             $out[$key]['error'] = ['message' => $ex->getMessage()];
                         }
                     }
                     break;
                 case 'file':
                     $name = ArrayUtils::get($resource, 'name', '');
                     $srcPath = ArrayUtils::get($resource, 'source_path');
                     if (!empty($srcPath)) {
                         // copy or move
                         $srcContainer = ArrayUtils::get($resource, 'source_container', $this->container);
                         if (empty($name)) {
                             $name = FileUtilities::getNameFromPath($srcPath);
                         }
                         $fullPathName = $this->folderPath . $name;
                         $out[$key] = ['name' => $name, 'path' => $fullPathName, 'type' => 'file'];
                         try {
                             $this->driver->copyFile($this->container, $fullPathName, $srcContainer, $srcPath, true);
                             $deleteSource = ArrayUtils::getBool($resource, 'delete_source');
                             if ($deleteSource) {
                                 $this->driver->deleteFile($this->container, $srcPath);
                             }
                         } catch (\Exception $ex) {
                             $out[$key]['error'] = ['message' => $ex->getMessage()];
                         }
                     } elseif (isset($resource['content'])) {
                         $fullPathName = $this->folderPath . $name;
                         $out[$key] = ['name' => $name, 'path' => $fullPathName, 'type' => 'file'];
                         $content = ArrayUtils::get($resource, 'content', '');
                         $isBase64 = ArrayUtils::getBool($resource, 'is_base64');
                         if ($isBase64) {
                             $content = base64_decode($content);
                         }
                         try {
                             $this->driver->writeFile($this->container, $fullPathName, $content);
                         } catch (\Exception $ex) {
                             $out[$key]['error'] = ['message' => $ex->getMessage()];
                         }
                     }
                     break;
             }
         }
     }
     return $out;
 }
Esempio n. 12
0
 /**
  * {@inheritdoc}
  */
 protected function commitTransaction($extras = null)
 {
     if (empty($this->batchRecords) && empty($this->batchIds)) {
         if (isset($this->transaction)) {
             $this->transaction->commit();
         }
         return null;
     }
     $updates = ArrayUtils::get($extras, 'updates');
     $ssFilters = ArrayUtils::get($extras, 'ss_filters');
     $fields = ArrayUtils::get($extras, ApiOptions::FIELDS);
     $idFields = ArrayUtils::get($extras, 'id_fields');
     $related = ArrayUtils::get($extras, 'related');
     $requireMore = ArrayUtils::getBool($extras, 'require_more') || !empty($related);
     $allowRelatedDelete = ArrayUtils::getBool($extras, 'allow_related_delete', false);
     $relatedInfo = $this->describeTableRelated($this->transactionTable);
     $where = [];
     $params = [];
     $idName = isset($this->tableIdsInfo, $this->tableIdsInfo[0], $this->tableIdsInfo[0]->name) ? $this->tableIdsInfo[0]->name : null;
     if (empty($idName)) {
         throw new BadRequestException('No valid identifier found for this table.');
     }
     if (!empty($this->batchRecords)) {
         if (is_array($this->batchRecords[0])) {
             $temp = [];
             foreach ($this->batchRecords as $record) {
                 $temp[] = ArrayUtils::get($record, $idName);
             }
             $where[] = ['in', $idName, $temp];
         } else {
             $where[] = ['in', $idName, $this->batchRecords];
         }
     } else {
         $where[] = ['in', $idName, $this->batchIds];
     }
     $serverFilter = $this->buildQueryStringFromData($ssFilters, $params);
     if (!empty($serverFilter)) {
         $where[] = $serverFilter;
     }
     if (count($where) > 1) {
         array_unshift($where, 'AND');
     } else {
         $where = $where[0];
     }
     $out = [];
     $action = $this->getAction();
     if (!empty($this->batchRecords)) {
         if (1 == count($this->tableIdsInfo)) {
             // records are used to retrieve extras
             // ids array are now more like records
             $fields = empty($fields) ? $idFields : $fields;
             $result = $this->parseFieldsForSqlSelect($fields, $this->tableFieldsInfo);
             $bindings = ArrayUtils::get($result, 'bindings');
             $fields = ArrayUtils::get($result, 'fields');
             $fields = empty($fields) ? '*' : $fields;
             $result = $this->recordQuery($this->transactionTable, $fields, $where, $params, $bindings, $extras);
             if (empty($result)) {
                 throw new NotFoundException('No records were found using the given identifiers.');
             }
             $out = $result;
         } else {
             $out = $this->retrieveRecords($this->transactionTable, $this->batchRecords, $extras);
         }
         $this->batchRecords = [];
     } elseif (!empty($this->batchIds)) {
         /** @var Command $command */
         $command = $this->dbConn->createCommand();
         switch ($action) {
             case Verbs::PUT:
             case Verbs::MERGE:
             case Verbs::PATCH:
                 if (!empty($updates)) {
                     $parsed = $this->parseRecord($updates, $this->tableFieldsInfo, $ssFilters, true);
                     if (!empty($parsed)) {
                         $rows = $command->update($this->transactionTable, $parsed, $where, $params);
                         if (0 >= $rows) {
                             throw new NotFoundException('No records were found using the given identifiers.');
                         }
                         if (count($this->batchIds) !== $rows) {
                             throw new BadRequestException('Batch Error: Not all requested records could be updated.');
                         }
                     }
                     foreach ($this->batchIds as $id) {
                         if (!empty($relatedInfo)) {
                             $this->updateRelations($this->transactionTable, $updates, $id, $relatedInfo, $allowRelatedDelete);
                         }
                     }
                     if ($requireMore) {
                         $fields = empty($fields) ? $idFields : $fields;
                         $result = $this->parseFieldsForSqlSelect($fields, $this->tableFieldsInfo);
                         $bindings = ArrayUtils::get($result, 'bindings');
                         $fields = ArrayUtils::get($result, 'fields');
                         $fields = empty($fields) ? '*' : $fields;
                         $result = $this->recordQuery($this->transactionTable, $fields, $where, $params, $bindings, $extras);
                         if (empty($result)) {
                             throw new NotFoundException('No records were found using the given identifiers.');
                         }
                         $out = $result;
                     }
                 }
                 break;
             case Verbs::DELETE:
                 if ($requireMore) {
                     $fields = empty($fields) ? $idFields : $fields;
                     $result = $this->parseFieldsForSqlSelect($fields, $this->tableFieldsInfo);
                     $bindings = ArrayUtils::get($result, 'bindings');
                     $fields = ArrayUtils::get($result, 'fields');
                     $fields = empty($fields) ? '*' : $fields;
                     $result = $this->recordQuery($this->transactionTable, $fields, $where, $params, $bindings, $extras);
                     if (count($this->batchIds) !== count($result)) {
                         $errors = [];
                         foreach ($this->batchIds as $index => $id) {
                             $found = false;
                             if (empty($result)) {
                                 foreach ($result as $record) {
                                     if ($id == ArrayUtils::get($record, $idName)) {
                                         $out[$index] = $record;
                                         $found = true;
                                         continue;
                                     }
                                 }
                             }
                             if (!$found) {
                                 $errors[] = $index;
                                 $out[$index] = "Record with identifier '" . print_r($id, true) . "' not found.";
                             }
                         }
                     } else {
                         $out = $result;
                     }
                 }
                 $rows = $command->delete($this->transactionTable, $where, $params);
                 if (count($this->batchIds) !== $rows) {
                     throw new BadRequestException('Batch Error: Not all requested records were deleted.');
                 }
                 break;
             case Verbs::GET:
                 $fields = empty($fields) ? $idFields : $fields;
                 $result = $this->parseFieldsForSqlSelect($fields, $this->tableFieldsInfo);
                 $bindings = ArrayUtils::get($result, 'bindings');
                 $fields = ArrayUtils::get($result, 'fields');
                 $fields = empty($fields) ? '*' : $fields;
                 $result = $this->recordQuery($this->transactionTable, $fields, $where, $params, $bindings, $extras);
                 if (empty($result)) {
                     throw new NotFoundException('No records were found using the given identifiers.');
                 }
                 if (count($this->batchIds) !== count($result)) {
                     $errors = [];
                     foreach ($this->batchIds as $index => $id) {
                         $found = false;
                         foreach ($result as $record) {
                             if ($id == ArrayUtils::get($record, $idName)) {
                                 $out[$index] = $record;
                                 $found = true;
                                 continue;
                             }
                         }
                         if (!$found) {
                             $errors[] = $index;
                             $out[$index] = "Record with identifier '" . print_r($id, true) . "' not found.";
                         }
                     }
                     if (!empty($errors)) {
                         $context = ['error' => $errors, ResourcesWrapper::getWrapper() => $out];
                         throw new NotFoundException('Batch Error: Not all records could be retrieved.', null, null, $context);
                     }
                 }
                 $out = $result;
                 break;
             default:
                 break;
         }
         if (empty($out)) {
             $out = [];
             foreach ($this->batchIds as $id) {
                 $out[] = [$idName => $id];
             }
         }
         $this->batchIds = [];
     }
     if (isset($this->transaction)) {
         $this->transaction->commit();
     }
     return $out;
 }
Esempio n. 13
0
 /**
  * @param string $table
  * @param mixed  $ids - array or comma-delimited list of record identifiers
  * @param array  $extras
  *
  * @throws \Exception
  * @return array
  */
 public function retrieveRecordsByIds($table, $ids, $extras = [])
 {
     $ids = DbUtilities::validateAsArray($ids, ',', true, 'The request contains no valid identifiers.');
     $fields = ArrayUtils::get($extras, ApiOptions::FIELDS);
     $idFields = ArrayUtils::get($extras, ApiOptions::ID_FIELD);
     $idTypes = ArrayUtils::get($extras, ApiOptions::ID_TYPE);
     $isSingle = 1 == count($ids);
     $continue = $isSingle ? false : ArrayUtils::getBool($extras, ApiOptions::CONTINUES, false);
     $this->initTransaction($table, $idFields, $idTypes);
     $extras['single'] = $isSingle;
     $extras['id_fields'] = $idFields;
     $extras['require_more'] = static::requireMoreFields($fields, $idFields);
     $out = [];
     $errors = [];
     try {
         foreach ($ids as $index => $id) {
             try {
                 if (false === ($id = static::checkForIds($id, $this->tableIdsInfo, $extras, true))) {
                     throw new BadRequestException("Required id field(s) not valid in request {$index}: " . print_r($id, true));
                 }
                 $result = $this->addToTransaction(null, $id, $extras, false, $continue, $isSingle);
                 if (isset($result)) {
                     // operation performed, take output
                     $out[$index] = $result;
                 }
             } catch (\Exception $ex) {
                 if ($isSingle || !$continue) {
                     if (0 !== $index) {
                         // first error, don't worry about batch just throw it
                         // mark last error and index for batch results
                         $errors[] = $index;
                         $out[$index] = $ex->getMessage();
                     }
                     throw $ex;
                 }
                 // mark error and index for batch results
                 $errors[] = $index;
                 $out[$index] = $ex->getMessage();
             }
         }
         if (!empty($errors)) {
             throw new BadRequestException();
         }
         $result = $this->commitTransaction($extras);
         if (isset($result)) {
             $out = $result;
         }
         return $out;
     } catch (\Exception $ex) {
         $msg = $ex->getMessage();
         $context = null;
         if (!empty($errors)) {
             $wrapper = ResourcesWrapper::getWrapper();
             $context = ['error' => $errors, $wrapper => $out];
             $msg = 'Batch Error: Not all records could be retrieved.';
         }
         if ($ex instanceof RestException) {
             $temp = $ex->getContext();
             $context = empty($temp) ? $context : $temp;
             $ex->setContext($context);
             $ex->setMessage($msg);
             throw $ex;
         }
         throw new InternalServerErrorException("Failed to retrieve records from '{$table}'.\n{$msg}", null, null, $context);
     }
 }
Esempio n. 14
0
 /**
  * {@inheritdoc}
  */
 protected function commitTransaction($extras = null)
 {
     if (empty($this->batchRecords) && empty($this->batchIds)) {
         return null;
     }
     $fields = ArrayUtils::get($extras, ApiOptions::FIELDS);
     $requireMore = ArrayUtils::getBool($extras, 'require_more');
     $out = [];
     switch ($this->getAction()) {
         case Verbs::POST:
             $result = $this->parent->getConnection()->asArray()->storeDocs($this->batchRecords, true);
             if ($requireMore) {
                 $result = static::recordArrayMerge($this->batchRecords, $result);
             }
             $out = static::cleanRecords($result, $fields);
             break;
         case Verbs::PUT:
             $result = $this->parent->getConnection()->asArray()->storeDocs($this->batchRecords, true);
             if ($requireMore) {
                 $result = static::recordArrayMerge($this->batchRecords, $result);
             }
             $out = static::cleanRecords($result, $fields);
             break;
         case Verbs::MERGE:
         case Verbs::PATCH:
             $result = $this->parent->getConnection()->asArray()->storeDocs($this->batchRecords, true);
             if ($requireMore) {
                 $result = static::recordArrayMerge($this->batchRecords, $result);
             }
             $out = static::cleanRecords($result, $fields);
             break;
         case Verbs::DELETE:
             $out = [];
             if ($requireMore) {
                 $result = $this->parent->getConnection()->setQueryParameters($extras)->asArray()->include_docs(true)->keys($this->batchIds)->getAllDocs();
                 $rows = ArrayUtils::get($result, 'rows');
                 $out = static::cleanRecords($rows, $fields, static::DEFAULT_ID_FIELD, true);
             }
             $result = $this->parent->getConnection()->asArray()->deleteDocs($this->batchRecords, true);
             if (empty($out)) {
                 $out = static::cleanRecords($result, $fields);
             }
             break;
         case Verbs::GET:
             $result = $this->parent->getConnection()->setQueryParameters($extras)->asArray()->include_docs($requireMore)->keys($this->batchIds)->getAllDocs();
             $rows = ArrayUtils::get($result, 'rows');
             $out = static::cleanRecords($rows, $fields, static::DEFAULT_ID_FIELD, true);
             if (count($this->batchIds) !== count($out)) {
                 throw new BadRequestException('Batch Error: Not all requested ids were found to retrieve.');
             }
             break;
         default:
             break;
     }
     $this->batchIds = [];
     $this->batchRecords = [];
     return $out;
 }
Esempio n. 15
0
 /**
  * @param       $records
  * @param array $params
  * @param bool  $singlePayload
  *
  * @return array|mixed
  * @throws BadRequestException
  * @throws \Exception
  */
 public static function bulkDelete($records, $params = [], $singlePayload = false)
 {
     if (empty($records)) {
         throw new BadRequestException('There is no record in the request.');
     }
     $response = [];
     $transaction = null;
     $errors = [];
     $singleRow = 1 === count($records) ? true : false;
     $rollback = ArrayUtils::getBool($params, ApiOptions::ROLLBACK);
     $continue = ArrayUtils::getBool($params, ApiOptions::CONTINUES);
     try {
         //	Start a transaction
         if (!$singleRow && $rollback) {
             DB::beginTransaction();
             $transaction = true;
         }
         foreach ($records as $key => $record) {
             try {
                 $m = new static();
                 $pk = $m->getPrimaryKey();
                 $id = ArrayUtils::get($record, $pk);
                 $response[$key] = static::deleteInternal($id, $record, $params);
             } catch (\Exception $ex) {
                 if ($singleRow) {
                     throw $ex;
                 }
                 if ($rollback && $transaction) {
                     DB::rollBack();
                     throw $ex;
                 }
                 // track the index of the error and copy error to results
                 $errors[] = $key;
                 $response[$key] = $ex->getMessage();
                 if (!$continue) {
                     break;
                 }
             }
         }
     } catch (\Exception $ex) {
         throw $ex;
     }
     if (!empty($errors)) {
         $msg = ['errors' => $errors, ResourcesWrapper::getWrapper() => $response];
         throw new BadRequestException("Batch Error: Not all parts of the request were successful.", null, null, $msg);
     }
     //	Commit
     if ($transaction) {
         try {
             DB::commit();
         } catch (\Exception $ex) {
             throw $ex;
         }
     }
     return $singlePayload ? current($response) : $response;
 }
Esempio n. 16
0
 /**
  * @param array  $headers
  * @param string $action
  * @param array  $options
  *
  * @return void
  */
 protected static function addHeaders($headers, $action, &$options)
 {
     if (null === ArrayUtils::get($options, CURLOPT_HTTPHEADER)) {
         $options[CURLOPT_HTTPHEADER] = [];
     }
     // DSP outbound headers, additional and pass through
     if (!empty($headers)) {
         foreach ($headers as $header) {
             if (static::doesActionApply($header, $action)) {
                 $name = ArrayUtils::get($header, 'name');
                 $value = ArrayUtils::get($header, 'value');
                 if (ArrayUtils::getBool($header, 'pass_from_client')) {
                     // Check for Basic Auth pulled into server variable already
                     if (0 === strcasecmp($name, 'Authorization') && (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW']))) {
                         $value = 'Basic ' . base64_encode($_SERVER['PHP_AUTH_USER'] . ':' . $_SERVER['PHP_AUTH_PW']);
                     } else {
                         $phpHeaderName = strtoupper(str_replace(['-', ' '], ['_', '_'], $name));
                         // check for non-standard headers (prefix HTTP_) and standard headers like Content-Type
                         $value = isset($_SERVER['HTTP_' . $phpHeaderName]) ? $_SERVER['HTTP_' . $phpHeaderName] : isset($_SERVER[$phpHeaderName]) ? $_SERVER[$phpHeaderName] : $value;
                     }
                 }
                 Session::replaceLookups($value, true);
                 $options[CURLOPT_HTTPHEADER][] = $name . ': ' . $value;
             }
         }
     }
 }
Esempio n. 17
0
 /**
  * {@inheritdoc}
  */
 public static function deleteInternal($id, $record, $params = [])
 {
     if (empty($record)) {
         throw new BadRequestException('There are no fields in the record to create . ');
     }
     if (empty($id)) {
         //Todo:perform logging below
         //Log::error( 'Update request with no id supplied: ' . print_r( $record, true ) );
         throw new BadRequestException('Identifying field "id" can not be empty for update request . ');
     }
     /** @type User $model */
     $model = static::find($id);
     if (!$model instanceof Model) {
         throw new NotFoundException('No resource found for ' . $id);
     }
     try {
         if ($model->is_sys_admin && !ArrayUtils::getBool($params, 'admin')) {
             throw new ForbiddenException('Not allowed to delete an admin user.');
         } elseif (ArrayUtils::getBool($params, 'admin') && !$model->is_sys_admin) {
             throw new BadRequestException('Cannot delete a non-admin user.');
         } elseif (Session::getCurrentUserId() === $model->id) {
             throw new ForbiddenException('Cannot delete your account.');
         }
         $result = static::buildResult($model, $params);
         $model->delete();
         return $result;
     } catch (\Exception $ex) {
         if (!$ex instanceof ForbiddenException && !$ex instanceof BadRequestException) {
             throw new InternalServerErrorException('Failed to delete resource: ' . $ex->getMessage());
         } else {
             throw $ex;
         }
     }
 }
Esempio n. 18
0
 protected static function checkForIds(&$record, $ids_info, $extras = null, $on_create = false, $remove = false)
 {
     $id = null;
     if (!empty($ids_info)) {
         if (1 == count($ids_info)) {
             $info = $ids_info[0];
             $name = ArrayUtils::get($info, 'name');
             if (is_array($record)) {
                 $value = ArrayUtils::get($record, $name);
                 if ($remove) {
                     unset($record[$name]);
                 }
             } elseif (static::ROW_KEY == $name) {
                 $value = $record;
             }
             if (!empty($value)) {
                 $type = ArrayUtils::get($info, 'type');
                 switch ($type) {
                     case 'int':
                         $value = intval($value);
                         break;
                     case 'string':
                         $value = strval($value);
                         break;
                 }
                 $id = $value;
             } else {
                 $required = ArrayUtils::getBool($info, 'required');
                 // could be passed in as a parameter affecting all records
                 $param = ArrayUtils::get($extras, $name);
                 if ($on_create && $required && empty($param)) {
                     return false;
                 }
             }
         } else {
             $id = [];
             foreach ($ids_info as $info) {
                 $name = ArrayUtils::get($info, 'name');
                 if (is_array($record)) {
                     $value = ArrayUtils::get($record, $name);
                     if ($remove) {
                         unset($record[$name]);
                     }
                 } elseif (static::ROW_KEY == $name) {
                     $value = $record;
                 }
                 if (!empty($value)) {
                     $type = ArrayUtils::get($info, 'type');
                     switch ($type) {
                         case 'int':
                             $value = intval($value);
                             break;
                         case 'string':
                             $value = strval($value);
                             break;
                     }
                     $id[$name] = $value;
                 } else {
                     $required = ArrayUtils::getBool($info, 'required');
                     // could be passed in as a parameter affecting all records
                     $param = ArrayUtils::get($extras, $name);
                     if ($on_create && $required && empty($param)) {
                         if (!is_array($record) && static::ROW_KEY == $name) {
                             $id[$name] = $record;
                         } else {
                             return false;
                         }
                     }
                 }
             }
         }
     }
     if (!empty($id)) {
         return $id;
     } elseif ($on_create) {
         return [];
     }
     return false;
 }
Esempio n. 19
0
 /**
  * @param array $info
  *
  * @param bool  $recursive
  *
  * @return array
  */
 protected static function cleanPhpInfo($info, $recursive = false)
 {
     static $excludeKeys = ['directive', 'variable'];
     $clean = [];
     //  Remove images and move nested args to root
     if (!$recursive && isset($info[0], $info[0][0]) && is_array($info[0])) {
         $info['general'] = [];
         foreach ($info[0] as $key => $value) {
             if (is_numeric($key) || in_array(strtolower($key), $excludeKeys)) {
                 continue;
             }
             $info['general'][$key] = $value;
             unset($info[0][$key]);
         }
         unset($info[0]);
     }
     foreach ($info as $key => $value) {
         if (in_array(strtolower($key), $excludeKeys)) {
             continue;
         }
         $key = strtolower(str_replace(' ', '_', $key));
         if (is_array($value) && 2 == count($value) && isset($value[0], $value[1])) {
             $v1 = ArrayUtils::get($value, 0);
             if ($v1 == '<i>no value</i>') {
                 $v1 = null;
             }
             if (Scalar::in(strtolower($v1), 'on', 'off', '0', '1')) {
                 $v1 = ArrayUtils::getBool($value, 0);
             }
             $value = $v1;
         }
         if (is_array($value)) {
             $value = static::cleanPhpInfo($value, true);
         }
         $clean[$key] = $value;
     }
     return $clean;
 }
Esempio n. 20
0
 /**
  * Returns the validated URL that has been called to get here
  *
  * @param bool $includeQuery If true, query string is included
  * @param bool $includePath  If true, the uri path is included
  *
  * @return string
  */
 public static function currentUrl($includeQuery = true, $includePath = true)
 {
     //	Are we SSL? Check for load balancer protocol as well...
     $_port = intval(ArrayUtils::get($_SERVER, 'HTTP_X_FORWARDED_PORT', ArrayUtils::get($_SERVER, 'SERVER_PORT', 80)));
     $_protocol = ArrayUtils::get($_SERVER, 'HTTP_X_FORWARDED_PROTO', 'http' . (ArrayUtils::getBool($_SERVER, 'HTTPS') ? 's' : null)) . '://';
     $_host = ArrayUtils::get($_SERVER, 'HTTP_X_FORWARDED_HOST', ArrayUtils::get($_SERVER, 'HTTP_HOST', gethostname()));
     $_parts = parse_url($_protocol . $_host . ArrayUtils::get($_SERVER, 'REQUEST_URI'));
     if ((empty($_port) || !is_numeric($_port)) && null !== ($_parsePort = ArrayUtils::get($_parts, 'port'))) {
         $_port = @intval($_parsePort);
     }
     if (null !== ($_query = ArrayUtils::get($_parts, 'query'))) {
         $_query = static::urlSeparator($_query) . http_build_query(explode('&', $_query));
     }
     if (false !== strpos($_host, ':') || $_protocol == 'https://' && $_port == 443 || $_protocol == 'http://' && $_port == 80) {
         $_port = null;
     } else {
         $_port = ':' . $_port;
     }
     if (false !== strpos($_host, ':')) {
         $_port = null;
     }
     $_currentUrl = $_protocol . $_host . $_port . (true === $includePath ? ArrayUtils::get($_parts, 'path') : null) . (true === $includeQuery ? $_query : null);
     return $_currentUrl;
 }