This commit is contained in:
evgen-d 2014-06-16 09:49:22 +04:00
parent f020707f5c
commit 44e77d8a18
6 changed files with 413 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
# phpstorm project files
.idea

80
ActionColumn.php Normal file
View File

@ -0,0 +1,80 @@
<?php
namespace bethrezen\arangodb;
use Yii;
use Closure;
use yii\helpers\Html;
use yii\helpers\Url;
use kartik\icons\Icon;
class ActionColumn extends \yii\grid\Column
{
public $buttons = [
[
'url' => 'edit',
'icon' => 'pencil',
'class' => 'btn-primary',
'label' => 'Edit',
],
[
'url' => 'delete',
'icon' => 'trash-o',
'class' => 'btn-danger',
'label' => 'Delete',
],
];
/**
* @var string the ID of the controller that should handle the actions specified here.
* If not set, it will use the currently active controller. This property is mainly used by
* [[urlCreator]] to create URLs for different actions. The value of this property will be prefixed
* to each action name to form the route of the action.
*/
public $controller;
/**
* @var callable a callback that creates a button URL using the specified model information.
* The signature of the callback should be the same as that of [[createUrl()]].
* If this property is not set, button URLs will be created using [[createUrl()]].
*/
public $urlCreator;
/**
* Creates a URL for the given action and model.
* This method is called for each button and each row.
* @param string $action the button name (or action ID)
* @param \yii\db\ActiveRecord $model the data model
* @param mixed $key the key associated with the data model
* @param integer $index the current row index
* @return string the created URL
*/
public function createUrl($action, $model, $key, $index)
{
if ($this->urlCreator instanceof Closure) {
return call_user_func($this->urlCreator, $action, $model, $key, $index);
} else {
$params = is_array($key) ? $key : ['id' => (string) $key];
$params[0] = $this->controller ? $this->controller . '/' . $action : $action;
return Url::toRoute($params);
}
}
protected function renderDataCellContent($model, $key, $index)
{
$data = '';
foreach ($this->buttons as $button) {
$data .= Html::a(
Icon::show($button['icon']).'&nbsp;&nbsp;'.$button['label'],
$url = $this->createUrl($button['url'], $model, $key, $index),
[
'data-pjax' => 0,
'class' => 'btn btn-xs '.$button['class']
]
) . ' ';
}
return $data;
}
}

76
ArangoDbConnection.php Normal file
View File

@ -0,0 +1,76 @@
<?php
namespace bethrezen\arangodb;
use yii\helpers\ArrayHelper;
use yii\base\Object;
// set up some aliases for less typing later
use triagens\ArangoDb\Connection as ArangoConnection;
use triagens\ArangoDb\ConnectionOptions as ArangoConnectionOptions;
use triagens\ArangoDb\DocumentHandler as ArangoDocumentHandler;
use triagens\ArangoDb\Document as ArangoDocument;
use triagens\ArangoDb\Exception as ArangoException;
use triagens\ArangoDb\ConnectException as ArangoConnectException;
use triagens\ArangoDb\ClientException as ArangoClientException;
use triagens\ArangoDb\ServerException as ArangoServerException;
use triagens\ArangoDb\UpdatePolicy as ArangoUpdatePolicy;
use triagens\ArangoDb\Statement as Statement;
class ArangoDbConnection extends Object {
private $_connection = null;
public $connectionOptions = [
// server endpoint to connect to
ArangoConnectionOptions::OPTION_ENDPOINT => 'tcp://127.0.0.1:8529',
// authorization type to use (currently supported: 'Basic')
ArangoConnectionOptions::OPTION_AUTH_TYPE => 'Basic',
// user for basic authorization
ArangoConnectionOptions::OPTION_AUTH_USER => 'root',
// password for basic authorization
ArangoConnectionOptions::OPTION_AUTH_PASSWD => '',
// connection persistence on server. can use either 'Close' (one-time connections) or 'Keep-Alive' (re-used connections)
ArangoConnectionOptions::OPTION_CONNECTION => 'Close',
// connect timeout in seconds
ArangoConnectionOptions::OPTION_TIMEOUT => 3,
// whether or not to reconnect when a keep-alive connection has timed out on server
ArangoConnectionOptions::OPTION_RECONNECT => true,
// optionally create new collections when inserting documents
ArangoConnectionOptions::OPTION_CREATE => true,
// optionally create new collections when inserting documents
ArangoConnectionOptions::OPTION_UPDATE_POLICY => ArangoUpdatePolicy::LAST,
];
private $_collectionHandler = null;
private $_documentHandler = null;
public function __construct($config=[])
{
parent::__construct($config);
}
public function init()
{
parent::init();
$this->_connection = new ArangoConnection($this->connectionOptions);
$this->_collectionHandler = new \triagens\ArangoDb\CollectionHandler($this->_connection);
$this->_documentHandler = new \triagens\ArangoDb\DocumentHandler($this->_connection);
}
public function getDocument($collection, $id) {
return $this->documentHandler()->get($collection, $id);
}
public function documentHandler() {
return $this->_documentHandler;
}
public function statement($options=[]) {
return new Statement($this->_connection, $options);
}
public function collectionHandler() {
return $this->_collectionHandler;
}
}

100
ArangoModel.php Normal file
View File

