diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 47caa7eb..b8b66777 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -7,6 +7,7 @@ docs/ @JoshuaEstes /src/SonsOfPHP/Bard @JoshuaEstes # Each component/contract needs a Team +/src/SonsOfPHP/**/Attribute @JoshuaEstes /src/SonsOfPHP/**/Cache @JoshuaEstes /src/SonsOfPHP/**/Clock @JoshuaEstes /src/SonsOfPHP/**/Container @JoshuaEstes diff --git a/.github/labeler.yml b/.github/labeler.yml index e0ece348..e2de3d60 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -2,6 +2,11 @@ Bard: - docs/bard/* - src/SonsOfPHP/Bard/* +Attribute: + - docs/components/attribute/* + - docs/contracts/attribute/* + - src/SonsOfPHP/**/Attribute/* + Cache: - docs/components/cache/* - src/SonsOfPHP/**/Cache/* diff --git a/composer.json b/composer.json index b3791522..29910ff8 100644 --- a/composer.json +++ b/composer.json @@ -54,7 +54,8 @@ "psr/http-server-handler-implementation": "^1.0", "psr/http-server-middleware-implementation": "^1.0", "sonsofphp/http-handler-implementation": "0.3.x-dev", - "sonsofphp/mailer-implementation": "0.3.x-dev" + "sonsofphp/mailer-implementation": "0.3.x-dev", + "sonsofphp/attribute-implementation": "0.3.x-dev" }, "require": { "php": ">=8.1", @@ -127,11 +128,15 @@ "sonsofphp/http-handler": "self.version", "sonsofphp/http-handler-contract": "self.version", "sonsofphp/mailer-contract": "self.version", - "sonsofphp/mailer": "self.version" + "sonsofphp/mailer": "self.version", + "sonsofphp/attribute-contract": "self.version", + "sonsofphp/attribute": "self.version" }, "autoload": { "psr-4": { "SonsOfPHP\\Bard\\": "src/SonsOfPHP/Bard/src", + "SonsOfPHP\\Contract\\Attribute\\": "src/SonsOfPHP/Contract/Attribute", + "SonsOfPHP\\Component\\Attribute\\": "src/SonsOfPHP/Component/Attribute", "SonsOfPHP\\Contract\\Mailer\\": "src/SonsOfPHP/Contract/Mailer", "SonsOfPHP\\Component\\Mailer\\": "src/SonsOfPHP/Component/Mailer", "SonsOfPHP\\Component\\Cache\\": "src/SonsOfPHP/Component/Cache", @@ -174,6 +179,7 @@ }, "exclude-from-classmap": [ "src/SonsOfPHP/Bard/Tests", + "src/SonsOfPHP/Component/Attribute/Tests", "src/SonsOfPHP/Component/Mailer/Tests", "src/SonsOfPHP/Component/Cache/Tests", "src/SonsOfPHP/Component/Clock/Tests", diff --git a/src/SonsOfPHP/Component/Attribute/.gitattributes b/src/SonsOfPHP/Component/Attribute/.gitattributes new file mode 100644 index 00000000..84c7add0 --- /dev/null +++ b/src/SonsOfPHP/Component/Attribute/.gitattributes @@ -0,0 +1,4 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore diff --git a/src/SonsOfPHP/Component/Attribute/.gitignore b/src/SonsOfPHP/Component/Attribute/.gitignore new file mode 100644 index 00000000..5414c2c6 --- /dev/null +++ b/src/SonsOfPHP/Component/Attribute/.gitignore @@ -0,0 +1,3 @@ +composer.lock +phpunit.xml +vendor/ diff --git a/src/SonsOfPHP/Component/Attribute/Attribute.php b/src/SonsOfPHP/Component/Attribute/Attribute.php index 1a532f22..3ae4ee86 100644 --- a/src/SonsOfPHP/Component/Attribute/Attribute.php +++ b/src/SonsOfPHP/Component/Attribute/Attribute.php @@ -8,9 +8,11 @@ use SonsOfPHP\Contract\Attribute\AttributeTypeInterface; /** + * @author Joshua Estes */ class Attribute implements AttributeInterface, \Stringable { + protected ?string $code = null; protected ?string $name = null; protected int $position = 0; protected ?AttributeTypeInterface $type = null; @@ -20,6 +22,11 @@ public function __toString(): string return (string) $this->getName(); } + public function getCode(): ?string + { + return $this->code; + } + public function setCode(?string $code): static { // Normalize value diff --git a/src/SonsOfPHP/Component/Attribute/AttributeType.php b/src/SonsOfPHP/Component/Attribute/AttributeType.php index 0bed0e85..9151c57a 100644 --- a/src/SonsOfPHP/Component/Attribute/AttributeType.php +++ b/src/SonsOfPHP/Component/Attribute/AttributeType.php @@ -6,6 +6,9 @@ use SonsOfPHP\Contract\Attribute\AttributeTypeInterface; +/** + * @author Joshua Estes + */ enum AttributeType: string implements AttributeTypeInterface { case TYPE_TEXT = 'text'; diff --git a/src/SonsOfPHP/Component/Attribute/AttributeValue.php b/src/SonsOfPHP/Component/Attribute/AttributeValue.php index 903135aa..d25045d3 100644 --- a/src/SonsOfPHP/Component/Attribute/AttributeValue.php +++ b/src/SonsOfPHP/Component/Attribute/AttributeValue.php @@ -10,6 +10,7 @@ use SonsOfPHP\Contract\Attribute\AttributeValueInterface; /** + * @author Joshua Estes */ class AttributeValue implements AttributeValueInterface { diff --git a/src/SonsOfPHP/Component/Attribute/LICENSE b/src/SonsOfPHP/Component/Attribute/LICENSE new file mode 100644 index 00000000..39238382 --- /dev/null +++ b/src/SonsOfPHP/Component/Attribute/LICENSE @@ -0,0 +1,19 @@ +Copyright 2022 to Present Joshua Estes + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/SonsOfPHP/Component/Attribute/README.md b/src/SonsOfPHP/Component/Attribute/README.md new file mode 100644 index 00000000..113e0b20 --- /dev/null +++ b/src/SonsOfPHP/Component/Attribute/README.md @@ -0,0 +1,16 @@ +Sons of PHP - Attribute +======================= + +## Learn More + +* [Documentation][docs] +* [Contributing][contributing] +* [Report Issues][issues] and [Submit Pull Requests][pull-requests] in the [Mother Repository][mother-repo] +* Get Help & Support using [Discussions][discussions] + +[discussions]: https://github.com/orgs/SonsOfPHP/discussions +[mother-repo]: https://github.com/SonsOfPHP/sonsofphp +[contributing]: https://docs.sonsofphp.com/contributing/ +[docs]: https://docs.sonsofphp.com/components/attribute/ +[issues]: https://github.com/SonsOfPHP/sonsofphp/issues?q=is%3Aopen+is%3Aissue+label%3AAttribute +[pull-requests]: https://github.com/SonsOfPHP/sonsofphp/pulls?q=is%3Aopen+is%3Apr+label%3AAttribute diff --git a/src/SonsOfPHP/Component/Attribute/Tests/AttributeTest.php b/src/SonsOfPHP/Component/Attribute/Tests/AttributeTest.php new file mode 100644 index 00000000..54a00f2e --- /dev/null +++ b/src/SonsOfPHP/Component/Attribute/Tests/AttributeTest.php @@ -0,0 +1,63 @@ +model = new Attribute(); + } + + /** + * @coversNothing + */ + public function testItHasTheCorrectInterfaces(): void + { + $this->assertInstanceOf(AttributeInterface::class, $this->model); + } + + /** + * @covers ::getCode + * @covers ::setCode + */ + public function testCode(): void + { + $this->assertNull($this->model->getCode()); + $this->model->setCode('sku'); + $this->assertSame('sku', $this->model->getCode()); + } + + /** + * @covers ::getName + * @covers ::setName + */ + public function testName(): void + { + $this->assertNull($this->model->getName()); + $this->model->setName('Test Attribute'); + $this->assertSame('Test Attribute', $this->model->getName()); + } + + /** + * @covers ::getPosition + * @covers ::setPosition + */ + public function testPosition(): void + { + $this->assertSame(0, $this->model->getPosition()); + $this->model->setPosition(100); + $this->assertSame(100, $this->model->getPosition()); + } +} diff --git a/src/SonsOfPHP/Component/Attribute/composer.json b/src/SonsOfPHP/Component/Attribute/composer.json new file mode 100644 index 00000000..a8e4c668 --- /dev/null +++ b/src/SonsOfPHP/Component/Attribute/composer.json @@ -0,0 +1,54 @@ +{ + "name": "sonsofphp/attribute", + "type": "library", + "description": "Attribute library for PHP", + "keywords": [ + "attribute" + ], + "homepage": "https://github.com/SonsOfPHP/attribute", + "license": "MIT", + "authors": [ + { + "name": "Joshua Estes", + "email": "joshua@sonsofphp.com" + } + ], + "support": { + "issues": "https://github.com/SonsOfPHP/sonsofphp/issues", + "forum": "https://github.com/orgs/SonsOfPHP/discussions", + "docs": "https://docs.sonsofphp.com" + }, + "autoload": { + "psr-4": { + "SonsOfPHP\\Component\\Attribute\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "prefer-stable": true, + "require": { + "php": ">=8.2", + "sonsofphp/attribute-contract": "0.3.x-dev" + }, + "provide": { + "sonsofphp/attribute-implementation": "0.3.x-dev" + }, + "extra": { + "sort-packages": true, + "branch-alias": { + "dev-main": "0.3.x-dev" + } + }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/JoshuaEstes" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/subscription/pkg/packagist-sonsofphp-sonsofphp" + } + ] +} \ No newline at end of file diff --git a/src/SonsOfPHP/Contract/Attribute/AttributeInterface.php b/src/SonsOfPHP/Contract/Attribute/AttributeInterface.php index a422f330..5ebc5d24 100644 --- a/src/SonsOfPHP/Contract/Attribute/AttributeInterface.php +++ b/src/SonsOfPHP/Contract/Attribute/AttributeInterface.php @@ -5,24 +5,66 @@ namespace SonsOfPHP\Contract\Attribute; /** + * @author Joshua Estes */ interface AttributeInterface { public function getCode(): ?string; + /** + * The code is unique, no two attributes should have the same code. The code + * should ONLY consist of letters, numbers, underscores, and periods. + * + * Example Code: sku + * + * @throws InvalidArgumentException + * - When the code is invalid or contains invalid characters + */ public function setCode(?string $code): static; public function getName(): ?string; + /** + * The name of the attribute. This could be displayed on the frontend to + * users or used anywhere. This is the friendly version of the code. This + * does not have to be unique. + * + * @throws InvalidArgumentException + * - When the name is invalid for any reason + */ public function setName(?string $name): static; + public function getType(): ?AttributeTypeInterface; + + /** + * The attribute type such as Text, Textarea, Select, etc. + */ + public function setType(AttributeTypeInterface $type): static; + public function getPosition(): int; + /** + * The position helps with ordering. When returning the list of attributes, the position + * should determine what order they are listed in. + */ public function setPosition(int $position): static; - public function getType(): ?AttributeTypeInterface; - + /** + * Is this a system attribute? System attributes should not be editable by + * a user. + */ //public function isSystem(): bool; + /** + * If the attribute is unique, the values should be checked. An example of + * a unique value would be an email address. This will help avoid duplicate + * resources. + */ //public function isUnique(): bool; + + /** + * Similar to a system attribute, this means that the name and code should + * not be modified by users + */ + //public function isLocked(): bool; } diff --git a/src/SonsOfPHP/Contract/Attribute/AttributeSubjectInterface.php b/src/SonsOfPHP/Contract/Attribute/AttributeSubjectInterface.php index a41b5398..7b3a45f4 100644 --- a/src/SonsOfPHP/Contract/Attribute/AttributeSubjectInterface.php +++ b/src/SonsOfPHP/Contract/Attribute/AttributeSubjectInterface.php @@ -9,6 +9,8 @@ /** * Classes should implement this is they want to use attributes. For example, the Product * class would implement this + * + * @author Joshua Estes */ interface AttributeSubjectInterface { diff --git a/src/SonsOfPHP/Contract/Attribute/AttributeTypeInterface.php b/src/SonsOfPHP/Contract/Attribute/AttributeTypeInterface.php index 2eeed2e3..52b2dcb3 100644 --- a/src/SonsOfPHP/Contract/Attribute/AttributeTypeInterface.php +++ b/src/SonsOfPHP/Contract/Attribute/AttributeTypeInterface.php @@ -4,6 +4,9 @@ namespace SonsOfPHP\Contract\Attribute; +/** + * @author Joshua Estes + */ interface AttributeTypeInterface { public function getDisplayName(): string; diff --git a/src/SonsOfPHP/Contract/Attribute/AttributeValueInterface.php b/src/SonsOfPHP/Contract/Attribute/AttributeValueInterface.php index f0b531c6..69d4357b 100644 --- a/src/SonsOfPHP/Contract/Attribute/AttributeValueInterface.php +++ b/src/SonsOfPHP/Contract/Attribute/AttributeValueInterface.php @@ -5,6 +5,7 @@ namespace SonsOfPHP\Contract\Attribute; /** + * @author Joshua Estes */ interface AttributeValueInterface { diff --git a/src/SonsOfPHP/Contract/Attribute/composer.json b/src/SonsOfPHP/Contract/Attribute/composer.json index ef9d0c40..df99b0ad 100644 --- a/src/SonsOfPHP/Contract/Attribute/composer.json +++ b/src/SonsOfPHP/Contract/Attribute/composer.json @@ -51,4 +51,4 @@ "url": "https://tidelift.com/subscription/pkg/packagist-sonsofphp-sonsofphp" } ] -} +} \ No newline at end of file