Skip to content

Commit

Permalink
Merge pull request #25 from CoopBelvedere/dev_1.1.2
Browse files Browse the repository at this point in the history
Dev 1.1.2
  • Loading branch information
pascalboucher authored Oct 9, 2019
2 parents 93c086c + ee6f48c commit 756b7c9
Show file tree
Hide file tree
Showing 16 changed files with 146 additions and 71 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![Latest Version on Packagist](https://img.shields.io/badge/packagist-v1.1.1-blue)](https://packagist.org/packages/coopbelvedere/laravel-form-maker)
[![Latest Version on Packagist](https://img.shields.io/badge/packagist-v1.1.2-blue)](https://packagist.org/packages/coopbelvedere/laravel-form-maker)
[![Build Status](https://travis-ci.org/CoopBelvedere/laravel-form-maker.svg?branch=master)](https://travis-ci.org/CoopBelvedere/laravel-form-maker)
[![StyleCI](https://github.styleci.io/repos/156127313/shield?branch=master)](https://github.styleci.io/repos/156127313)

Expand Down
1 change: 1 addition & 0 deletions database/migrations/create_form_maker_tables.php.stub
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class CreateFormMakerTables extends Migration
$table->json('html_attributes')->nullable();
$table->json('rules')->nullable();
$table->timestamps();
$table->index(['nodable_id', 'type']);
});

Schema::create(config('form-maker.database.rankings_table', 'rankings'), function (Blueprint $table) {
Expand Down
9 changes: 5 additions & 4 deletions src/Contracts/Models/Rankings/RankerContract.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Belvedere\FormMaker\Contracts\Models\Rankings;

use Illuminate\Support\Enumerable;
use Illuminate\Database\Eloquent\Relations\MorphOne;

interface RankerContract
Expand Down Expand Up @@ -116,12 +117,12 @@ public function reverse(): void;
public function shuffle(): void;

/**
* Order the list according to the items position in the ranking.
* Order the list according to the nodes position in the ranking.
*
* @param \Illuminate\Support\LazyCollection|\Illuminate\Support\Collection $nodes
* @return mixed
* @param \Illuminate\Support\Enumerable $nodes
* @return \Illuminate\Support\Enumerable
*/
public function sortByRank($nodes);
public function sortByRank(Enumerable $nodes): Enumerable;

/**
* Toggle two nodes in the ranking.
Expand Down
6 changes: 3 additions & 3 deletions src/Contracts/Repositories/NodeRepositoryContract.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

namespace Belvedere\FormMaker\Contracts\Repositories;

use Illuminate\Support\Collection;
use Belvedere\FormMaker\Models\Model;
use Illuminate\Support\LazyCollection;
use Belvedere\FormMaker\Models\Nodes\Node;

interface NodeRepositoryContract
Expand All @@ -13,9 +13,9 @@ interface NodeRepositoryContract
*
* @param \Belvedere\FormMaker\Models\Model $parent
* @param string|null $type
* @return \Illuminate\Support\LazyCollection
* @return \Illuminate\Support\Collection
*/
public function all(Model $parent, ?string $type = null): LazyCollection;
public function all(Model $parent, ?string $type = null): Collection;

/**
* Delete all nodes of the parent model.
Expand Down
6 changes: 3 additions & 3 deletions src/Contracts/Traits/Nodes/HasNodesContract.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Belvedere\FormMaker\Contracts\Traits\Nodes;

use Illuminate\Support\LazyCollection;
use Illuminate\Support\Collection;
use Belvedere\FormMaker\Models\Nodes\Node;
use Belvedere\FormMaker\Contracts\Traits\Rankings\HasRankingsContract;

Expand Down Expand Up @@ -59,7 +59,7 @@ public function node($key): ?Node;
* Get the nodes filtered by type or not and sorted by their position in the ranking.
*
* @param string|null $type
* @return \Illuminate\Support\LazyCollection
* @return \Illuminate\Support\Collection
*/
public function nodes(?string $type = null): LazyCollection;
public function nodes(?string $type = null): Collection;
}
6 changes: 3 additions & 3 deletions src/Contracts/Traits/Nodes/HasOptionsContract.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Belvedere\FormMaker\Contracts\Traits\Nodes;

use Illuminate\Support\LazyCollection;
use Illuminate\Support\Collection;
use Belvedere\FormMaker\Contracts\Traits\Rankings\HasRankingsContract;
use Belvedere\FormMaker\Contracts\Models\Nodes\Inputs\Option\OptionerContract;

Expand Down Expand Up @@ -34,7 +34,7 @@ public function option($key): ?OptionerContract;
/**
* Get the options sorted by their position in the ranking.
*
* @return \Illuminate\Support\LazyCollection
* @return \Illuminate\Support\Collection
*/
public function options(): LazyCollection;
public function options(): Collection;
}
2 changes: 1 addition & 1 deletion src/Http/Resources/Form/FormResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class FormResource extends JsonResource
*/
public function toArray($request): array
{
$nodes = new NodeCollection($this->nodes()->collect());
$nodes = new NodeCollection($this->nodes());

return [
'id' => $this->getKey(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class DatalistResourcer extends JsonResource implements DatalistResourcerContrac
public function toArray($request): array
{
$inputId = uniqid('list_');
$options = new NodeCollection($this->options()->collect());
$options = new NodeCollection($this->options());
$label = $this->getLabelResource($inputId);

return [
Expand Down
2 changes: 1 addition & 1 deletion src/Http/Resources/Nodes/Inputs/InputResourcer.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class InputResourcer extends JsonResource implements InputResourcerContract
public function toArray($request): array
{
if ($options = method_exists($this->resource, 'options')) {
$options = new NodeCollection($this->options()->collect());
$options = new NodeCollection($this->options());
}

$label = $this->getLabelResource();
Expand Down
7 changes: 4 additions & 3 deletions src/Models/Rankings/Ranker.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Belvedere\FormMaker\Models\Rankings;

use Illuminate\Support\Enumerable;
use Illuminate\Database\Eloquent\Model as Eloquent;
use Illuminate\Database\Eloquent\Relations\MorphOne;
use Belvedere\FormMaker\Contracts\Models\Rankings\RankerContract;
Expand Down Expand Up @@ -357,10 +358,10 @@ public function shuffle(): void
/**
* Order the list according to the nodes position in the ranking.
*
* @param \Illuminate\Support\LazyCollection|\Illuminate\Support\Collection $nodes
* @return mixed
* @param \Illuminate\Support\Enumerable $nodes
* @return \Illuminate\Support\Enumerable
*/
public function sortByRank($nodes)
public function sortByRank(Enumerable $nodes): Enumerable
{
return $nodes->sortBy(function ($node, $key) {
return $this->rank($node);
Expand Down
141 changes: 112 additions & 29 deletions src/Repositories/NodeRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Belvedere\FormMaker\Models\Model;
use Illuminate\Support\LazyCollection;
use Illuminate\Database\Query\Builder;
use Belvedere\FormMaker\Models\Nodes\Node;
use Belvedere\FormMaker\Contracts\Repositories\NodeRepositoryContract;
use Belvedere\FormMaker\Contracts\Models\Nodes\Siblings\Label\LabelerContract;

class NodeRepository implements NodeRepositoryContract
{
Expand Down Expand Up @@ -49,24 +50,46 @@ class NodeRepository implements NodeRepositoryContract
*
* @param \Belvedere\FormMaker\Models\Model $parent
* @param string|null $type
* @return \Illuminate\Support\LazyCollection
* @return \Illuminate\Support\Collection
*/
public function all(Model $parent, ?string $type = null): LazyCollection
public function all(Model $parent, ?string $type = null): Collection
{
$query = DB::table(config('form-maker.database.form_nodes_table', 'form_nodes'))
->where('nodable_type', $parent->getMorphClass())
->where('nodable_id', $parent->getKey())
->orderBy('type');
$table = config('form-maker.database.form_nodes_table', 'form_nodes');

$query = $this->getSelectQuery($table, $parent);

if ($type === 'inputs' || $type === 'siblings') {
$query->whereIn('type', array_keys(config('form-maker.nodes')[$type]));
$query->whereIn(sprintf('%s.type', $table), array_keys(config('form-maker.nodes')[$type]));
} elseif ($type) {
$query->where('type', $type);
$query->where(sprintf('%s.type', $table), $type);
}

return $query->cursor()->groupBy('type')->map(function ($nodes, $key) {
return $this->hydrate($nodes->toArray());
})->flatten(1);
return $query->get()->map(function ($node, $key) {
return $this->buildNodeModel($node);
});
}

/**
* Build a node model with label eager loaded.
*
* @param object|null $node
* @return Node|null
*/
protected function buildNodeModel(?object $node): ?Node
{
if (is_null($node)) {
return null;
}

$label = $this->hydrateLabel($node);
$this->removeAttributes('label', $node);
$node = $this->hydrate($node);

if ($label) {
$node->setRelation('label', $label);
}

return $node;
}

/**
Expand All @@ -78,6 +101,7 @@ public function all(Model $parent, ?string $type = null): LazyCollection
public function delete(Model $parent)
{
return DB::table(config('form-maker.database.form_nodes_table', 'form_nodes'))
->whereNotNull('nodable_id')
->where('nodable_type', $parent->getMorphClass())
->where('nodable_id', $parent->getKey())
->delete();
Expand All @@ -93,25 +117,23 @@ public function delete(Model $parent)
*/
public function find(Model $parent, $nodeKey, array $columns): ?Node
{
$query = DB::table(config('form-maker.database.form_nodes_table', 'form_nodes'))
->where('nodable_type', $parent->getMorphClass())
->where('nodable_id', $parent->getKey());
$table = config('form-maker.database.form_nodes_table', 'form_nodes');

$query = $this->getSelectQuery($table, $parent);

if (count($columns) > 0) {
$query->where(function ($query) use ($columns, $nodeKey) {
$query->where(function ($query) use ($table, $columns, $nodeKey) {
foreach ($columns as $key => $column) {
if ($key === 0) {
$query->where(sprintf('html_attributes->%s', $column), $nodeKey);
$query->where(sprintf('%s.html_attributes->%s', $table, $column), $nodeKey);
} else {
$query->orWhere(sprintf('html_attributes->%s', $column), $nodeKey);
$query->orWhere(sprintf('%s.html_attributes->%s', $table, $column), $nodeKey);
}
}
});
}

$node = $query->first();

return (is_null($node)) ? $node : $this->hydrate([$node])[0];
return $this->buildNodeModel($query->first());
}

/**
Expand All @@ -134,20 +156,81 @@ public function getInstanceOf(Model $parent, string $type): Node
}

/**
* Create a collection of nodes from plain arrays.
* Get the query builder for select statements.
*
* @param array $nodes
* @return \Illuminate\Support\Collection
* @param string $table
* @param Model $parent
* @return \Illuminate\Database\Query\Builder
*/
protected function getSelectQuery(string $table, Model $parent): Builder
{
return DB::table($table)
->select(DB::raw(sprintf('%s.*, label.id as label_id, label.nodable_type as label_nodable_type, label.nodable_id as label_nodable_id, label.text as label_text, label.html_attributes as label_html_attributes, label.rules as label_rules, label.created_at as label_created_at, label.updated_at as label_updated_at', $table)))
->leftJoin(DB::raw(sprintf('%s as label', $table)), function ($join) use ($table) {
$join->on(sprintf('%s.id', $table), '=', 'label.nodable_id')
->where('label.type', '=', 'label');
})
->whereNotNull(sprintf('%s.nodable_id', $table))
->where(sprintf('%s.nodable_type', $table), $parent->getMorphClass())
->where(sprintf('%s.nodable_id', $table), $parent->getKey());
}

/**
* Hydrate the label columns in the node object to a Label model.
*
* @param object $node
* @return LabelerContract|null
*/
protected function hydrate(array $nodes): Collection
protected function hydrateLabel(object $node): ?LabelerContract
{
if (count($nodes) === 0 || is_null($nodes[0]->type)) {
return collect([]);
if ($node->label_id) {
return $this->hydrate((object) [
'id' => $node->label_id,
'nodable_type' => $node->label_nodable_type,
'nodable_id' => $node->label_nodable_id,
'type' => 'label',
'text' => $node->label_text,
'html_attributes' => $node->label_html_attributes,
'rules' => $node->label_rules,
'created_at' => $node->label_created_at,
'updated_at' => $node->label_updated_at,
]);
}

$type = $nodes[0]->type;
return null;
}

return $this->resolve($type)::hydrate($nodes);
/**
* Create a laravel model from stdClass object.
*
* @param object $node
* @return \Belvedere\FormMaker\Models\Nodes\Node
*/
protected function hydrate(object $node): ?Node
{
if (is_null($node->type)) {
return null;
}

$type = $node->type;

return $this->resolve($type)::hydrate([$node])->shift();
}

/**
* Remove attributes that start with a given prefix.
*
* @param string $prefix
* @param object $node
* @return void
*/
protected function removeAttributes(string $prefix, object &$node): void
{
foreach ($node as $key => $value) {
if (substr($key, 0, strlen($prefix)) === $prefix) {
unset($node->$key);
}
}
}

/**
Expand Down
6 changes: 3 additions & 3 deletions src/Traits/HtmlAttributes/HasHtmlAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ trait HasHtmlAttributes
protected $htmlAttributesProvider;

/**
* Check if the attribute is valid for the model.
* Check if the attribute is available for the model.
*
* @param string $attribute
* @return bool
*/
protected function isValidAttribute(string $attribute): bool
protected function attributeIsAvailable(string $attribute): bool
{
return in_array($attribute, $this->htmlAttributesAvailable);
}
Expand All @@ -47,7 +47,7 @@ public function removeHtmlAttributes(array $attributes): HasHtmlAttributesContra
protected function updateHtmlAttributes(array $attributes): void
{
foreach ($attributes as $attribute => $value) {
if (is_null($value) || $this->isValidAttribute($attribute)) {
if (is_null($value) || $this->attributeIsAvailable($attribute)) {
$this->htmlAttributesProvider->$attribute = $value;
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/Traits/Nodes/HasNodes.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Belvedere\FormMaker\Traits\Nodes;

use Illuminate\Support\LazyCollection;
use Illuminate\Support\Collection;
use Belvedere\FormMaker\Models\Nodes\Node;
use Belvedere\FormMaker\Contracts\Repositories\NodeRepositoryContract;

Expand Down Expand Up @@ -104,9 +104,9 @@ public function node($key): ?Node
* Get the nodes filtered by type or not and sorted by their position in the ranking.
*
* @param string|null $type
* @return \Illuminate\Support\LazyCollection
* @return \Illuminate\Support\Collection
*/
public function nodes(?string $type = null): LazyCollection
public function nodes(?string $type = null): Collection
{
$nodeRepository = resolve(NodeRepositoryContract::class);

Expand Down
Loading

0 comments on commit 756b7c9

Please sign in to comment.