@ -0,0 +1,100 @@
<?php
namespace bethrezen\arangodb;
use yii;
use triagens\ArangoDb\Document;
class ArangoModel extends \yii\base\model {
private $_isNewRecord = true;
private $_doc = null;
public static function findById($id)
{
$parts = explode("\\", $id);
if (count($parts)==2) {
$id = $parts[1]; // для формата "Collection\1237643123"
} else {
$parts = explode("/", $id); // для формата "Collection/123123321"
if (count($parts)==2) {
$id = $parts[1];
}
}
$model = new static;
$model
->setDocument(Yii::$app->arango->getDocument(static::class_to_collection(get_called_class()), $id))
->setIsNewRecord(false);
return $model;
}
/**
* @todo функция должна возвращать true/false в зависимости от результата
* Но аранга возвращает различный тип данных. Надо написать код
*
*/
public function save()
{
if ($this->_isNewRecord) {
// добавляем запись
$this->_doc = Document::createFromArray($this->getAttributes());
return intval(Yii::$app->arango->documentHandler()->add(static::class_to_collection(get_called_class()), $this->_doc)) > 0;
} else {
// патчим!
$doc_attributes = array_keys($this->_doc->getAll());
$attributes = $this->getAttributes();
foreach ($attributes as $k=>$v) {
$this->_doc->set($k, $v);
unset($doc_attributes[$k]);
}
foreach ($doc_attributes as $key) {
if ($key != '_key')
unset($this->_doc->$key);
}
return Yii::$app->arango->documentHandler()->update($this->_doc);
}
}
private static function class_to_collection($class)
{
$parts = explode("\\", $class);
return end($parts);
}
private static function id_to_int($class)
{
$parts = explode("/", $class);
return end($parts);
}
public function setIsNewRecord($state)
{
$this->_isNewRecord = $state;
return $this;
}
public function setDocument($doc)
{
$this->_doc = $doc;
$all = $this->_doc->getAll();
$this->_id = $this->_doc->getInternalId();
$this->setAttributes($all, false);
return $this;
}
public function delete()
{
Yii::$app->arango->documentHandler()->deleteById(
static::class_to_collection(get_called_class()),
static::id_to_int($this->_doc->getInternalId())
);
}
}

133
ArangoProvider.php Normal file
View File

@ -0,0 +1,133 @@
<?php
namespace bethrezen\arangodb;
use yii;
use yii\di\Instance;
use triagens\ArangoDb\Document;
use app;
class ArangoProvider extends yii\data\ActiveDataProvider
{
public $arango = 'arango';
public $collection;
/**
* @var array parameters for example
*/
public $params = [];
public function init()
{
parent::init();
$this->arango = Instance::ensure($this->arango, app\components\ArangoDbConnection::className());
if ($this->collection === null) {
throw new InvalidConfigException('The "collection" property must be set.');
}
}
/**
* @inheritdoc
*/
protected function prepareKeys($models)
{
return array_keys($models);
}
/**
* @inheritdoc
*/
protected function prepareModels()
{
// $sql = $this->sql;
// $qb = $this->db->getQueryBuilder();
// if (($sort = $this->getSort()) !== false) {
// $orderBy = $qb->buildOrderBy($sort->getOrders());
// if (!empty($orderBy)) {
// $orderBy = substr($orderBy, 9);
// if (preg_match('/\s+order\s+by\s+[\w\s,\.]+$/i', $sql)) {
// $sql .= ', ' . $orderBy;
// } else {
// $sql .= ' ORDER BY ' . $orderBy;
// }
// }
// }
// if (($pagination = $this->getPagination()) !== false) {
// $pagination->totalCount = $this->getTotalCount();
// $sql .= ' ' . $qb->buildLimit($pagination->getLimit(), $pagination->getOffset());
// }
// return $this->db->createCommand($sql, $this->params)->queryAll();
$statement = $this->getBaseStatement();
if (($pagination = $this->getPagination()) !== false) {
$pagination->totalCount = $this->getTotalCount();
$statement->setQuery($statement->getQuery() . "\n LIMIT " . $pagination->getOffset() . ", " . $pagination->getLimit());
}
$statement->setQuery($statement->getQuery()."\n RETURN a");
$cursor = $statement->execute();
$data = $cursor->getAll();
$result = [];
foreach ($data as $doc) {
$item = $doc->getAll();
foreach ($item as $k=>$v) {
if (is_array($item[$k]) || is_object($item[$k])) {
$item[$k] = json_encode($v, true);
}
}
$result[$item['_key']] = $item;
}
$pagination->totalCount = $cursor->getFullCount();
return $result;
}
public function getTotalCount() {
$statement = $this->getBaseStatement();
$statement->setQuery($statement->getQuery(). "\n LIMIT 1 \n RETURN a");
$cursor = $statement->execute();
return $cursor->getFullCount();
}
private function getBaseStatement() {
$query = "FOR a in @@collection\n";
$filter = [];
$bindings = ['@collection' => $this->collection];
$counter = 0;
foreach ($this->params as $k => $v) {
$filter[] = " a.@filter_field_$counter == @filter_value_$counter ";
$bindings["filter_field_$counter"] = $k;
$bindings["filter_value_$counter"] = $v;
$counter++;
}
if (count($filter)>0){
$query .= "\nFILTER ".implode(" && ", $filter)."\n";
}
$statement = $this->arango->statement([
'query' => $query,
'count' => true,
'bindVars' => $bindings,
'fullCount' => true,
]);
return $statement;
}
/**
* @inheritdoc
*/
protected function prepareTotalCount()
{
return 0;
}
}

22
composer.json Normal file
View File

@ -0,0 +1,22 @@
{
"name": "bethrezen/yii2-arangodb",
"description": "Yii2 arangodb components",
"type": "yii2-extension",
"keywords": ["yii2","arangodb"],
"license": "GPL-3.0+",
"authors": [
{
"name": "Alexander Kozhevnikov",
"email": "b37hr3z3n@gmail.com"
}
],
"require": {
"yiisoft/yii2": "*",
"triagens/arangodb": "*"
},
"autoload": {
"psr-4": {
"bethrezen\\arangodb\\": ""
}
}
}