<?php<liu21st@gmail.com>declare (strict_types = 1);
namespace think\db\concern;
use Closure;
use think\Collection;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\db\Query;
use think\helper\Str;
use think\Model;
trait ResultOperation
{
public function allowEmpty(bool $allowEmpty = true)
{
$this->options['allow_empty'] = $allowEmpty;
return $this;
}
public function failException(bool $fail = true)
{
$this->options['fail'] = $fail;
return $this;
}
protected function result(array &$result): void
{
if (!empty($this->options['json'])) {
$this->jsonResult($result, $this->options['json'], true);
}
if (!empty($this->options['with_attr'])) {
$this->getResultAttr($result, $this->options['with_attr']);
}
$this->filterResult($result);
}
protected function resultSet(array &$resultSet): void
{
if (!empty($this->options['json'])) {
foreach ($resultSet as &$result) {
$this->jsonResult($result, $this->options['json'], true);
}
}
if (!empty($this->options['with_attr'])) {
foreach ($resultSet as &$result) {
$this->getResultAttr($result, $this->options['with_attr']);
}
}
if (!empty($this->options['visible']) || !empty($this->options['hidden'])) {
foreach ($resultSet as &$result) {
$this->filterResult($result);
}
}
$resultSet = new Collection($resultSet);
}
protected function filterResult(&$result): void
{
$array = [];
if (!empty($this->options['visible'])) {
foreach ($this->options['visible'] as $key) {
$array[] = $key;
}
$result = array_intersect_key($result, array_flip($array));
} elseif (!empty($this->options['hidden'])) {
foreach ($this->options['hidden'] as $key) {
$array[] = $key;
}
$result = array_diff_key($result, array_flip($array));
}
}
protected function getResultAttr(array &$result, array $withAttr = []): void
{
foreach ($withAttr as $name => $closure) {
$name = Str::snake($name);
if (strpos($name, '.')) {
[$key, $field] = explode('.', $name);
if (isset($result[$key])) {
$result[$key][$field] = $closure($result[$key][$field] ?? null, $result[$key]);
}
} else {
$result[$name] = $closure($result[$name] ?? null, $result);
}
}
}
protected function resultToEmpty()
{
if (!empty($this->options['fail'])) {
$this->throwNotFound();
} elseif (!empty($this->options['allow_empty'])) {
return !empty($this->model) ? $this->model->newInstance() : [];
}
}
public function findOrEmpty($data = null)
{
return $this->allowEmpty(true)->find($data);
}
protected function jsonResult(array &$result, array $json = [], bool $assoc = false, array $withRelationAttr = []): void
{
foreach ($json as $name) {
if (!isset($result[$name])) {
continue;
}
$result[$name] = json_decode($result[$name], true);
if (isset($withRelationAttr[$name])) {
foreach ($withRelationAttr[$name] as $key => $closure) {
$result[$name][$key] = $closure($result[$name][$key] ?? null, $result[$name]);
}
}
if (!$assoc) {
$result[$name] = (object) $result[$name];
}
}
}
protected function throwNotFound(): void
{
if (!empty($this->model)) {
$class = get_class($this->model);
throw new ModelNotFoundException('model data Not Found:' . $class, $class, $this->options);
}
$table = $this->getTable();
throw new DataNotFoundException('table data not Found:' . $table, $table, $this->options);
}
public function selectOrFail($data = null)
{
return $this->failException(true)->select($data);
}
public function findOrFail($data = null)
{
return $this->failException(true)->find($data);
}
}