Skip to content

Instantly share code, notes, and snippets.

@timkelty
Last active November 23, 2020 19:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timkelty/fe00ff49785802f3722bf3aaee5dd670 to your computer and use it in GitHub Desktop.
Save timkelty/fe00ff49785802f3722bf3aaee5dd670 to your computer and use it in GitHub Desktop.
Scout Transformers
<?php
namespace modules\appmodule\transformers;
use craft\base\ElementInterface;
use League\Fractal\TransformerAbstract;
use modules\appmodule\AppModule;
use Tightenco\Collect\Support\Collection;
class ElementTransformer extends TransformerAbstract
{
const DEFAULT_ATTRIBUTES = [
'id',
'title',
'slug',
'uri',
'dateCreated',
'dateUpdated',
];
public $transformer;
public function __construct()
{
$this->transformer = AppModule::getInstance()->transformer;
}
public function transform(ElementInterface $element): array
{
$values = Collection::make($element)->only(self::DEFAULT_ATTRIBUTES);
return $this->transformer->transformValues($values)->all();
}
}
<?php
namespace modules\appmodule\transformers;
use craft\base\ElementInterface;
use Tightenco\Collect\Support\Collection;
class ProductTransformer extends ElementTransformer
{
public function transform(ElementInterface $entry): array
{
$collection = Collection::make($entry)
->only([
'someField',
'someOtherField',
])
->merge(parent::transform($entry))
->put('myMenu', $this->transformer->structureToMenuHierarchy($entry->myCategoriesField));
return $this->transformer->transformValues($collection)->all();
}
}
<?php
namespace modules\appmodule\services;
use craft\base\Element;
use craft\elements\Asset;
use craft\elements\db\ElementQuery;
use craft\elements\User;
use craft\fields\data\MultiOptionsFieldData;
use craft\fields\data\OptionData;
use craft\models\EntryType;
use craft\models\Section;
use modules\appmodule\transformers\ElementTransformer;
use Tightenco\Collect\Support\Collection;
use yii\base\Component;
use yii\db\QueryInterface;
class Transformer extends Component
{
public function transformSingleOptionFieldData(OptionData $data): Collection
{
return Collection::make($data)->only('label', 'value');
}
public function transformMultiOptionsFieldData(MultiOptionsFieldData $data): Collection
{
return Collection::make($data->getOptions())
->filter(function ($item) {
return $item->selected;
})
->map(function ($item) {
return $this->transformSingleOptionFieldData($item);
})
->values();
}
public function structureToMenuHierarchy(ElementQuery $elementQuery): Collection
{
$elements = Collection::make($elementQuery->orderBy(['level' => SORT_ASC])->all())
->map(function ($element) {
$rootElement = $element->getAncestors()->one() ?? $element;
return Collection::make($element)
->only(['level', 'title', 'id'])
->put('rootId', $rootElement->id);
});
return $elements
->groupBy('level')
->keys()
->flatMap(function ($level) use ($elements) {
$crumbs = $elements
->where('level', '<=', $level)
->groupBy('rootId')
->values()
->map(function ($item) {
return $item->pluck('title')->join(' > ');
});
$key = implode('', ['lvl', $level -1]);
return [
$key => $crumbs,
];
});
}
public function transformValue($value)
{
if ($value instanceof \DateTime) {
return $value->getTimestamp();
} elseif ($value instanceof RedactorFieldData) {
return (string) $value;
} elseif ($value instanceof MultiOptionsFieldData) {
return $this->transformMultiOptionsFieldData($value);
} elseif ($value instanceof SingleOptionFieldData) {
return $this->transformSingleOptionFieldData($value);
} elseif ($value instanceof User) {
return Collection::make($value)
->only([
'id',
'username',
]);
} elseif ($value instanceof Asset) {
return Collection::make($value)
->only([
'id',
'url',
]);
} elseif ($value instanceof Element) {
return (new ElementTransformer)->transform($value);
} elseif ($value instanceof Section || $value instanceof EntryType) {
return Collection::make($value)
->only([
'name',
'handle',
]);
} elseif ($value instanceof QueryInterface) {
return $this->queryToCollection($value);
}
return $value;
}
public function queryToCollection(?QueryInterface $query): Collection
{
return Collection::make($query ? $query->all() : null);
}
public function transformValues($values): Collection
{
return Collection::make($this->transformValue($values))->map(function ($value) {
return (is_iterable($value)) ?
$this->transformValues($value) :
$this->transformValue($value);
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment