Skip to content

Commit

Permalink
Merge branch '1.x' into custom-user-provider
Browse files Browse the repository at this point in the history
  • Loading branch information
bryannielsen committed Mar 13, 2024
2 parents 1be5d71 + 5faebd6 commit dfaf590
Show file tree
Hide file tree
Showing 14 changed files with 228 additions and 60 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@

### Added

- Ability to pass a 'tagdata' parameter to the ExpressionEngine Template library
- Support for the Member fieldtype introduced in ExpressionEngine 7.4
- A custom user provider to enable the `coilpack` guard to be used for logging in ExpressionEngine members through Laravel's authentication manager.

### Fixed

- Bug retrieving dynamic Structure entry from Structure Entries tag
- GraphQL response error when site has no content populated
- Improve handling of LegacyTag to preserve a tag's string output when structured data exists
- Setting proper visibility when setting protected values through reflection

## [1.2.2] - 2023-12-05

Expand Down
2 changes: 2 additions & 0 deletions src/Api/Graph/Support/FieldtypeRegistrar.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ class FieldtypeRegistrar

protected $booted = false;

protected $fieldtypeManager;

public function __construct(FieldtypeManager $manager)
{
$this->fieldtypeManager = $manager;
Expand Down
7 changes: 7 additions & 0 deletions src/Coilpack.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ public function isolateTemplateLibrary(callable $callable, $parameters = null)
$template = new View\TemplateStub;
ee()->set('TMPL', $template);

// Allow setting the EE Template Library's tagdata with a parameter
if ($parameters['tagdata'] ?? false) {
ee()->TMPL->tagdata = $parameters['tagdata'];
unset($parameters['tagdata']);
}

// Assign parameters to the template library
if ($parameters) {
$template->tagparams = $parameters;
}
Expand Down
37 changes: 37 additions & 0 deletions src/Fieldtypes/Member.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace Expressionengine\Coilpack\Fieldtypes;

use Expressionengine\Coilpack\Contracts\Field;
use Expressionengine\Coilpack\Contracts\ListsGraphType;
use Expressionengine\Coilpack\FieldtypeOutput;
use Expressionengine\Coilpack\Fieldtypes\Presenters\MemberPresenter;
use Expressionengine\Coilpack\Models\FieldContent;

class Member extends Fieldtype implements ListsGraphType
{
protected $presenter;

public function __construct(string $name, $id = null)
{
parent::__construct($name, $id);
$this->presenter = new MemberPresenter;
}

public function apply(FieldContent $content, $parameters = [])
{
$data = $this->presenter->present($content, $parameters);

return FieldtypeOutput::for($this)->value($data);
}

public function parametersForField(Field $field = null): array
{
return $this->presenter->defineParameters();
}

public function graphType()
{
return 'Member';
}
}
19 changes: 19 additions & 0 deletions src/Fieldtypes/Presenters/MemberPresenter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Expressionengine\Coilpack\Fieldtypes\Presenters;

use Expressionengine\Coilpack\Models\FieldContent;
use Expressionengine\Coilpack\Models\Member\Member;
use Expressionengine\Coilpack\Traits\HasArgumentsAndParameters;

class MemberPresenter extends Presenter
{
use HasArgumentsAndParameters, Traits\QueriesRelationships;

public function present(FieldContent $content, $arguments)
{
$query = $this->buildRelationshipQuery($content, new Member);

return $query->get();
}
}
34 changes: 5 additions & 29 deletions src/Fieldtypes/Presenters/RelationshipPresenter.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,20 @@
namespace Expressionengine\Coilpack\Fieldtypes\Presenters;

use Expressionengine\Coilpack\FieldtypeManager;
use ExpressionEngine\Coilpack\Models\Category\Category;
use ExpressionEngine\Coilpack\Models\Channel\ChannelEntry;
use ExpressionEngine\Coilpack\Models\Channel\Scopes;
use Expressionengine\Coilpack\Models\FieldContent;
use Expressionengine\Coilpack\Support\Arguments\FilterArgument;
use Expressionengine\Coilpack\Support\Arguments\ListArgument;
use Expressionengine\Coilpack\Support\Arguments\SearchArgument;
use Expressionengine\Coilpack\Support\Arguments\Term;
use Expressionengine\Coilpack\Support\Parameter;
use Expressionengine\Coilpack\Traits\HasArgumentsAndParameters;

class RelationshipPresenter extends Presenter
{
use HasArgumentsAndParameters;
use HasArgumentsAndParameters, Traits\QueriesRelationships;

private $fieldtypeManager;

Expand All @@ -24,34 +27,7 @@ public function __construct()

public function present(FieldContent $content, $arguments)
{
$isGrid = $content->field->field_type === 'grid';
$isFluid = $content->hasAttribute('fluid_field');
$fluidFieldId = ($isFluid) ? $content->fluid_field_data_id : 0;
$this->arguments($arguments);

$query = ChannelEntry::query();

if ($content->entry->isPreview()) {
$query->whereIn('entry_id', $content->data['data'] ?? [0]);
} else {
$query->select('channel_titles.*')
->join('relationships', 'entry_id', '=', 'child_id')
->when($isFluid, function ($query) use ($fluidFieldId) {
$query->where('relationships.fluid_field_data_id', $fluidFieldId);
}, function ($query) {
$query->where('relationships.fluid_field_data_id', 0);
})
->when($isGrid, function ($query) use ($content) {
$query->where('relationships.grid_field_id', $content->field->field_id)
->where('relationships.grid_row_id', $content->grid_row_id)
->where('relationships.grid_col_id', $content->grid_col_id);
}, function ($query) use ($content) {
$query->where('relationships.field_id', $content->field->field_id)
->where('relationships.grid_field_id', 0);
})
->where('relationships.parent_id', $content->entry_id)
->orderBy('order');
}
$query = $this->buildRelationshipQuery($content, new ChannelEntry, 'relationships');

// Author
$query->when($this->hasArgument('author'), function ($query) {
Expand Down
44 changes: 44 additions & 0 deletions src/Fieldtypes/Presenters/Traits/QueriesRelationships.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace Expressionengine\Coilpack\Fieldtypes\Presenters\Traits;

use Expressionengine\Coilpack\Model;
use Expressionengine\Coilpack\Models\FieldContent;
use Illuminate\Support\Str;

trait QueriesRelationships
{
public function buildRelationshipQuery(FieldContent $content, Model $model, $tableName = null)
{
$isGrid = $content->field->field_type === 'grid';
$isFluid = $content->hasAttribute('fluid_field');
$fluidFieldId = ($isFluid) ? $content->fluid_field_data_id : 0;

$query = $model::query();
$tableName = $tableName ?: Str::singular($model->getTable()).'_relationships';

if ($content->entry->isPreview()) {
$query->whereIn('member_id', $content->data['data'] ?? [0]);
} else {
$query->select("{$model->getTable()}.*")
->join($tableName, $model->getKeyName(), '=', 'child_id')
->when($isFluid, function ($query) use ($fluidFieldId, $tableName) {
$query->where("$tableName.fluid_field_data_id", $fluidFieldId);
}, function ($query) use ($tableName) {
$query->where("$tableName.fluid_field_data_id", 0);
})
->when($isGrid, function ($query) use ($content, $tableName) {
$query->where("$tableName.grid_field_id", $content->field->field_id)
->where("$tableName.grid_row_id", $content->grid_row_id)
->where("$tableName.grid_col_id", $content->grid_col_id);
}, function ($query) use ($content, $tableName) {
$query->where("$tableName.field_id", $content->field->field_id)
->where("$tableName.grid_field_id", 0);
})
->where("$tableName.parent_id", $content->entry_id)
->orderBy('order');
}

return $query;
}
}
5 changes: 5 additions & 0 deletions src/Support/Parameter.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ public function __get($key)
return $this->attributes[$key];
}

public function __set($key, $value)
{
return $this->attributes[$key] = $value;
}

public function __isset($key)
{
return array_key_exists($key, $this->attributes);
Expand Down
2 changes: 2 additions & 0 deletions src/Traits/CanAccessRestrictedClass.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ protected function setRestrictedProperty($object, $property, $value)
{
$reflection = new \ReflectionClass($object);
$prop = $reflection->getProperty($property);
$prop->setAccessible(true);

$prop->setValue($object, $value);
}

Expand Down
30 changes: 24 additions & 6 deletions src/View/LegacyTag.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,34 @@ public function __toString()

public function run()
{
$output = Coilpack::isolateTemplateLibrary(function ($template) {
return Coilpack::isolateTemplateLibrary(function ($template) {
$output = $this->getInstanceClass()->{$this->method}();
$templateData = $template->get_data();
$templateOutput = \Expressionengine\Coilpack\TemplateOutput::make();

// If the tag generated non-empty string output we should pass that along to the TemplateOutput class
// this could be a single tag that is passing along its final value while also parsing/setting data
// that will be available through $template->get_data()
if (! empty($output) && is_string($output)) {
$templateOutput->string($output);
}

// If the Tag stored data for us in the template library that is preferable to the generated output
return $template->get_data() ?: $output;
}, $this->getArguments());
$templateData = $templateData ?: $output;

// If our template data is an array of arrays we will transform it into a collection of TemplateOutputs
if (is_array($templateData) && is_array(current($templateData))) {
$templateData = collect($templateData)->map(function ($row) {
return \Expressionengine\Coilpack\TemplateOutput::make()->value($row);
});
}

return is_array($output) && is_array(current($output)) ? collect($output)->map(function ($row) {
return \Expressionengine\Coilpack\TemplateOutput::make()->value($row);
}) : \Expressionengine\Coilpack\TemplateOutput::make()->value($output);
if (! empty($templateData)) {
$templateOutput->value($templateData);
}

return $templateOutput;
}, $this->getArguments());
}

private function getInstanceClass()
Expand Down
2 changes: 1 addition & 1 deletion src/View/Tags/Channel/Entries.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public function defineParameters(): array
// 'prefix' => 'Channel_Entries',
'description' => 'Search for entries matching a certain criteria',
'type' => function () {
return app(FieldtypeManager::class)->allFields()->map(function ($field) {
return app(FieldtypeManager::class)->allFields()->toBase()->map(function ($field) {
return new Parameter([
'name' => $field->field_name,
'type' => 'string',
Expand Down
18 changes: 18 additions & 0 deletions tests/Fieldtype/MemberTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Tests\Fieldtype;

use Expressionengine\Coilpack\Models\Channel\ChannelEntry;
use Tests\TestCase;

class MemberTest extends TestCase
{
public function test_member()
{
$entry = ChannelEntry::where('title', 'Test Fieldtypes')->first();

$output = $entry->test_members->value();

$this->assertEquals('admin', $output->toArray()[0]['username']);
}
}
19 changes: 19 additions & 0 deletions tests/Graphql/ChannelEntriesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,25 @@ public function test_entries_relationship()
->assertJsonFragment(['type' => ['value' => 'soundcloud']]);
}

public function test_entries_member()
{
$this->postJson('graphql', [
'query' => <<<'GQL'
{
exp_channel_entries(search: {title:"Test Fieldtypes"} limit:1){
data {
entry_id
test_members {
screen_name
}
}
}
}
GQL
])
->assertJsonFragment(['screen_name' => 'admin']);
}

public function test_entries_fluid()
{
/**
Expand Down
Loading

0 comments on commit dfaf590

Please sign in to comment.