Created
September 14, 2017 17:06
-
-
Save bel1k0v/abc62a9ff1ca7b63ce67c9980b36b36a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace common\components\pgsql; | |
use yii\base\Behavior; | |
use yii\db\ActiveRecord; | |
class ArrayBehavior extends Behavior | |
{ | |
public $attributes; | |
/** | |
* @return array | |
*/ | |
public function events() | |
{ | |
return [ | |
ActiveRecord::EVENT_INIT => 'loadArrays', | |
ActiveRecord::EVENT_AFTER_FIND => 'loadArrays', | |
ActiveRecord::EVENT_AFTER_INSERT => 'loadArrays', | |
ActiveRecord::EVENT_AFTER_UPDATE => 'loadArrays', | |
ActiveRecord::EVENT_BEFORE_INSERT => 'saveArrays', | |
ActiveRecord::EVENT_BEFORE_UPDATE => 'saveArrays' | |
]; | |
} | |
/** | |
* void | |
*/ | |
public function saveArrays() | |
{ | |
/* @var $owner ActiveRecord */ | |
$owner = $this->owner; | |
$values = $owner->getAttributes($this->attributes); | |
foreach ($values as $attr => $value) { | |
if (is_array($value)) { | |
$value = $this->arrayToPg($value); | |
} elseif (empty($value)) { | |
$value = '{}'; | |
} | |
$owner->setAttribute($attr, $value); | |
} | |
} | |
/** | |
* @throws \Exception | |
*/ | |
public function loadArrays() | |
{ | |
/* @var $owner ActiveRecord */ | |
$owner = $this->owner; | |
$values = $owner->getAttributes($this->attributes); | |
foreach ($values as $attr => $value) { | |
$value = $this->pgToArray($value); | |
$value = $value ?: []; | |
$owner->setAttribute($attr, $value); | |
} | |
} | |
/** | |
* Преобразует массив PostgreSQL в массив PHP | |
* @param string $array_string | |
* @param boolean $reset | |
* @throws \Exception | |
* @return array | |
*/ | |
protected function pgToArray($array_string, $reset = true) | |
{ | |
static $i = 0; | |
if ($reset) $i = 0; | |
$matches = array(); | |
$indexer = 1; // by default sql attributes start at 1 | |
// handle [0,2]= cases | |
if (preg_match('/^\[(?P<index_start>\d+):(?P<index_end>\d+)]=/', substr($array_string, $i), $matches)) { | |
$indexer = (int)$matches['index_start']; | |
$i = strpos($array_string, '{'); | |
} | |
if ($array_string[$i] != '{') { | |
return NULL; | |
} | |
if (is_array($array_string)) return $array_string; | |
// handles btyea and blob binary streams | |
if (is_resource($array_string)) return fread($array_string, 4096); | |
$i++; | |
$work = array(); | |
$curr = ''; | |
$length = strlen($array_string); | |
$quoted = false; | |
while ($i < $length) { | |
// echo "\n [ $i ] ..... $array_string[$i] .... $curr"; | |
switch ($array_string[$i]) { | |
case '{': | |
$sub = self::pgToArray($array_string, false); | |
if (!empty($sub)) { | |
$work[$indexer++] = $sub; | |
} | |
break; | |
case '}': | |
$i++; | |
if (!empty($curr)) { | |
$work[$indexer++] = $curr; | |
} | |
return $work; | |
break; | |
case '\\': | |
$i++; | |
$curr .= $array_string[$i]; | |
$i++; | |
break; | |
case '"': | |
$quoted = true; | |
$openq = $i; | |
do { | |
$closeq = strpos($array_string, '"', $i + 1); | |
if ($closeq > $openq && $array_string[$closeq - 1] == '\\') { | |
$i = $closeq; | |
} else { | |
break; | |
} | |
} while (true); | |
if ($closeq <= $openq) { | |
throw new \Exception('Unexpected condition'); | |
} | |
$curr .= substr($array_string, $openq + 1, $closeq - ($openq + 1)); | |
$i = $closeq + 1; | |
break; | |
case ',': | |
if (strlen($curr) > 0) { | |
if (!$quoted && (strtoupper($curr) == 'NULL')) { | |
$curr = null; | |
} | |
$work[$indexer++] = $curr; | |
} | |
$curr = ''; | |
$quoted = false; | |
$i++; | |
break; | |
default: | |
$curr .= $array_string[$i]; | |
$i++; | |
} | |
} | |
} | |
/** | |
* Преобразует массив PHP в массив PostgreSQL | |
* @param mixed $value | |
* @return string | |
*/ | |
protected function arrayToPg(array $value) | |
{ | |
$f = function (&$value) { | |
if (is_string($value) && !empty($value)) { | |
$value = "\"{$value}\""; | |
} | |
if (is_array($value)) { | |
$value = '{' . implode(',', $value) . '}'; | |
} | |
}; | |
array_walk_recursive($value, $f); | |
$f($value); | |
return $value; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment