diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index d2df5560..cc81cd80 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -22,4 +22,5 @@ docs/ @JoshuaEstes /src/SonsOfPHP/**/Logger @JoshuaEstes /src/SonsOfPHP/**/Money @JoshuaEstes /src/SonsOfPHP/**/Pager @JoshuaEstes +/src/SonsOfPHP/**/Search @JoshuaEstes /src/SonsOfPHP/**/Version @JoshuaEstes diff --git a/.github/labeler.yml b/.github/labeler.yml index fb9d35e6..921de0a1 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -62,6 +62,10 @@ Pager: - docs/components/pager/* - src/SonsOfPHP/**/Pager/* +Search: + - docs/components/search/* + - src/SonsOfPHP/**/Search/* + Version: - docs/components/version/* - src/SonsOfPHP/**/Version/* diff --git a/CHANGELOG.md b/CHANGELOG.md index f6a29d4d..e1357334 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ To get the diff between two versions, go to https://github.com/SonsOfPHP/sonsofp * [PR #134](https://github.com/SonsOfPHP/sonsofphp/pull/134) [Pager] New Component * [PR #170](https://github.com/SonsOfPHP/sonsofphp/pull/170) [Link] New Component (PSR-13) * [PR #173](https://github.com/SonsOfPHP/sonsofphp/pull/173) [Money] Twig Bridge +* [PR #176](https://github.com/SonsOfPHP/sonsofphp/pull/176) [Search] New Component and Contract ## [0.3.8] diff --git a/bard.json b/bard.json index 8837d7fa..72256d7b 100644 --- a/bard.json +++ b/bard.json @@ -129,6 +129,14 @@ "path": "src/SonsOfPHP/Contract/Pager", "repository": "git@github.com:SonsOfPHP/pager-contract.git" }, + { + "path": "src/SonsOfPHP/Component/Search", + "repository": "git@github.com:SonsOfPHP/search.git" + }, + { + "path": "src/SonsOfPHP/Contract/Search", + "repository": "git@github.com:SonsOfPHP/search-contract.git" + }, { "path": "src/SonsOfPHP/Contract/Version", "repository": "git@github.com:SonsOfPHP/version-contract.git" diff --git a/composer.json b/composer.json index d42f8f7f..398286d0 100644 --- a/composer.json +++ b/composer.json @@ -47,7 +47,8 @@ "psr/log-implementation": "^1.0 || ^2.0 || ^3.0", "sonsofphp/logger-implementation": "0.3.x-dev", "sonsofphp/pager-implementation": "0.3.x-dev", - "psr/link-implementation": "^1.0 || ^2.0" + "psr/link-implementation": "^1.0 || ^2.0", + "sonsofphp/search-implementation": "0.3.x-dev" }, "require": { "php": ">=8.1", @@ -110,7 +111,9 @@ "sonsofphp/money-twig": "self.version", "sonsofphp/pager-doctrine-collections": "self.version", "sonsofphp/pager-doctrine-dbal": "self.version", - "sonsofphp/pager-doctrine-orm": "self.version" + "sonsofphp/pager-doctrine-orm": "self.version", + "sonsofphp/search-contract": "self.version", + "sonsofphp/search": "self.version" }, "autoload": { "psr-4": { @@ -146,6 +149,8 @@ "SonsOfPHP\\Contract\\Logger\\": "src/SonsOfPHP/Contract/Logger", "SonsOfPHP\\Contract\\Money\\": "src/SonsOfPHP/Contract/Money", "SonsOfPHP\\Contract\\Pager\\": "src/SonsOfPHP/Contract/Pager", + "SonsOfPHP\\Component\\Search\\": "src/SonsOfPHP/Component/Search", + "SonsOfPHP\\Contract\\Search\\": "src/SonsOfPHP/Contract/Search", "SonsOfPHP\\Contract\\Version\\": "src/SonsOfPHP/Contract/Version" }, "exclude-from-classmap": [ @@ -172,7 +177,8 @@ "src/SonsOfPHP/Bridge/Doctrine/Collections/Pager/Tests", "src/SonsOfPHP/Bridge/Doctrine/DBAL/Pager/Tests", "src/SonsOfPHP/Bridge/Doctrine/ORM/Pager/Tests", - "src/SonsOfPHP/Component/Version/Tests" + "src/SonsOfPHP/Component/Version/Tests", + "src/SonsOfPHP/Component/Search/Tests" ] }, "extra": { diff --git a/docs/components/search/index.md b/docs/components/search/index.md new file mode 100644 index 00000000..0d7a72df --- /dev/null +++ b/docs/components/search/index.md @@ -0,0 +1,28 @@ +--- +title: Search +description: Abstract PHP Search Library that supports many different backends +--- + +## Installation + +```shell +composer require sonsofphp/search +``` + +## Usage + +```php +query($query); // @var \SonsOfPHP\Contract\Pager\PagerInterface +foreach ($pager as $result) { + // ... +} +``` diff --git a/mkdocs.yml b/mkdocs.yml index b8b29ee1..fec1036c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -114,6 +114,7 @@ nav: - Operators: components/money/operators.md - Queries: components/money/queries.md - Pager: components/pager/index.md + - Search: components/search/index.md - Version: components/version/index.md - Contracts: - contracts/index.md diff --git a/src/SonsOfPHP/Component/Pager/README.md b/src/SonsOfPHP/Component/Pager/README.md index 79b97e64..94b314db 100644 --- a/src/SonsOfPHP/Component/Pager/README.md +++ b/src/SonsOfPHP/Component/Pager/README.md @@ -1,5 +1,5 @@ -Sons of PHP - Logger -==================== +Sons of PHP - Pager +=================== ## Learn More @@ -11,6 +11,6 @@ Sons of PHP - Logger [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/logger/ -[issues]: https://github.com/SonsOfPHP/sonsofphp/issues?q=is%3Aopen+is%3Aissue+label%3ALogger -[pull-requests]: https://github.com/SonsOfPHP/sonsofphp/pulls?q=is%3Aopen+is%3Apr+label%3ALogger +[docs]: https://docs.sonsofphp.com/components/pager/ +[issues]: https://github.com/SonsOfPHP/sonsofphp/issues?q=is%3Aopen+is%3Aissue+label%3APager +[pull-requests]: https://github.com/SonsOfPHP/sonsofphp/pulls?q=is%3Aopen+is%3Apr+label%3APager diff --git a/src/SonsOfPHP/Component/Search/.gitattributes b/src/SonsOfPHP/Component/Search/.gitattributes new file mode 100644 index 00000000..84c7add0 --- /dev/null +++ b/src/SonsOfPHP/Component/Search/.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/Search/.gitignore b/src/SonsOfPHP/Component/Search/.gitignore new file mode 100644 index 00000000..5414c2c6 --- /dev/null +++ b/src/SonsOfPHP/Component/Search/.gitignore @@ -0,0 +1,3 @@ +composer.lock +phpunit.xml +vendor/ diff --git a/src/SonsOfPHP/Component/Search/Backend/MockBackend.php b/src/SonsOfPHP/Component/Search/Backend/MockBackend.php new file mode 100644 index 00000000..038b8ddb --- /dev/null +++ b/src/SonsOfPHP/Component/Search/Backend/MockBackend.php @@ -0,0 +1,34 @@ + + */ +class MockBackend implements BackendInterface +{ + public function __construct(private array $results = []) {} + + public function pushResult(mixed $result): self + { + $this->results[] = $result; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function query(QueryInterface|string $query): iterable + { + return $this->results; + } +} diff --git a/src/SonsOfPHP/Component/Search/Backend/NullBackend.php b/src/SonsOfPHP/Component/Search/Backend/NullBackend.php new file mode 100644 index 00000000..9cacbf6f --- /dev/null +++ b/src/SonsOfPHP/Component/Search/Backend/NullBackend.php @@ -0,0 +1,25 @@ + + */ +class NullBackend implements BackendInterface +{ + /** + * {@inheritdoc} + */ + public function query(QueryInterface|string $query): iterable + { + return []; + } +} diff --git a/src/SonsOfPHP/Component/Search/LICENSE b/src/SonsOfPHP/Component/Search/LICENSE new file mode 100644 index 00000000..39238382 --- /dev/null +++ b/src/SonsOfPHP/Component/Search/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/Search/Query.php b/src/SonsOfPHP/Component/Search/Query.php new file mode 100644 index 00000000..6116eea1 --- /dev/null +++ b/src/SonsOfPHP/Component/Search/Query.php @@ -0,0 +1,112 @@ + + */ +class Query implements QueryInterface, \ArrayAccess, \JsonSerializable +{ + private array $fields = [ + 'offset' => 0, + 'length' => null, + ]; + + /** + * {@inheritdoc} + */ + public function has(string $field): bool + { + return array_key_exists($field, $this->fields); + } + + /** + * {@inheritdoc} + */ + public function get(string $field): mixed + { + if (!$this->has($field)) { + return null; + } + + return $this->fields[$field]; + } + + /** + * {@inheritdoc} + */ + public function remove(string $field): self + { + if (!in_array(strtolower($field), ['offset', 'length'])) { + unset($this->fields[$field]); + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function set(string $field, mixed $value): self + { + if (0 === strcasecmp('offset', $field) || 0 === strcasecmp('length', $field)) { + if (0 === strcasecmp('offset', $field) && !is_int($value)) { + throw new \InvalidArgumentException('Offset must be integer'); + } + + if (0 === strcasecmp('length', $field) && !is_int($value) && !is_null($value)) { + throw new \InvalidArgumentException('Length must be integer or null'); + } + $field = strtolower($field); + } + + $this->fields[$field] = $value; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getOffset(): int + { + return $this->fields['offset']; + } + + /** + * {@inheritdoc} + */ + public function getLength(): ?int + { + return $this->fields['length']; + } + + public function offsetExists(mixed $offset): bool + { + return $this->has($offset); + } + + public function offsetGet(mixed $offset): mixed + { + return $this->get($offset); + } + + public function offsetSet(mixed $offset, mixed $value): void + { + $this->set($offset, $value); + } + + public function offsetUnset(mixed $offset): void + { + $this->remove($offset); + } + + public function jsonSerialize(): mixed + { + return $this->fields; + } +} diff --git a/src/SonsOfPHP/Component/Search/README.md b/src/SonsOfPHP/Component/Search/README.md new file mode 100644 index 00000000..fca76406 --- /dev/null +++ b/src/SonsOfPHP/Component/Search/README.md @@ -0,0 +1,16 @@ +Sons of PHP - Search +==================== + +## 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/search/ +[issues]: https://github.com/SonsOfPHP/sonsofphp/issues?q=is%3Aopen+is%3Aissue+label%3ASearch +[pull-requests]: https://github.com/SonsOfPHP/sonsofphp/pulls?q=is%3Aopen+is%3Apr+label%3ASearch diff --git a/src/SonsOfPHP/Component/Search/Search.php b/src/SonsOfPHP/Component/Search/Search.php new file mode 100644 index 00000000..88c4df8e --- /dev/null +++ b/src/SonsOfPHP/Component/Search/Search.php @@ -0,0 +1,32 @@ + + */ +final class Search implements SearchInterface +{ + public function __construct(private BackendInterface $backend) {} + + /** + * {@inheritdoc} + */ + public function getBackend(): BackendInterface + { + return $this->backend; + } + + /** + * {@inheritdoc} + */ + public function query(QueryInterface|string $query): iterable + { + return $this->backend->query($query); + } +} diff --git a/src/SonsOfPHP/Component/Search/Tests/QueryTest.php b/src/SonsOfPHP/Component/Search/Tests/QueryTest.php new file mode 100644 index 00000000..9c7572ea --- /dev/null +++ b/src/SonsOfPHP/Component/Search/Tests/QueryTest.php @@ -0,0 +1,199 @@ +assertInstanceOf(QueryInterface::class, $query); + } + + /** + * @covers ::getOffset + */ + public function testGetOffset(): void + { + $query = new Query(); + + $this->assertSame(0, $query->getOffset()); + $query['offset'] = 100; + $this->assertSame(100, $query->getOffset()); + } + + /** + * @covers ::getLength + */ + public function testGetLength(): void + { + $query = new Query(); + + $this->assertNull($query->getLength()); + $query['length'] = 100; + $this->assertSame(100, $query->getLength()); + } + + /** + * @covers ::has + */ + public function testHas(): void + { + $query = new Query(); + + // defaults + $this->assertTrue($query->has('offset')); + $this->assertTrue($query->has('length')); + + $this->assertFalse($query->has('testing')); + $query->set('testing', 'test'); + $this->assertTrue($query->has('testing')); + } + + /** + * @covers ::get + */ + public function testGet(): void + { + $query = new Query(); + + // defaults + $this->assertSame(0, $query->get('offset')); + $this->assertNull($query->get('length')); + + $value = 'test value'; + $this->assertSame($query, $query->set('value', $value)); + $this->assertSame($value, $query->get('value')); + } + + /** + * @covers ::get + */ + public function testGetWhenFieldDoesNotExist(): void + { + $query = new Query(); + + $this->assertNull($query->get('not a real field')); + } + + /** + * @covers ::remove + */ + public function testRemove(): void + { + $query = new Query(); + $this->assertFalse($query->has('unit.test')); + $query->set('unit.test', 'value'); + $this->assertTrue($query->has('unit.test')); + + $this->assertSame($query, $query->remove('unit.test')); + $this->assertFalse($query->has('unit.test')); + } + + /** + * @covers ::remove + */ + public function testRemoveWithFieldThatDoesNotExist(): void + { + $query = new Query(); + $this->assertFalse($query->has('unit.test')); + $this->assertSame($query, $query->remove('unit.test')); + $this->assertFalse($query->has('unit.test')); + } + + /** + * @covers ::remove + */ + public function testRemoveCannotRemoveField(): void + { + $query = new Query(); + + $this->assertTrue($query->has('offset')); + $this->assertTrue($query->has('length')); + + $this->assertSame($query, $query->remove('offset')); + $this->assertSame($query, $query->remove('length')); + + $this->assertTrue($query->has('offset')); + $this->assertTrue($query->has('length')); + } + + /** + * @covers ::set + */ + public function testItCanSetOffset(): void + { + $query = new Query(); + + $this->assertSame($query, $query->set('offset', 100)); + $this->assertSame(100, $query->get('offset')); + } + + /** + * @covers ::set + */ + public function testItCanSetLength(): void + { + $query = new Query(); + + $this->assertSame($query, $query->set('length', 100)); + $this->assertSame(100, $query->get('length')); + } + + /** + * @covers ::set + */ + public function testSet(): void + { + $query = new Query(); + + $this->assertFalse($query->has('field')); + $this->assertSame($query, $query->set('field', 'value')); + $this->assertTrue($query->has('field')); + $this->assertSame('value', $query->get('field')); + } + + /** + * @covers ::offsetExists + * @covers ::offsetGet + * @covers ::offsetSet + * @covers ::offsetUnset + */ + public function testItWorksLikeAnArray(): void + { + $query = new Query(); + + $query['field'] = 'value'; + $this->assertSame('value', $query['field']); + + $this->assertArrayHasKey('field', $query); + unset($query['field']); + $this->assertArrayNotHasKey('field', $query); + } + + /** + * @covers ::jsonSerialize + */ + public function testJsonSerialize(): void + { + $query = new Query(); + + // default + $this->assertSame('{"offset":0,"length":null}', json_encode($query)); + } +} diff --git a/src/SonsOfPHP/Component/Search/composer.json b/src/SonsOfPHP/Component/Search/composer.json new file mode 100644 index 00000000..e5cf69c7 --- /dev/null +++ b/src/SonsOfPHP/Component/Search/composer.json @@ -0,0 +1,55 @@ +{ + "name": "sonsofphp/search", + "type": "library", + "description": "", + "keywords": [ + "search" + ], + "homepage": "https://github.com/SonsOfPHP/search", + "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\\Search\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "prefer-stable": true, + "require": { + "php": ">=8.1", + "sonsofphp/pager": "0.3.x-dev", + "sonsofphp/search-contract": "0.3.x-dev" + }, + "provide": { + "sonsofphp/search-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/Search/.gitattributes b/src/SonsOfPHP/Contract/Search/.gitattributes new file mode 100644 index 00000000..3a01b372 --- /dev/null +++ b/src/SonsOfPHP/Contract/Search/.gitattributes @@ -0,0 +1,2 @@ +/.gitattributes export-ignore +/.gitignore export-ignore diff --git a/src/SonsOfPHP/Contract/Search/.gitignore b/src/SonsOfPHP/Contract/Search/.gitignore new file mode 100644 index 00000000..d8a7996a --- /dev/null +++ b/src/SonsOfPHP/Contract/Search/.gitignore @@ -0,0 +1,2 @@ +composer.lock +vendor/ diff --git a/src/SonsOfPHP/Contract/Search/BackendInterface.php b/src/SonsOfPHP/Contract/Search/BackendInterface.php new file mode 100644 index 00000000..1c04694c --- /dev/null +++ b/src/SonsOfPHP/Contract/Search/BackendInterface.php @@ -0,0 +1,22 @@ + + */ +interface BackendInterface +{ + //public function indexDocument(mixed $document): void; + //public function updateDocument(mixed $document): void; + //public function deleteDocument(mixed $document): void; + //public function getDocument(mixed $document): void; + + public function query(QueryInterface|string $query): iterable; +} diff --git a/src/SonsOfPHP/Contract/Search/LICENSE b/src/SonsOfPHP/Contract/Search/LICENSE new file mode 100644 index 00000000..39238382 --- /dev/null +++ b/src/SonsOfPHP/Contract/Search/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/Contract/Search/QueryInterface.php b/src/SonsOfPHP/Contract/Search/QueryInterface.php new file mode 100644 index 00000000..0eee3ad2 --- /dev/null +++ b/src/SonsOfPHP/Contract/Search/QueryInterface.php @@ -0,0 +1,19 @@ + + */ +interface QueryInterface// extends \ArrayAccess, \JsonSerializable +{ + public function has(string $field): bool; + public function get(string $field): mixed; + public function remove(string $field): self; + public function set(string $field, mixed $value): self; + + public function getOffset(): int; + public function getLength(): ?int; +} diff --git a/src/SonsOfPHP/Contract/Search/README.md b/src/SonsOfPHP/Contract/Search/README.md new file mode 100644 index 00000000..deaf86ae --- /dev/null +++ b/src/SonsOfPHP/Contract/Search/README.md @@ -0,0 +1,16 @@ +Sons of PHP - Search Contract +============================= + +## 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/contracts/search/ +[issues]: https://github.com/SonsOfPHP/sonsofphp/issues?q=is%3Aopen+is%3Aissue+label%3ASearch +[pull-requests]: https://github.com/SonsOfPHP/sonsofphp/pulls?q=is%3Aopen+is%3Apr+label%3ASearch diff --git a/src/SonsOfPHP/Contract/Search/SearchExceptionInterface.php b/src/SonsOfPHP/Contract/Search/SearchExceptionInterface.php new file mode 100644 index 00000000..e67efb82 --- /dev/null +++ b/src/SonsOfPHP/Contract/Search/SearchExceptionInterface.php @@ -0,0 +1,10 @@ + + */ +interface SearchExceptionInterface {} diff --git a/src/SonsOfPHP/Contract/Search/SearchInterface.php b/src/SonsOfPHP/Contract/Search/SearchInterface.php new file mode 100644 index 00000000..1bf652ba --- /dev/null +++ b/src/SonsOfPHP/Contract/Search/SearchInterface.php @@ -0,0 +1,25 @@ + + */ +interface SearchInterface +{ + /** + */ + public function getBackend(): BackendInterface; + + /** + * Takes a QueryInterface or a String + * + * If a string is passed in, it MUST be able to be converted to a QueryInterface + * + * @throws \SonsOfPHP\Contract\Search\SearchExceptionInterface + * If the $query is invalid for any reason + */ + public function query(QueryInterface|string $query): iterable; +} diff --git a/src/SonsOfPHP/Contract/Search/composer.json b/src/SonsOfPHP/Contract/Search/composer.json new file mode 100644 index 00000000..e0ecf687 --- /dev/null +++ b/src/SonsOfPHP/Contract/Search/composer.json @@ -0,0 +1,53 @@ +{ + "name": "sonsofphp/search-contract", + "type": "library", + "description": "", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "homepage": "https://github.com/SonsOfPHP/search-contract", + "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\\Contract\\Search\\": "" + } + }, + "minimum-stability": "dev", + "prefer-stable": true, + "require": { + "php": ">=8.1", + "sonsofphp/pager-contract": "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" + } + ] +}