-
Notifications
You must be signed in to change notification settings - Fork 203
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
EZP-31078: Enhanced Content Type Value Object #2839
Conversation
* | ||
* @return bool | ||
*/ | ||
public function hasFieldDefinitionWithType(string $fieldTypeIdentifier): bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not returning the number of fields of the given type? The returned number can be used in the same IFs as a boolean would do. It also allows for more complex scenarios (eg. a Content has 2 images => which one to map for our needs ?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also: given that this method does not optimize away any processing, as it is seems a bit pointless... The user might just put in her code the same check if ($ft->getFieldDefinitionWithType($fieldTypeIdentifier) !== null)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would sound good with a countFieldDefinitionsWithType()
.
* | ||
* @return \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition | ||
*/ | ||
public function getFieldDefinitionWithType(string $fieldTypeIdentifier): ?FieldDefinition |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'ofType' instead 'withType' ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also, might add 2nd param int $offset = 0
. This way we could get the 1st image field, the 2nd one, etc...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need getFirstFieldDefinitionWithType()
and getFieldDefinitionsWithType()
? My question about the use-case for this still stands :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bdunogier if you have the getFieldDefinitionsWithType($limit, $offset), I don't think both the getFirstFieldDefinitionWithType() or getFieldDefinitionWithType() method would be needed at all.
Hm. Wouldn't it be more useful to have Having the method only return the first definition with a specific field type is most of the time limiting. |
getFieldDefinitionWithType() only fetches the first match. Typical example - being able to detect all image or file fields in the content type. Of course this can be done by manually looping through the field definitions, but it would be convenient to have both in PHP and the templates. |
About the I kind of like the May I also ask what the use-case for finding a field def with a given type is ? If it's generating a thumbnail for a content item, we actually have a feature dedicated to that in store, that does it better and doesn't spread the logic around (similar to content object name). |
@emodric while in theory |
Hah, maybe :) I find it convenient and readable enough to clearly communicate intent. In any case, having a method return only the first match is way less usable. |
Thank you for a feedback. While reading comments about namespace eZ\Publish\API\Repository\Values\ContentType;
use Closure;
use Countable;
use IteratorAggregate;
interface FieldDefinitionCollection extends Countable, IteratorAggregate
{
/**
* This method returns the field definition for the given identifier.
*
* @param string $fieldDefinitionIdentifier
*
* @return \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition|null
*/
public function get(string $fieldDefinitionIdentifier): ?FieldDefinition;
/**
* This method returns true if the field definition for the given identifier exists.
*
* @param string $fieldDefinitionIdentifier
*
* @return bool
*/
public function has(string $fieldDefinitionIdentifier): bool;
/**
* Return first element of collection
*
* @return \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition|null
*/
public function first(): ?FieldDefinition;
/**
* Return last element of collection
*
* @return \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition|null
*/
public function last(): ?FieldDefinition;
/**
* Checks whether the collection is empty (contains no elements).
*
* @return bool TRUE if the collection is empty, FALSE otherwise.
*/
public function isEmpty(): bool;
/**
* Returns all the elements of this collection that satisfy the predicate p.
* The order of the elements is preserved.
*
* @param Closure $p The predicate used for filtering.
*
* @return FieldDefinitionCollection A collection with the results of the filter operation.
*/
public function filter(Closure $p): FieldDefinitionCollection;
/**
* Applies the given function to each element in the collection and returns
* a new collection with the elements returned by the function.
*
* @param Closure $p The predicate.
*
* @return array
*/
public function map(Closure $p): array;
/**
* Tests whether the given predicate p holds for all elements of this collection.
*
* @param Closure $p The predicate.
*
* @return bool TRUE, if the predicate yields TRUE for all elements, FALSE otherwise.
*/
public function all(Closure $p): bool;
/**
* Alias for FieldDefinitionCollectionInterface::exists
*
* @param Closure $p The predicate.
*
* @return bool TRUE if the predicate is TRUE for at least one element, FALSE otherwise.
*/
public function any(Closure $p): bool;
/**
* Tests for the existence of an element that satisfies the given predicate.
*
* @param Closure $p The predicate.
*
* @return bool TRUE if the predicate is TRUE for at least one element, FALSE otherwise.
*/
public function exists(Closure $p): bool;
/**
* Partitions this collection in two collections according to a predicate.
*
* @param Closure $p The predicate on which to partition.
*
* @return FieldDefinitionCollection[] An array with two elements. The first element contains the collection
* of elements where the predicate returned TRUE, the second element
* contains the collection of elements where the predicate returned FALSE.
*/
public function partition(Closure $p): array;
/**
* Gets a native PHP array representation of the collection.
*
* @return \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition[]
*/
public function toArray(): array;
}
WDYT ? |
@adamwojs tbh I am not sure that would strike the best balance between flexibility and complexity. |
Keeping balance between flexibility and complexity is the hardest part of designing APIs. IMHO This covers all discussed use cases: // 1. Check if field definition with given type exists
$contentType->getFieldDefinitions()->filterByType('ezuser')->isEmpty();
// 2. Get first field definition with given type
$contentType->getFieldDefinitions()->filterByType('ezuser')->first();
// 3. Get the number of fields definition of the given type
$contentType->getFieldDefinitions()->filterByType('ezimage')->count();
// 4. Get all fields definition of the given type
$contentType->getFieldDefinitions()->filterByType('ezimage'); and from the maintainer POV it will reduce the responsibility of namespace eZ\Publish\API\Repository\Values\ContentType;
use eZ\Publish\API\Repository\Values\ValueObject;
use eZ\Publish\SPI\Repository\Values\MultiLanguageDescription;
use eZ\Publish\SPI\Repository\Values\MultiLanguageName;
abstract class ContentType extends ValueObject implements MultiLanguageName, MultiLanguageDescription
{
// ...
abstract public function getFieldDefinitions(): FieldDefinitionCollection;
public function getFieldDefinition(string $fieldDefinitionIdentifier): ?FieldDefinition
{
return $this->getFieldDefinitions()->get($fieldDefinitionIdentifier);
}
public function hasFieldDefinition(string $fieldDefinitionIdentifier): bool
{
return $this->getFieldDefinitions()->has($fieldDefinitionIdentifier);
}
} † See ‡ For example filtering field definitions by groups and Nevertheless we can also keep methods |
7068635
to
5325f75
Compare
@@ -175,16 +175,67 @@ abstract class ContentType extends ValueObject implements MultiLanguageName, Mul | |||
/** | |||
* This method returns the content type field definitions from this type. | |||
* | |||
* @return \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition[] | |||
* @return \eZ\Publish\API\Repository\Values\ContentType\FieldDefinitionCollection |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As this goes to master we could skip @param/@return
here and below
* | ||
* @return \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition|null | ||
*/ | ||
public function get(string $fieldDefinitionIdentifier): ?FieldDefinition; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public function get(string $fieldDefinitionIdentifier): ?FieldDefinition; | |
public function get(string $fieldDefinitionIdentifier): FieldDefinition; |
* | ||
* @return FieldDefinitionCollection A collection with the results of the filter operation. | ||
*/ | ||
public function filter(Closure $p): FieldDefinitionCollection; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public function filter(Closure $p): FieldDefinitionCollection; | |
public function filter(Closure $predicate): FieldDefinitionCollection; |
* | ||
* @param Closure $p The predicate used for filtering. | ||
* | ||
* @return FieldDefinitionCollection A collection with the results of the filter operation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FQCN
protected function createFieldDefinitionCollectionMock(array $fieldDefinitions): FieldDefinitionCollection | ||
{ | ||
return new \eZ\Publish\Core\Repository\Values\ContentType\FieldDefinitionCollection($fieldDefinitions); | ||
// $collection = $this->createMock(FieldDefinitionCollection::class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
commented code
private $fieldDefinitions; | ||
|
||
/** | ||
* Field definitions indexed by identifier. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not convinced that this comment is necessary
eZ/Publish/Core/Repository/Values/ContentType/FieldDefinitionCollection.php
Show resolved
Hide resolved
}; | ||
} | ||
|
||
public function offsetExists($offset) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public function offsetExists($offset) | |
public function offsetExists($offset): bool |
return isset($this->fieldDefinitions[$offset]); | ||
} | ||
|
||
public function offsetGet($offset) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing return type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be good if someone from @ezsystems/documentation-team looked at PHPDocs.
Nitpicks:
* | ||
* @param string $fieldTypeIdentifier | ||
* | ||
* @return FieldDefinitionCollection A collection with the results of the filter operation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inconsistent PHPDoc: some param and return types are FQCN, some are not. E.g.: ^
@@ -144,7 +145,7 @@ public function testLoadVersionInfoById() | |||
* Test for the loadVersionInfo() method, of a draft. | |||
* | |||
* @depends testLoadVersionInfoById | |||
* @covers \eZ\Publish\Core\Repository\ContentService::loadVersionInfoById | |||
* @covers \eZ\Publish\Core\Repository\ContentService::loadVersionInfoById |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it a result of CS fixer?
|
||
final class FieldDefinitionCollectionTest extends TestCase | ||
{ | ||
public function testGet(): void |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you add @covers
to all those methods?
Not insisting, because we do not use it right now, but it might come in handy at some point (I also expect it's beneficial IDE go to test nav - just guessing).
e.g.:
/**
* @covers \eZ\Publish\API\Repository\Values\ContentType\FieldDefinitionCollection::get
*/
(intentionally no braces after the method name)
} | ||
|
||
/** | ||
* Returns predicate with is always true. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Returns predicate with is always true. | |
* Returns a predicate with is always true. |
not quite following "with" in this sentence, but seems like it's intentional?
}; | ||
} | ||
|
||
public function offsetExists($offset) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no strict types?
5325f75
to
b8dedac
Compare
PR updated according to @alongosz and @mikadamczyk code review suggestions. |
Once again PR updated according to @mikadamczyk @alongosz code review suggestions :-) |
…PI\Repository\Exceptions\Exception in OutOfBoundsException)
5ecaf22
to
323fd60
Compare
PR rebased against current master to implement |
master
Changelog
eZ\Publish\API\Repository\Values\ContentType\FieldDefinitionCollection
which takeover responsibility of providing access field definitions:Changed return type of
getFieldDefinitions()
from array toFieldDefinitionCollection
.Added
eZ\Publish\API\Repository\Values\ContentType\ContentType
methods:hasFieldDefinition($fieldDefinitionIdentifier): bool
hasFieldDefinitionOfType(string $fieldTypeIdentifier): bool
getFieldDefinitionsOfType(string $fieldTypeIdentifier): FieldDefinitionCollection
getFirstFieldDefinitionOfType(string $fieldTypeIdentifier): ?FieldDefinition
Use Cases
getFirstFieldDefinitionOfType
The typical use case for
getFirstFieldDefinitionOfType
is the search for singular field type (ref.\eZ\Publish\API\Repository\FieldType::isSingular
). For example:ezpublish-kernel/eZ/Publish/Core/Repository/UserService.php
Lines 416 to 423 in c54917f
ezpublish-kernel/eZ/Publish/Core/MVC/Symfony/Templating/Twig/Extension/ContentExtension.php
Lines 237 to 256 in c849ef1
hasFieldDefinition
andhasFieldDefintionWithType
hasFieldDefinition
andhasFieldDefintionWithType
is just syntax sugar which improvs code readability.VS
TODO:
/doc/bc/changes-8.0.md
$ composer fix-cs
).