From 8a0729469019efea716d446d12e2afcf4ed7fa17 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Fri, 26 Apr 2024 15:46:32 +0300 Subject: [PATCH 01/48] documentation WIP --- docs/book/index.md | 1 + docs/book/v4/introduction.md | 0 docs/book/v4/introduction/features.md | 0 docs/book/v4/introduction/file-structure.md | 60 +++++++++++++ docs/book/v4/introduction/getting-started.md | 5 ++ docs/book/v4/introduction/installation.md | 84 +++++++++++++++++++ docs/book/v4/introduction/packages.md | 40 +++++++++ .../v4/introduction/server-requirements.md | 38 +++++++++ docs/book/v4/tutorials.md | 0 .../tutorials/create-hello-world-handler.md | 0 10 files changed, 228 insertions(+) create mode 100644 docs/book/index.md create mode 100644 docs/book/v4/introduction.md create mode 100644 docs/book/v4/introduction/features.md create mode 100644 docs/book/v4/introduction/file-structure.md create mode 100644 docs/book/v4/introduction/getting-started.md create mode 100644 docs/book/v4/introduction/installation.md create mode 100644 docs/book/v4/introduction/packages.md create mode 100644 docs/book/v4/introduction/server-requirements.md create mode 100644 docs/book/v4/tutorials.md create mode 100644 docs/book/v4/tutorials/create-hello-world-handler.md diff --git a/docs/book/index.md b/docs/book/index.md new file mode 100644 index 0000000..4c0539a --- /dev/null +++ b/docs/book/index.md @@ -0,0 +1 @@ +../../README.md diff --git a/docs/book/v4/introduction.md b/docs/book/v4/introduction.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/book/v4/introduction/features.md b/docs/book/v4/introduction/features.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/book/v4/introduction/file-structure.md b/docs/book/v4/introduction/file-structure.md new file mode 100644 index 0000000..dfc6970 --- /dev/null +++ b/docs/book/v4/introduction/file-structure.md @@ -0,0 +1,60 @@ +## File structure + +It is a good practice to standardize the file structure of projects. This way it’s easier to keep a clean overview of multiple projects, and less time is wasted trying to find the correct class. + +When using DotKernel 3 API the following structure is recommended: + +### Main directories + +* `src` - should contain the source code files +* `templates` - should contain the page templates and layouts +* `data` - should contain project-related data (AVOID storing sensitive data on VCS) +* `docs` - should contain project-related documentation + +These directories reside in one of the following directories: + +* if the Module is a composer package where the directories above are stored in the package’s root path, eg.: `/vendor/my-name/my-project-name/` +* if the Module is an extension/component for the project, eg.: `/src/MyProjectName` + +### The `src` directory + +This directory contains all source code related to the Module. It should contain following directories, if they’re not empty: + +* Handler - Action classes (similar to Controllers but can only perform one action) +* Entity - For database entities +* Service - Service classes +* Collection - Database entities collections +* Repository - Entity repository folder + +> The above example is just some of the directories a project may include, but these should give you an idea of how the structure should look like. + +Other classes in the `src` directory may include `InputFilter`, `EventListener`, `Helper`, `Command`, `Factory` etc. + +The `src` directory should also contain 2 files: + +* `ConfigProvider.php` - Provides configuration data +* `RoutesDelegator.php` - Module main routes entry file + +### The `templates` directory + +This directory contains the template files, used for example to help render e-mail templates. + +> DotKernel3 API uses twig as Templating Engine. All template files have the extension .html.twig + +### The `data` directory + +This directory contains project-related data (such as cache, file uploads) + +We recommend using the following directory structure: + +* `data/cache` - location where caches are stored +* `data/oauth` - encryption, private and public keys needed for authentication. +* `data/lock` - folder where lock files generated by commands are stored, if enabled +* `data/doctrine/fixtures` - folder for doctrine data fixtures +* `data/doctrine/migrations` - folder for doctrine migrations + + + + + + diff --git a/docs/book/v4/introduction/getting-started.md b/docs/book/v4/introduction/getting-started.md new file mode 100644 index 0000000..b0b19c7 --- /dev/null +++ b/docs/book/v4/introduction/getting-started.md @@ -0,0 +1,5 @@ +### Clone the project +Using your terminal, navigate inside the directory you want to download the project files into. Make sure that the directory is empty before proceeding to the download process. Once there, run the following command: + + git clone https://github.com/dotkernel/api.git . + diff --git a/docs/book/v4/introduction/installation.md b/docs/book/v4/introduction/installation.md new file mode 100644 index 0000000..e2eb493 --- /dev/null +++ b/docs/book/v4/introduction/installation.md @@ -0,0 +1,84 @@ +### Install project's dependencies + + composer install + +### Development mode +If you're installing the project for development, make sure you have development mode enabled, by running: + + composer development-enable + +You can disable development mode by running: + + composer development-disable + +You can check if you have development mode enabled by running: + + composer development-status + +### Prepare config files +* duplicate `config/autoload/cors.local.php.dist` as `config/autoload/cors.local.php` <- if your API will be consumed by another application, make sure configure the `allowed_origins` +* duplicate `config/autoload/local.php.dist` as `config/autoload/local.php` +* duplicate `config/autoload/mail.local.php.dist` as `config/autoload/mail.local.php` <- if your API will send emails, make sure you fill in SMTP connection params +* **optional**: in order to run/create tests, duplicate `config/autoload/local.test.php.dist` as `config/autoload/local.test.php` <- this creates a new in-memory database that your tests will run on. + + +### Setup database + +Make sure you fill out the database credentials in `config/autoload/local.php` under `$databases['default']`. + +#### Running migrations: +* create a new MySQL database - set collation to `utf8mb4_general_ci` +* run the database migrations by using the following command: + + php vendor/bin/doctrine-migrations migrate + +This command will prompt you to confirm that you want to run it: + + WARNING! You are about to execute a migration in database "..." that could result in schema changes and data loss. Are you sure you wish to continue? (yes/no) [yes]: + +Hit `Enter` to confirm the operation. + +#### Executing fixtures: +**Fixtures are used to seed the database with initial values and should be executed after migrating the database.** + +To list all the fixtures, run: + + php bin/doctrine fixtures:list + +This will output all the fixtures in the order of execution. + +To execute all fixtures, run: + + php bin/doctrine fixtures:execute + +To execute a specific fixture, run: + + php bin/doctrine fixtures:execute --class=FixtureClassName + +More details on how fixtures work can be found here: https://github.com/dotkernel/dot-data-fixtures#creating-fixtures + +### Test the installation + + php -S 0.0.0.0:8080 -t public + +Sending a GET request to the [home page](http://localhost:8080/) should output the following message: +```json +{ + "message": "Welcome to DotKernel API!" +} +``` + +### Running tests + +The project has 2 types of tests : functional and unit tests, you can run both types at the same type by executing this command: + + php vendor/bin/phpunit + +#### Running unit tests + + vendor/bin/phpunit --testsuite=UnitTests --testdox --colors=always + +#### Running functional tests + + vendor/bin/phpunit --testsuite=FunctionalTests --testdox --colors=always + diff --git a/docs/book/v4/introduction/packages.md b/docs/book/v4/introduction/packages.md new file mode 100644 index 0000000..43fcb20 --- /dev/null +++ b/docs/book/v4/introduction/packages.md @@ -0,0 +1,40 @@ +## Packages + +* `dotkernel/dot-annotated-services` - Dependency injection component using class attributes. +* `dotkernel/dot-cache` - Cache component extending symfony-cache +* `dotkernel/dot-cli` - Component for creating console applications based on laminas-cli +* `dotkernel/dot-data-fixtures` - Provides a CLI interface for listing & executing doctrine data fixtures +* `dotkernel/dot-errorhandler` - Logging Error Handler for Middleware Applications +* `dotkernel/dot-mail` - Mail component based on laminas-mail +* `dotkernel/dot-response-header` - Middleware for setting custom response headers. +* `laminas/laminas-component-installer` - Composer plugin for injecting modules and configuration providers into application configuration +* `laminas/laminas-config` - Provides a nested object property based user interface for accessing this configuration data within application code +* `laminas/laminas-config-aggregator` - Lightweight library for collecting and merging configuration from different sources +* `laminas/laminas-http` - Provides an easy interface for performing Hyper-Text Transfer Protocol (HTTP) requests +* `laminas/laminas-hydrator` - Serialize objects to arrays, and vice versa +* `laminas/laminas-inputfilter` - Normalize and validate input sets from the web, APIs, the CLI, and more, including files +* `laminas/laminas-paginator` - Paginate collections of data from arbitrary sources +* `laminas/laminas-stdlib` - SPL extensions, array utilities, error handlers, and more +* `laminas/laminas-text` - Create FIGlets and text-based tables +* `mezzio/mezzio` - PSR-15 Middleware Microframework +* `mezzio/mezzio-authentication-oauth2` - OAuth2 (server) authentication middleware for Mezzio and PSR-7 applications +* `mezzio/mezzio-authorization-acl` - laminas-permissions-acl adapter for mezzio-authorization +* `mezzio/mezzio-authorization-rbac` - mezzio authorization rbac adapter for laminas/laminas-permissions-rbac +* `mezzio/mezzio-cors` - CORS component for Mezzio and other PSR-15 middleware runners +* `mezzio/mezzio-fastroute` - FastRoute integration for Mezzio +* `mezzio/mezzio-hal` - Hypertext Application Language implementation for PHP and PSR-7 +* `mezzio/mezzio-problem-details` - Problem Details for PSR-7 HTTP APIs addressing the RFC 7807 standard +* `mezzio/mezzio-twigrenderer` - Twig integration for Mezzio +* `ramsey/uuid-doctrine` - Use ramsey/uuid as a Doctrine field type +* `roave/psr-container-doctrine` - Doctrine Factories for PSR-11 Containers +* `symfony/filesystem` - Provides basic utilities for the filesystem + + + + + + + + + + diff --git a/docs/book/v4/introduction/server-requirements.md b/docs/book/v4/introduction/server-requirements.md new file mode 100644 index 0000000..878e9de --- /dev/null +++ b/docs/book/v4/introduction/server-requirements.md @@ -0,0 +1,38 @@ +## Server Requirements + +For production, we highly recommend a *nix based system. + +### Webserver + +* Apache >= 2.2 + * mod_rewrite + .htaccess support `(AllowOverride All)` +* Nginx + +### PHP >= 8.2 + +Both mod_php and FCGI (FPM) are supported. + +### Required Settings and Modules & Extensions + +* memory_limit >= 128M +* upload_max_filesize and post_max_size >= 100M (depending on your data) +* mbstring +* CLI SAPI (for Cron Jobs) +* Composer (added to $PATH) + +### RDBMS +* MySQL / MariaDB >= 5.5.3 + +### Recommended extensions + +* opcache +* pdo_mysql or mysqli (if using MySql or MariaDb as RDBMS) +* dom - if working with markup files structure (html, xml, etc) +* simplexml - working with xml files +* gd, exif - if working with images +* zlib, zip, bz2 - if compessing files +* curl (required if APIs are used) + + + diff --git a/docs/book/v4/tutorials.md b/docs/book/v4/tutorials.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/book/v4/tutorials/create-hello-world-handler.md b/docs/book/v4/tutorials/create-hello-world-handler.md new file mode 100644 index 0000000..e69de29 From 8885603ded7525f0e86f245c358b48d77e895a1c Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Tue, 30 Apr 2024 16:21:55 +0300 Subject: [PATCH 02/48] dk3 api documentation WIP --- docs/book/v4/introduction.md | 0 docs/book/v4/introduction/features.md | 0 docs/book/v4/introduction/introduction.md | 106 +++ docs/book/v4/tutorials.md | 0 docs/book/v4/tutorials/create-book-module.md | 636 ++++++++++++++++++ .../tutorials/create-hello-world-handler.md | 0 mkdocs.yml | 24 + 7 files changed, 766 insertions(+) delete mode 100644 docs/book/v4/introduction.md delete mode 100644 docs/book/v4/introduction/features.md create mode 100644 docs/book/v4/introduction/introduction.md delete mode 100644 docs/book/v4/tutorials.md create mode 100644 docs/book/v4/tutorials/create-book-module.md delete mode 100644 docs/book/v4/tutorials/create-hello-world-handler.md create mode 100644 mkdocs.yml diff --git a/docs/book/v4/introduction.md b/docs/book/v4/introduction.md deleted file mode 100644 index e69de29..0000000 diff --git a/docs/book/v4/introduction/features.md b/docs/book/v4/introduction/features.md deleted file mode 100644 index e69de29..0000000 diff --git a/docs/book/v4/introduction/introduction.md b/docs/book/v4/introduction/introduction.md new file mode 100644 index 0000000..d233b8d --- /dev/null +++ b/docs/book/v4/introduction/introduction.md @@ -0,0 +1,106 @@ +### Introduction + +Based on Enrico Zimuel’s Zend Expressive API – Skeleton example, DotKernel API runs on Laminas and Mezzio components and implements standards like PSR-3, PSR-4, PSR-7, PSR-11 and PSR-15. + +Here is a list of the core components: + +* Middleware Microframework (mezzio/mezzio) +* Error Handler (dotkernel/dot-errorhandler) +* Problem Details (mezzio-problem-details) +* CORS (mezzio-cors) +* Routing (mezzio/mezzio-fastroute) +* Authentication (mezzio-authentication) +* Authorization (mezzio-authorization) +* Config Aggregator (laminas/laminas-config-aggregator) +* Container (roave/psr-container-doctrine) +* Implicit Head, Options and Method Not Allowed +* Annotations (dotkernel/dot-annotated-services) +* Input Filter (laminas/laminas-inputfilter) +* Doctrine +* Hydrator (laminas/laminas-hydrator) +* Paginator (laminas/laminas-paginator) +* HAL (mezzio-hal) +* CLI (dotkernel/dot-cli) +* TwigRenderer (mezzio/mezzio-twigrenderer) +* Fixtures (dotkernel/dot-data-fixtures) +* UUID (ramsey/uuid-doctrine) + +## Doctrine 2 ORM + +For the persistence in a relational database management system we chose Doctrine ORM (object-relational mapper) . + +The benefit of Doctrine for the programmer is the ability to focus on the object-oriented business logic and worry about persistence only as a secondary priority. + +## Documentation + +Our documentation is Postman based. We use the following files in which we store information about every available endpoint ready to be tested: + + documentation/DotKernel_API.postman_collection.json + documentation/DotKernel_API.postman_environment.json + +## Hypertext Application Language + +For our API payloads ( a value object for describing the API resource, its relational links and any embedded/child resources related to it ) we chose mezzio-hal. + +## CORS + +By using `MezzioCorsMiddlewareCorsMiddleware`, the CORS preflight will be recognized and the middleware will start to detect the proper CORS configuration. The Router is used to detect every allowed request method by executing a route match with all possible request methods. Therefore, for every preflight request, there is at least one Router request. + + +## OAuth 2 + +OAuth 2 is an authorization framework that enables applications to obtain limited access to user accounts on your Dotkernel API. We are using mezzio/mezzio-authentication-oauth2 which provides OAuth2 authentication for Mezzio and PSR-7/PSR-15 applications by using league/oauth2-server package. + +## Email + +It is not unlikely for an API to send emails depending on the use case. Here is another area where Dotkernel API shines. Using `DotMailServiceMailService` provided by dotkernel/dot-mail you can easily send custom email templates. + +## Configuration + +From authorization at request route level to API keys for your application, you can find every configuration variable in the config directory. + +Registering a new module can be done by including its ConfigProvider.php in config.php. + +Brand new middlewares should go into pipeline.php. Here you can edit the order in which they run and find more info about the currently included ones. + +You can further customize your api within the autoload directory where each configuration category has its own file. + +## Routing + +Each Module has a `RoutesDelegator.php` file for managing existing routes inside that specific module. It also allows a quick way of adding new routes by providing the route path, Middlewares that the route will use and the route name. + +You can allocate permissions per route name in order to restrict access for a user role to a specific route in `config/autoload/authorization.global.php`. + +## Commands + +For registering new commands first make sure your command class extends `SymfonyComponentConsoleCommandCommand`. Then you can enable it by registering it in `config/autoload/cli.global.php`. + +## File locker + +Here you will also find our brand-new file locker configuration, so you can easily turn it on or off ( by default: `'enabled' => true` ) + +Note: The File Locker System will create a `command-{command-default-name}.lock` file which will not let another instance of the same command to run until the previous one has finished. + +## PSR Standards + +* PSR-3: Logger Interface – the application uses `LoggerInterface` for error logging +* PSR-4: Autoloader – the application locates classes using an autoloader +* PSR-7: HTTP message interfaces – the handlers return `ResponseInterface` +* PSR-11: Container interface – the application is container-based +* PSR-15: HTTP Server Request Handlers – the handlers implement `RequestHandlerInterface` + +## Tests + +One of the best ways to ensure the quality of your product is to create and run functional and unit tests. You can find factory-made tests in the tests/AppTest/ folder, and you can also register your own. + +We have 2 types of tests: functional and unit tests, you can run both types at the same type by executing this command: + + php vendor/bin/phpunit + +#### Running unit tests + + vendor/bin/phpunit --testsuite=UnitTests --testdox --colors=always + +#### Running functional tests + + vendor/bin/phpunit --testsuite=FunctionalTests --testdox --colors=always diff --git a/docs/book/v4/tutorials.md b/docs/book/v4/tutorials.md deleted file mode 100644 index e69de29..0000000 diff --git a/docs/book/v4/tutorials/create-book-module.md b/docs/book/v4/tutorials/create-book-module.md new file mode 100644 index 0000000..35c68c0 --- /dev/null +++ b/docs/book/v4/tutorials/create-book-module.md @@ -0,0 +1,636 @@ +## Implementing a book module in DotKernel 3 API + +### File structure + +The below file structure is just an example, you can have multiple components such as event listeners, wrappers, etc. + + /src/ + /Book/ + /src/ + /Collection/ + /BookCollection.php + /Entity/ + /Book.php + /Handler/ + /BookHandler.php + /Repository/ + /BookRepository.php + /Service/ + /BookService.php + /InputFilter/ + /Input/ + /NameInput.php + /AuthorInput.php + /ReleaseDateInput.php + /BookInputFilter.php + ConfigProvider.php + RoutesDelegator.php + + +* `src/Book/src/Collection/BookCollection.php` - a collection refers to a container for a group of related objects, typically used to manage sets of related entities fetched from a database +* `src/Book/src/Entity/Book.php` - an entity refers to a PHP class that represents a persistent object or data structure +* `src/Book/src/Handler/BookHandler.php` - handlers are middleware that can handle requests based on an action +* `src/Book/src/Repository/BookRepository.php` - a repository is a class responsible for querying and retrieving entities from the database +* `src/Book/src/Service/BookService.php` - is a class or component responsible for performing a specific task or providing functionality to other parts of the application +* `src/Book/src/ConfigProvider.php` - is a class that provides configuration for various aspects of the framework or application +* `src/Book/src/RoutesDelegator.php` - a routes delegator is a delegator factory responsible for configuring routing middleware based on routing configuration provided by the application +* `src/Book/src/InputFilter/BookInputFilter.php` - input filters and validators +* `src/Book/src/InputFilter/Input/*` - input filters and validator configurations + +### File creation and contents + +* `src/Book/src/Collection/BookCollection.php` + +```php +setName($name); + $this->setAuthor($author); + $this->setReleaseDate($releaseDate); + } + + public function getName(): string + { + return $this->name; + } + + public function setName(string $name): self + { + $this->name = $name; + + return $this; + } + + public function getAuthor(): string + { + return $this->author; + } + + public function setAuthor(string $author): self + { + $this->author = $author; + + return $this; + } + + public function getReleaseDate(): DateTimeImmutable + { + return $this->releaseDate; + } + + public function setReleaseDate(DateTimeImmutable $releaseDate): self + { + $this->releaseDate = $releaseDate; + + return $this; + } + + public function getArrayCopy(): array + { + return [ + 'uuid' => $this->getUuid()->toString(), + 'name' => $this->getName(), + 'author' => $this->getAuthor(), + 'releaseDate' => $this->getReleaseDate(), + ]; + } +} +``` + +* `src/Book/src/Repository/BookRepository.php` + +```php + + */ +class BookRepository extends EntityRepository +{ + public function saveBook(Book $book): Book + { + $this->getEntityManager()->persist($book); + $this->getEntityManager()->flush(); + + return $book; + } + + public function getBooks(array $filters = []): BookCollection + { + $page = PaginationHelper::getOffsetAndLimit($filters); + + $qb = $this + ->getEntityManager() + ->createQueryBuilder() + ->select('book') + ->from(Book::class, 'book') + ->orderBy($filters['order'] ?? 'book.created', $filters['dir'] ?? 'desc') + ->setFirstResult($page['offset']) + ->setMaxResults($page['limit']); + + $qb->getQuery()->useQueryCache(true); + + return new BookCollection($qb, false); + } +} +``` +* `src/Book/src/Service/BookService.php` + +```php +bookRepository->saveBook($book); + } + + public function getBooks(array $filters = []) + { + return $this->bookRepository->getBooks($filters); + } +} +``` + +* `src/Book/src/Service/BookServiceInterface.php` + +```php + $this->getDependencies(), + MetadataMap::class => $this->getHalConfig(), + ]; + } + + public function getDependencies(): array + { + return [ + 'factories' => [ + BookHandler::class => AnnotatedServiceFactory::class, + BookService::class => AnnotatedServiceFactory::class, + BookRepository::class => AnnotatedRepositoryFactory::class, + ], + 'aliases' => [ + BookServiceInterface::class => BookService::class, + ], + ]; + } + + public function getHalConfig(): array + { + return [ + AppConfigProvider::getCollection(BookCollection::class, 'books.list', 'books'), + AppConfigProvider::getResource(Book::class, 'book.create'), + ]; + } +} +``` + +* `src/Book/src/RoutesDelegator.php` + +```php +get( + '/books', + BookHandler::class, + 'books.list' + ); + + $app->post( + '/book', + BookHandler::class, + 'book.create' + ); + + return $app; + } +} +``` + +* `src/Book/src/InputFilter/BookInputFilter.php` + + +```php +add(new NameInput('name')); + $this->add(new AuthorInput('author')); + $this->add(new ReleaseDateInput('releaseDate')); + } +} +``` + +* `src/Book/src/InputFilter/Input/AuthorInput.php` + +```php +setRequired($isRequired); + + $this->getFilterChain() + ->attachByName(StringTrim::class) + ->attachByName(StripTags::class); + + $this->getValidatorChain() + ->attachByName(NotEmpty::class, [ + 'message' => sprintf(Message::VALIDATOR_REQUIRED_FIELD_BY_NAME, 'author'), + ], true); + } +} +``` + +* `src/Book/src/InputFilter/Input/NameInput.php` + +```php +setRequired($isRequired); + + $this->getFilterChain() + ->attachByName(StringTrim::class) + ->attachByName(StripTags::class); + + $this->getValidatorChain() + ->attachByName(NotEmpty::class, [ + 'message' => sprintf(Message::VALIDATOR_REQUIRED_FIELD_BY_NAME, 'name'), + ], true); + } +} +``` + +* `src/Book/src/InputFilter/Input/ReleaseDateInput.php` + +```php +setRequired($isRequired); + + $this->getFilterChain() + ->attachByName(StringTrim::class) + ->attachByName(StripTags::class); + + $this->getValidatorChain() + ->attachByName(Date::class, [ + 'message' => sprintf(Message::INVALID_VALUE, 'releaseDate'), + ], true); + } +} +``` + +* `src/Book/src/Handler/BookHandler.php` + +```php +bookService->getBooks($request->getQueryParams()); + + return $this->createResponse($request, $books); + } + + public function post(ServerRequestInterface $request): ResponseInterface + { + $inputFilter = (new BookInputFilter())->setData($request->getParsedBody()); + if (! $inputFilter->isValid()) { + return $this->errorResponse($inputFilter->getMessages()); + } + + $book = $this->bookService->createBook($inputFilter->getValues()); + + return $this->createResponse($request, $book); + } +} +``` + +### Configuring and registering the new module + +Once you set up all the files as in the example above, you will need to do a few additional configurations: + +* Register the namespace by adding this line `"Api\\Book\\": "src/Book/src/",` in `composer.json` under the `autoload.psr-4` key. +* Register the module by adding `Api\Book\ConfigProvider::class,` under `Api\User\ConfigProvider::class,`. +* Register the module's routes by adding `\Api\Book\RoutesDelegator::class,` under `\Api\User\RoutesDelegator::class,` in `src/App/src/ConfigProvider.php`. + +It should look like this: + +```php +public function getDependencies(): array +{ + return [ + 'delegators' => [ + Application::class => [ + RoutesDelegator::class, + \Api\Admin\RoutesDelegator::class, + \Api\User\RoutesDelegator::class, + \Api\Book\RoutesDelegator::class, + ], + ], + 'factories' => [ + ... + ] + ... +``` + +* In `src/config/autoload/doctrine.global.php` add under the `doctrine.driver` key: + * ```php + 'BookEntities' => [ + 'class' => AttributeDriver::class, + 'cache' => 'array', + 'paths' => __DIR__ . '/../../src/Book/src/Entity', + ], + ``` + add this under the `doctrine.driver` key: + * ``'Api\\Book\Entity' => 'BookEntities',`` add this under the `doctrine.driver.drivers` class + +Example: + +```php + [ + ... + 'driver' => [ + 'orm_default' => [ + 'class' => MappingDriverChain::class, + 'drivers' => [ + 'Api\\App\Entity' => 'AppEntities', + 'Api\\Admin\\Entity' => 'AdminEntities', + 'Api\\User\\Entity' => 'UserEntities', + 'Api\\Book\Entity' => 'BookEntities', + ], + ], + 'AdminEntities' => [ + 'class' => AttributeDriver::class, + 'cache' => 'array', + 'paths' => __DIR__ . '/../../src/Admin/src/Entity', + ], + 'UserEntities' => [ + 'class' => AttributeDriver::class, + 'cache' => 'array', + 'paths' => __DIR__ . '/../../src/User/src/Entity', + ], + 'AppEntities' => [ + 'class' => AttributeDriver::class, + 'cache' => 'array', + 'paths' => __DIR__ . '/../../src/App/src/Entity', + ], + 'BookEntities' => [ + 'class' => AttributeDriver::class, + 'cache' => 'array', + 'paths' => __DIR__ . '/../../src/Book/src/Entity', + ], + ], + ... +``` + +Next we need to configure access to the newly created endpoints, add `books.list` and `book.create` to the authorization rbac array, under the `UserRole::ROLE_GUEST` key. +> Make sure you read and understand the rbac documentation. + +### Migrations + +We created the `Book` entity, but we didn't create the associated table for it. + +Doctrine can handle the table creation, run the following command: + + vendor/bin/doctrine-migrations diff --filter-expression='/^(?!oauth_)/' + +This will check for differences between your entities and database structure and create migration files if necessary, in `data/doctrine/migrations`. + +To execute the migrations run: + + vendor/bin/doctrine-migrations migrate + +### Checking endpoints + +If we did everything as planned we can call the `http://localhost/books` endpoint and create a new book: + + curl -X POST http://localhost/book + -H "Content-Type: application/json" + -d '{"name": "test", "author": "author name", "releaseDate": "2023-03-03"}' + +To list the books use : + + curl http://localhost/books \ No newline at end of file diff --git a/docs/book/v4/tutorials/create-hello-world-handler.md b/docs/book/v4/tutorials/create-hello-world-handler.md deleted file mode 100644 index e69de29..0000000 diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..ffed7a7 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,24 @@ +docs_dir: docs/book +site_dir: docs/html +extra: + project: DotKernel 3 API + current_version: v4 + versions: + - v4 +nav: + - Home: index.md + - v4: + - Introduction: + - "Introduction": v4/introduction/introduction.md + - "Getting Started": v4/introduction/getting-started.md + - "Server Requirements": v4/introduction/server-requirements.md + - "File Structure": v4/introduction/file-structure.md + - "Installation": v4/introduction/installation.md + - "Packages": v4/introduction/packages.md + - Tutorials: + - "Creating a book module": v4/tutorials/create-book-module.md +site_name: api +site_description: "DotKernel 3 API" +repo_url: "https://github.com/dotkernel/api" +plugins: + - search \ No newline at end of file From 350bacff9295964afc176a34654bffd9bb05fb7b Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Tue, 30 Apr 2024 16:23:15 +0300 Subject: [PATCH 03/48] dk3 api documentation WIP --- .github/workflows/docs-build.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/docs-build.yml diff --git a/.github/workflows/docs-build.yml b/.github/workflows/docs-build.yml new file mode 100644 index 0000000..bd2b91d --- /dev/null +++ b/.github/workflows/docs-build.yml @@ -0,0 +1,17 @@ +name: docs-build + +on: + push: + release: + types: [published] + workflow_dispatch: + +jobs: + build-deploy: + runs-on: ubuntu-latest + steps: + - name: Build Docs + uses: dotkernel/documentation-theme/github-actions/docs@dev + env: + DEPLOY_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From fa416ea094fac0d587fc9d0d058782f5685fba88 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Tue, 30 Apr 2024 16:28:39 +0300 Subject: [PATCH 04/48] dk3 api documentation WIP --- .github/workflows/docs-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs-build.yml b/.github/workflows/docs-build.yml index bd2b91d..414625a 100644 --- a/.github/workflows/docs-build.yml +++ b/.github/workflows/docs-build.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Build Docs - uses: dotkernel/documentation-theme/github-actions/docs@dev + uses: dotkernel/documentation-theme/github-actions/docs@main env: DEPLOY_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From 026ce0c2d663edf0adc097bedf5afb73b3686989 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Tue, 30 Apr 2024 16:36:31 +0300 Subject: [PATCH 05/48] dk3 api documentation WIP --- .github/workflows/continuous-integration.yml | 11 ++++ .github/workflows/cs-tests.yml | 47 ----------------- .github/workflows/docs-build.yml | 1 - .github/workflows/run-tests.yml | 55 -------------------- .github/workflows/static-analysis.yml | 47 ----------------- 5 files changed, 11 insertions(+), 150 deletions(-) create mode 100644 .github/workflows/continuous-integration.yml delete mode 100644 .github/workflows/cs-tests.yml delete mode 100644 .github/workflows/run-tests.yml delete mode 100644 .github/workflows/static-analysis.yml diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml new file mode 100644 index 0000000..eb6fdf1 --- /dev/null +++ b/.github/workflows/continuous-integration.yml @@ -0,0 +1,11 @@ +name: "Continuous Integration" + +on: + pull_request: + push: + branches: + tags: + +jobs: + ci: + uses: laminas/workflow-continuous-integration/.github/workflows/continuous-integration.yml@1.x \ No newline at end of file diff --git a/.github/workflows/cs-tests.yml b/.github/workflows/cs-tests.yml deleted file mode 100644 index ccd3f74..0000000 --- a/.github/workflows/cs-tests.yml +++ /dev/null @@ -1,47 +0,0 @@ -on: - - push - -name: Run phpcs checks - -jobs: - mutation: - name: PHP ${{ matrix.php }}-${{ matrix.os }} - - runs-on: ${{ matrix.os }} - - strategy: - matrix: - os: - - ubuntu-latest - - php: - - "8.2" - - "8.3" - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: "${{ matrix.php }}" - tools: composer:v2, cs2pr - coverage: none - - - name: Determine composer cache directory - run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV - - - name: Cache dependencies installed with composer - uses: actions/cache@v3 - with: - path: ${{ env.COMPOSER_CACHE_DIR }} - key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: | - php${{ matrix.php }}-composer- - - - name: Install dependencies with composer - run: composer install --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi - - - name: Run phpcs checks - run: vendor/bin/phpcs diff --git a/.github/workflows/docs-build.yml b/.github/workflows/docs-build.yml index 414625a..f9be9e2 100644 --- a/.github/workflows/docs-build.yml +++ b/.github/workflows/docs-build.yml @@ -1,7 +1,6 @@ name: docs-build on: - push: release: types: [published] workflow_dispatch: diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml deleted file mode 100644 index 7db2f86..0000000 --- a/.github/workflows/run-tests.yml +++ /dev/null @@ -1,55 +0,0 @@ -on: - - push - -name: Run PHPUnit tests - -jobs: - mutation: - name: PHP ${{ matrix.php }}-${{ matrix.os }} - - runs-on: ${{ matrix.os }} - - strategy: - matrix: - os: - - ubuntu-latest - - php: - - "8.2" - - "8.3" - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: "${{ matrix.php }}" - tools: composer:v2, cs2pr - coverage: none - - - name: Determine composer cache directory - run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV - - - name: Cache dependencies installed with composer - uses: actions/cache@v3 - with: - path: ${{ env.COMPOSER_CACHE_DIR }} - key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: | - php${{ matrix.php }}-composer- - - - name: Install dependencies with composer - run: composer install --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi - - - name: Setup project - run: | - mv config/autoload/local.php.dist config/autoload/local.php - mv config/autoload/mail.local.php.dist config/autoload/mail.local.php - mv config/autoload/local.test.php.dist config/autoload/local.test.php - - - name: Run unit tests - run: vendor/bin/phpunit --testsuite=UnitTests --testdox --colors=always - - name: Run functional tests - run: vendor/bin/phpunit --testsuite=FunctionalTests --testdox --colors=always diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml deleted file mode 100644 index 8d7d667..0000000 --- a/.github/workflows/static-analysis.yml +++ /dev/null @@ -1,47 +0,0 @@ -on: - - push - -name: Run static analysis - -jobs: - mutation: - name: PHP ${{ matrix.php }}-${{ matrix.os }} - - runs-on: ${{ matrix.os }} - - strategy: - matrix: - os: - - ubuntu-latest - - php: - - "8.2" - - "8.3" - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: "${{ matrix.php }}" - tools: composer:v2, cs2pr - coverage: none - - - name: Determine composer cache directory - run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV - - - name: Cache dependencies installed with composer - uses: actions/cache@v3 - with: - path: ${{ env.COMPOSER_CACHE_DIR }} - key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: | - php${{ matrix.php }}-composer- - - - name: Install dependencies with composer - run: composer install --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi - - - name: Static analysis - run: vendor/bin/psalm --output-format=github --show-info=false --threads=4 --php-version="${{ matrix.php }}" From 167b206930d152d610f1fa1abcf86b2d6ccac982 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Wed, 1 May 2024 17:53:17 +0300 Subject: [PATCH 06/48] documentation linting fix --- docs/book/index.md | 2 +- docs/book/v4/introduction/file-structure.md | 114 +- docs/book/v4/introduction/getting-started.md | 10 +- docs/book/v4/introduction/installation.md | 173 +-- docs/book/v4/introduction/introduction.md | 212 +-- docs/book/v4/introduction/packages.md | 70 +- .../v4/introduction/server-requirements.md | 73 +- docs/book/v4/tutorials/create-book-module.md | 1270 ++++++++--------- mkdocs.yml | 48 +- 9 files changed, 979 insertions(+), 993 deletions(-) diff --git a/docs/book/index.md b/docs/book/index.md index 4c0539a..ae42a26 100644 --- a/docs/book/index.md +++ b/docs/book/index.md @@ -1 +1 @@ -../../README.md +../../README.md diff --git a/docs/book/v4/introduction/file-structure.md b/docs/book/v4/introduction/file-structure.md index dfc6970..0283758 100644 --- a/docs/book/v4/introduction/file-structure.md +++ b/docs/book/v4/introduction/file-structure.md @@ -1,60 +1,54 @@ -## File structure - -It is a good practice to standardize the file structure of projects. This way it’s easier to keep a clean overview of multiple projects, and less time is wasted trying to find the correct class. - -When using DotKernel 3 API the following structure is recommended: - -### Main directories - -* `src` - should contain the source code files -* `templates` - should contain the page templates and layouts -* `data` - should contain project-related data (AVOID storing sensitive data on VCS) -* `docs` - should contain project-related documentation - -These directories reside in one of the following directories: - -* if the Module is a composer package where the directories above are stored in the package’s root path, eg.: `/vendor/my-name/my-project-name/` -* if the Module is an extension/component for the project, eg.: `/src/MyProjectName` - -### The `src` directory - -This directory contains all source code related to the Module. It should contain following directories, if they’re not empty: - -* Handler - Action classes (similar to Controllers but can only perform one action) -* Entity - For database entities -* Service - Service classes -* Collection - Database entities collections -* Repository - Entity repository folder - -> The above example is just some of the directories a project may include, but these should give you an idea of how the structure should look like. - -Other classes in the `src` directory may include `InputFilter`, `EventListener`, `Helper`, `Command`, `Factory` etc. - -The `src` directory should also contain 2 files: - -* `ConfigProvider.php` - Provides configuration data -* `RoutesDelegator.php` - Module main routes entry file - -### The `templates` directory - -This directory contains the template files, used for example to help render e-mail templates. - -> DotKernel3 API uses twig as Templating Engine. All template files have the extension .html.twig - -### The `data` directory - -This directory contains project-related data (such as cache, file uploads) - -We recommend using the following directory structure: - -* `data/cache` - location where caches are stored -* `data/oauth` - encryption, private and public keys needed for authentication. -* `data/lock` - folder where lock files generated by commands are stored, if enabled -* `data/doctrine/fixtures` - folder for doctrine data fixtures -* `data/doctrine/migrations` - folder for doctrine migrations - - - - - - +# File structure + +It is a good practice to standardize the file structure of projects. This way it’s easier to keep a clean overview of multiple projects, and less time is wasted trying to find the correct class. + +When using DotKernel 3 API the following structure is recommended: + +## Main directories + +* `src` - should contain the source code files +* `templates` - should contain the page templates and layouts +* `data` - should contain project-related data (AVOID storing sensitive data on VCS) +* `docs` - should contain project-related documentation + +These directories reside in one of the following directories: + +* if the Module is a composer package where the directories above are stored in the package’s root path, eg.: `/vendor/my-name/my-project-name/` +* if the Module is an extension/component for the project, eg.: `/src/MyProjectName` + +## The `src` directory + +This directory contains all source code related to the Module. It should contain following directories, if they’re not empty: + +* Handler - Action classes (similar to Controllers but can only perform one action) +* Entity - For database entities +* Service - Service classes +* Collection - Database entities collections +* Repository - Entity repository folder + +> The above example is just some of the directories a project may include, but these should give you an idea of how the structure should look like. + +Other classes in the `src` directory may include `InputFilter`, `EventListener`, `Helper`, `Command`, `Factory` etc. + +The `src` directory should also contain 2 files: + +* `ConfigProvider.php` - Provides configuration data +* `RoutesDelegator.php` - Module main routes entry file + +## The `templates` directory + +This directory contains the template files, used for example to help render e-mail templates. + +> DotKernel3 API uses twig as Templating Engine. All template files have the extension .html.twig + +## The `data` directory + +This directory contains project-related data (such as cache, file uploads) + +We recommend using the following directory structure: + +* `data/cache` - location where caches are stored +* `data/oauth` - encryption, private and public keys needed for authentication. +* `data/lock` - folder where lock files generated by commands are stored, if enabled +* `data/doctrine/fixtures` - folder for doctrine data fixtures +* `data/doctrine/migrations` - folder for doctrine migrations diff --git a/docs/book/v4/introduction/getting-started.md b/docs/book/v4/introduction/getting-started.md index b0b19c7..db745aa 100644 --- a/docs/book/v4/introduction/getting-started.md +++ b/docs/book/v4/introduction/getting-started.md @@ -1,5 +1,5 @@ -### Clone the project -Using your terminal, navigate inside the directory you want to download the project files into. Make sure that the directory is empty before proceeding to the download process. Once there, run the following command: - - git clone https://github.com/dotkernel/api.git . - +# Clone the project + +Using your terminal, navigate inside the directory you want to download the project files into. Make sure that the directory is empty before proceeding to the download process. Once there, run the following command: + + git clone https://github.com/dotkernel/api.git . diff --git a/docs/book/v4/introduction/installation.md b/docs/book/v4/introduction/installation.md index e2eb493..b68b173 100644 --- a/docs/book/v4/introduction/installation.md +++ b/docs/book/v4/introduction/installation.md @@ -1,84 +1,89 @@ -### Install project's dependencies - - composer install - -### Development mode -If you're installing the project for development, make sure you have development mode enabled, by running: - - composer development-enable - -You can disable development mode by running: - - composer development-disable - -You can check if you have development mode enabled by running: - - composer development-status - -### Prepare config files -* duplicate `config/autoload/cors.local.php.dist` as `config/autoload/cors.local.php` <- if your API will be consumed by another application, make sure configure the `allowed_origins` -* duplicate `config/autoload/local.php.dist` as `config/autoload/local.php` -* duplicate `config/autoload/mail.local.php.dist` as `config/autoload/mail.local.php` <- if your API will send emails, make sure you fill in SMTP connection params -* **optional**: in order to run/create tests, duplicate `config/autoload/local.test.php.dist` as `config/autoload/local.test.php` <- this creates a new in-memory database that your tests will run on. - - -### Setup database - -Make sure you fill out the database credentials in `config/autoload/local.php` under `$databases['default']`. - -#### Running migrations: -* create a new MySQL database - set collation to `utf8mb4_general_ci` -* run the database migrations by using the following command: - - php vendor/bin/doctrine-migrations migrate - -This command will prompt you to confirm that you want to run it: - - WARNING! You are about to execute a migration in database "..." that could result in schema changes and data loss. Are you sure you wish to continue? (yes/no) [yes]: - -Hit `Enter` to confirm the operation. - -#### Executing fixtures: -**Fixtures are used to seed the database with initial values and should be executed after migrating the database.** - -To list all the fixtures, run: - - php bin/doctrine fixtures:list - -This will output all the fixtures in the order of execution. - -To execute all fixtures, run: - - php bin/doctrine fixtures:execute - -To execute a specific fixture, run: - - php bin/doctrine fixtures:execute --class=FixtureClassName - -More details on how fixtures work can be found here: https://github.com/dotkernel/dot-data-fixtures#creating-fixtures - -### Test the installation - - php -S 0.0.0.0:8080 -t public - -Sending a GET request to the [home page](http://localhost:8080/) should output the following message: -```json -{ - "message": "Welcome to DotKernel API!" -} -``` - -### Running tests - -The project has 2 types of tests : functional and unit tests, you can run both types at the same type by executing this command: - - php vendor/bin/phpunit - -#### Running unit tests - - vendor/bin/phpunit --testsuite=UnitTests --testdox --colors=always - -#### Running functional tests - - vendor/bin/phpunit --testsuite=FunctionalTests --testdox --colors=always - +# Installation + +## Install dependencies + + composer install + +## Development mode + +If you're installing the project for development, make sure you have development mode enabled, by running: + + composer development-enable + +You can disable development mode by running: + + composer development-disable + +You can check if you have development mode enabled by running: + + composer development-status + +## Prepare config files + +* duplicate `config/autoload/cors.local.php.dist` as `config/autoload/cors.local.php` <- if your API will be consumed by another application, make sure configure the `allowed_origins` +* duplicate `config/autoload/local.php.dist` as `config/autoload/local.php` +* duplicate `config/autoload/mail.local.php.dist` as `config/autoload/mail.local.php` <- if your API will send emails, make sure you fill in SMTP connection params +* **optional**: in order to run/create tests, duplicate `config/autoload/local.test.php.dist` as `config/autoload/local.test.php` <- this creates a new in-memory database that your tests will run on. + + +## Setup database + +Make sure you fill out the database credentials in `config/autoload/local.php` under `$databases['default']`. + +## Running migrations: + +* create a new MySQL database - set collation to `utf8mb4_general_ci` +* run the database migrations by using the following command: + + php vendor/bin/doctrine-migrations migrate + +This command will prompt you to confirm that you want to run it. + + WARNING! You are about to execute a migration in database "..." that could result in schema changes and data loss. Are you sure you wish to continue? (yes/no) [yes]: + +Hit `Enter` to confirm the operation. + +## Executing fixtures: + +**Fixtures are used to seed the database with initial values and should be executed after migrating the database.** + +To list all the fixtures, run: + + php bin/doctrine fixtures:list + +This will output all the fixtures in the order of execution. + +To execute all fixtures, run: + + php bin/doctrine fixtures:execute + +To execute a specific fixture, run: + + php bin/doctrine fixtures:execute --class=FixtureClassName + +More details on how fixtures work can be found here: https://github.com/dotkernel/dot-data-fixtures#creating-fixtures + +## Test the installation + + php -S 0.0.0.0:8080 -t public + +Sending a GET request to the [home page](http://localhost:8080/) should output the following message: +```json +{ + "message": "Welcome to DotKernel API!" +} +``` + +## Running tests + +The project has 2 types of tests : functional and unit tests, you can run both types at the same type by executing this command: + + php vendor/bin/phpunit + +## Running unit tests + + vendor/bin/phpunit --testsuite=UnitTests --testdox --colors=always + +## Running functional tests + + vendor/bin/phpunit --testsuite=FunctionalTests --testdox --colors=always diff --git a/docs/book/v4/introduction/introduction.md b/docs/book/v4/introduction/introduction.md index d233b8d..df9e203 100644 --- a/docs/book/v4/introduction/introduction.md +++ b/docs/book/v4/introduction/introduction.md @@ -1,106 +1,106 @@ -### Introduction - -Based on Enrico Zimuel’s Zend Expressive API – Skeleton example, DotKernel API runs on Laminas and Mezzio components and implements standards like PSR-3, PSR-4, PSR-7, PSR-11 and PSR-15. - -Here is a list of the core components: - -* Middleware Microframework (mezzio/mezzio) -* Error Handler (dotkernel/dot-errorhandler) -* Problem Details (mezzio-problem-details) -* CORS (mezzio-cors) -* Routing (mezzio/mezzio-fastroute) -* Authentication (mezzio-authentication) -* Authorization (mezzio-authorization) -* Config Aggregator (laminas/laminas-config-aggregator) -* Container (roave/psr-container-doctrine) -* Implicit Head, Options and Method Not Allowed -* Annotations (dotkernel/dot-annotated-services) -* Input Filter (laminas/laminas-inputfilter) -* Doctrine -* Hydrator (laminas/laminas-hydrator) -* Paginator (laminas/laminas-paginator) -* HAL (mezzio-hal) -* CLI (dotkernel/dot-cli) -* TwigRenderer (mezzio/mezzio-twigrenderer) -* Fixtures (dotkernel/dot-data-fixtures) -* UUID (ramsey/uuid-doctrine) - -## Doctrine 2 ORM - -For the persistence in a relational database management system we chose Doctrine ORM (object-relational mapper) . - -The benefit of Doctrine for the programmer is the ability to focus on the object-oriented business logic and worry about persistence only as a secondary priority. - -## Documentation - -Our documentation is Postman based. We use the following files in which we store information about every available endpoint ready to be tested: - - documentation/DotKernel_API.postman_collection.json - documentation/DotKernel_API.postman_environment.json - -## Hypertext Application Language - -For our API payloads ( a value object for describing the API resource, its relational links and any embedded/child resources related to it ) we chose mezzio-hal. - -## CORS - -By using `MezzioCorsMiddlewareCorsMiddleware`, the CORS preflight will be recognized and the middleware will start to detect the proper CORS configuration. The Router is used to detect every allowed request method by executing a route match with all possible request methods. Therefore, for every preflight request, there is at least one Router request. - - -## OAuth 2 - -OAuth 2 is an authorization framework that enables applications to obtain limited access to user accounts on your Dotkernel API. We are using mezzio/mezzio-authentication-oauth2 which provides OAuth2 authentication for Mezzio and PSR-7/PSR-15 applications by using league/oauth2-server package. - -## Email - -It is not unlikely for an API to send emails depending on the use case. Here is another area where Dotkernel API shines. Using `DotMailServiceMailService` provided by dotkernel/dot-mail you can easily send custom email templates. - -## Configuration - -From authorization at request route level to API keys for your application, you can find every configuration variable in the config directory. - -Registering a new module can be done by including its ConfigProvider.php in config.php. - -Brand new middlewares should go into pipeline.php. Here you can edit the order in which they run and find more info about the currently included ones. - -You can further customize your api within the autoload directory where each configuration category has its own file. - -## Routing - -Each Module has a `RoutesDelegator.php` file for managing existing routes inside that specific module. It also allows a quick way of adding new routes by providing the route path, Middlewares that the route will use and the route name. - -You can allocate permissions per route name in order to restrict access for a user role to a specific route in `config/autoload/authorization.global.php`. - -## Commands - -For registering new commands first make sure your command class extends `SymfonyComponentConsoleCommandCommand`. Then you can enable it by registering it in `config/autoload/cli.global.php`. - -## File locker - -Here you will also find our brand-new file locker configuration, so you can easily turn it on or off ( by default: `'enabled' => true` ) - -Note: The File Locker System will create a `command-{command-default-name}.lock` file which will not let another instance of the same command to run until the previous one has finished. - -## PSR Standards - -* PSR-3: Logger Interface – the application uses `LoggerInterface` for error logging -* PSR-4: Autoloader – the application locates classes using an autoloader -* PSR-7: HTTP message interfaces – the handlers return `ResponseInterface` -* PSR-11: Container interface – the application is container-based -* PSR-15: HTTP Server Request Handlers – the handlers implement `RequestHandlerInterface` - -## Tests - -One of the best ways to ensure the quality of your product is to create and run functional and unit tests. You can find factory-made tests in the tests/AppTest/ folder, and you can also register your own. - -We have 2 types of tests: functional and unit tests, you can run both types at the same type by executing this command: - - php vendor/bin/phpunit - -#### Running unit tests - - vendor/bin/phpunit --testsuite=UnitTests --testdox --colors=always - -#### Running functional tests - - vendor/bin/phpunit --testsuite=FunctionalTests --testdox --colors=always +# Introduction + +Based on Enrico Zimuel’s Zend Expressive API – Skeleton example, DotKernel API runs on Laminas and Mezzio components and implements standards like PSR-3, PSR-4, PSR-7, PSR-11 and PSR-15. + +Here is a list of the core components: + +* Middleware Microframework (mezzio/mezzio) +* Error Handler (dotkernel/dot-errorhandler) +* Problem Details (mezzio-problem-details) +* CORS (mezzio-cors) +* Routing (mezzio/mezzio-fastroute) +* Authentication (mezzio-authentication) +* Authorization (mezzio-authorization) +* Config Aggregator (laminas/laminas-config-aggregator) +* Container (roave/psr-container-doctrine) +* Implicit Head, Options and Method Not Allowed +* Annotations (dotkernel/dot-annotated-services) +* Input Filter (laminas/laminas-inputfilter) +* Doctrine +* Hydrator (laminas/laminas-hydrator) +* Paginator (laminas/laminas-paginator) +* HAL (mezzio-hal) +* CLI (dotkernel/dot-cli) +* TwigRenderer (mezzio/mezzio-twigrenderer) +* Fixtures (dotkernel/dot-data-fixtures) +* UUID (ramsey/uuid-doctrine) + +## Doctrine 2 ORM + +For the persistence in a relational database management system we chose Doctrine ORM (object-relational mapper) . + +The benefit of Doctrine for the programmer is the ability to focus on the object-oriented business logic and worry about persistence only as a secondary priority. + +## Documentation + +Our documentation is Postman based. We use the following files in which we store information about every available endpoint ready to be tested: + + documentation/DotKernel_API.postman_collection.json + documentation/DotKernel_API.postman_environment.json + +## Hypertext Application Language + +For our API payloads ( a value object for describing the API resource, its relational links and any embedded/child resources related to it ) we chose mezzio-hal. + +## CORS + +By using `MezzioCorsMiddlewareCorsMiddleware`, the CORS preflight will be recognized and the middleware will start to detect the proper CORS configuration. The Router is used to detect every allowed request method by executing a route match with all possible request methods. Therefore, for every preflight request, there is at least one Router request. + + +## OAuth 2 + +OAuth 2 is an authorization framework that enables applications to obtain limited access to user accounts on your Dotkernel API. We are using mezzio/mezzio-authentication-oauth2 which provides OAuth2 authentication for Mezzio and PSR-7/PSR-15 applications by using league/oauth2-server package. + +## Email + +It is not unlikely for an API to send emails depending on the use case. Here is another area where Dotkernel API shines. Using `DotMailServiceMailService` provided by dotkernel/dot-mail you can easily send custom email templates. + +## Configuration + +From authorization at request route level to API keys for your application, you can find every configuration variable in the config directory. + +Registering a new module can be done by including its ConfigProvider.php in config.php. + +Brand new middlewares should go into pipeline.php. Here you can edit the order in which they run and find more info about the currently included ones. + +You can further customize your api within the autoload directory where each configuration category has its own file. + +## Routing + +Each Module has a `RoutesDelegator.php` file for managing existing routes inside that specific module. It also allows a quick way of adding new routes by providing the route path, Middlewares that the route will use and the route name. + +You can allocate permissions per route name in order to restrict access for a user role to a specific route in `config/autoload/authorization.global.php`. + +## Commands + +For registering new commands first make sure your command class extends `SymfonyComponentConsoleCommandCommand`. Then you can enable it by registering it in `config/autoload/cli.global.php`. + +## File locker + +Here you will also find our brand-new file locker configuration, so you can easily turn it on or off ( by default: `'enabled' => true` ) + +Note: The File Locker System will create a `command-{command-default-name}.lock` file which will not let another instance of the same command to run until the previous one has finished. + +## PSR Standards + +* PSR-3: Logger Interface – the application uses `LoggerInterface` for error logging +* PSR-4: Autoloader – the application locates classes using an autoloader +* PSR-7: HTTP message interfaces – the handlers return `ResponseInterface` +* PSR-11: Container interface – the application is container-based +* PSR-15: HTTP Server Request Handlers – the handlers implement `RequestHandlerInterface` + +## Tests + +One of the best ways to ensure the quality of your product is to create and run functional and unit tests. You can find factory-made tests in the tests/AppTest/ folder, and you can also register your own. + +We have 2 types of tests: functional and unit tests, you can run both types at the same type by executing this command: + + php vendor/bin/phpunit + +## Running unit tests + + vendor/bin/phpunit --testsuite=UnitTests --testdox --colors=always + +## Running functional tests + + vendor/bin/phpunit --testsuite=FunctionalTests --testdox --colors=always diff --git a/docs/book/v4/introduction/packages.md b/docs/book/v4/introduction/packages.md index 43fcb20..d64ca86 100644 --- a/docs/book/v4/introduction/packages.md +++ b/docs/book/v4/introduction/packages.md @@ -1,40 +1,30 @@ -## Packages - -* `dotkernel/dot-annotated-services` - Dependency injection component using class attributes. -* `dotkernel/dot-cache` - Cache component extending symfony-cache -* `dotkernel/dot-cli` - Component for creating console applications based on laminas-cli -* `dotkernel/dot-data-fixtures` - Provides a CLI interface for listing & executing doctrine data fixtures -* `dotkernel/dot-errorhandler` - Logging Error Handler for Middleware Applications -* `dotkernel/dot-mail` - Mail component based on laminas-mail -* `dotkernel/dot-response-header` - Middleware for setting custom response headers. -* `laminas/laminas-component-installer` - Composer plugin for injecting modules and configuration providers into application configuration -* `laminas/laminas-config` - Provides a nested object property based user interface for accessing this configuration data within application code -* `laminas/laminas-config-aggregator` - Lightweight library for collecting and merging configuration from different sources -* `laminas/laminas-http` - Provides an easy interface for performing Hyper-Text Transfer Protocol (HTTP) requests -* `laminas/laminas-hydrator` - Serialize objects to arrays, and vice versa -* `laminas/laminas-inputfilter` - Normalize and validate input sets from the web, APIs, the CLI, and more, including files -* `laminas/laminas-paginator` - Paginate collections of data from arbitrary sources -* `laminas/laminas-stdlib` - SPL extensions, array utilities, error handlers, and more -* `laminas/laminas-text` - Create FIGlets and text-based tables -* `mezzio/mezzio` - PSR-15 Middleware Microframework -* `mezzio/mezzio-authentication-oauth2` - OAuth2 (server) authentication middleware for Mezzio and PSR-7 applications -* `mezzio/mezzio-authorization-acl` - laminas-permissions-acl adapter for mezzio-authorization -* `mezzio/mezzio-authorization-rbac` - mezzio authorization rbac adapter for laminas/laminas-permissions-rbac -* `mezzio/mezzio-cors` - CORS component for Mezzio and other PSR-15 middleware runners -* `mezzio/mezzio-fastroute` - FastRoute integration for Mezzio -* `mezzio/mezzio-hal` - Hypertext Application Language implementation for PHP and PSR-7 -* `mezzio/mezzio-problem-details` - Problem Details for PSR-7 HTTP APIs addressing the RFC 7807 standard -* `mezzio/mezzio-twigrenderer` - Twig integration for Mezzio -* `ramsey/uuid-doctrine` - Use ramsey/uuid as a Doctrine field type -* `roave/psr-container-doctrine` - Doctrine Factories for PSR-11 Containers -* `symfony/filesystem` - Provides basic utilities for the filesystem - - - - - - - - - - +# Packages + +* `dotkernel/dot-annotated-services` - Dependency injection component using class attributes. +* `dotkernel/dot-cache` - Cache component extending symfony-cache +* `dotkernel/dot-cli` - Component for creating console applications based on laminas-cli +* `dotkernel/dot-data-fixtures` - Provides a CLI interface for listing & executing doctrine data fixtures +* `dotkernel/dot-errorhandler` - Logging Error Handler for Middleware Applications +* `dotkernel/dot-mail` - Mail component based on laminas-mail +* `dotkernel/dot-response-header` - Middleware for setting custom response headers. +* `laminas/laminas-component-installer` - Composer plugin for injecting modules and configuration providers into application configuration +* `laminas/laminas-config` - Provides a nested object property based user interface for accessing this configuration data within application code +* `laminas/laminas-config-aggregator` - Lightweight library for collecting and merging configuration from different sources +* `laminas/laminas-http` - Provides an easy interface for performing Hyper-Text Transfer Protocol (HTTP) requests +* `laminas/laminas-hydrator` - Serialize objects to arrays, and vice versa +* `laminas/laminas-inputfilter` - Normalize and validate input sets from the web, APIs, the CLI, and more, including files +* `laminas/laminas-paginator` - Paginate collections of data from arbitrary sources +* `laminas/laminas-stdlib` - SPL extensions, array utilities, error handlers, and more +* `laminas/laminas-text` - Create FIGlets and text-based tables +* `mezzio/mezzio` - PSR-15 Middleware Microframework +* `mezzio/mezzio-authentication-oauth2` - OAuth2 (server) authentication middleware for Mezzio and PSR-7 applications +* `mezzio/mezzio-authorization-acl` - laminas-permissions-acl adapter for mezzio-authorization +* `mezzio/mezzio-authorization-rbac` - mezzio authorization rbac adapter for laminas/laminas-permissions-rbac +* `mezzio/mezzio-cors` - CORS component for Mezzio and other PSR-15 middleware runners +* `mezzio/mezzio-fastroute` - FastRoute integration for Mezzio +* `mezzio/mezzio-hal` - Hypertext Application Language implementation for PHP and PSR-7 +* `mezzio/mezzio-problem-details` - Problem Details for PSR-7 HTTP APIs addressing the RFC 7807 standard +* `mezzio/mezzio-twigrenderer` - Twig integration for Mezzio +* `ramsey/uuid-doctrine` - Use ramsey/uuid as a Doctrine field type +* `roave/psr-container-doctrine` - Doctrine Factories for PSR-11 Containers +* `symfony/filesystem` - Provides basic utilities for the filesystem diff --git a/docs/book/v4/introduction/server-requirements.md b/docs/book/v4/introduction/server-requirements.md index 878e9de..f359b5f 100644 --- a/docs/book/v4/introduction/server-requirements.md +++ b/docs/book/v4/introduction/server-requirements.md @@ -1,38 +1,35 @@ -## Server Requirements - -For production, we highly recommend a *nix based system. - -### Webserver - -* Apache >= 2.2 - * mod_rewrite - .htaccess support `(AllowOverride All)` -* Nginx - -### PHP >= 8.2 - -Both mod_php and FCGI (FPM) are supported. - -### Required Settings and Modules & Extensions - -* memory_limit >= 128M -* upload_max_filesize and post_max_size >= 100M (depending on your data) -* mbstring -* CLI SAPI (for Cron Jobs) -* Composer (added to $PATH) - -### RDBMS -* MySQL / MariaDB >= 5.5.3 - -### Recommended extensions - -* opcache -* pdo_mysql or mysqli (if using MySql or MariaDb as RDBMS) -* dom - if working with markup files structure (html, xml, etc) -* simplexml - working with xml files -* gd, exif - if working with images -* zlib, zip, bz2 - if compessing files -* curl (required if APIs are used) - - - +# Server Requirements + +For production, we highly recommend a *nix based system. + +## Webserver + +* Apache >= 2.2 + * mod_rewrite + .htaccess support `(AllowOverride All)` +* Nginx + +## PHP >= 8.2 + +Both mod_php and FCGI (FPM) are supported. + +## Required Settings and Modules & Extensions + +* memory_limit >= 128M +* upload_max_filesize and post_max_size >= 100M (depending on your data) +* mbstring +* CLI SAPI (for Cron Jobs) +* Composer (added to $PATH) + +## RDBMS +* MySQL / MariaDB >= 5.5.3 + +## Recommended extensions + +* opcache +* pdo_mysql or mysqli (if using MySql or MariaDb as RDBMS) +* dom - if working with markup files structure (html, xml, etc) +* simplexml - working with xml files +* gd, exif - if working with images +* zlib, zip, bz2 - if compessing files +* curl (required if APIs are used) diff --git a/docs/book/v4/tutorials/create-book-module.md b/docs/book/v4/tutorials/create-book-module.md index 35c68c0..9712700 100644 --- a/docs/book/v4/tutorials/create-book-module.md +++ b/docs/book/v4/tutorials/create-book-module.md @@ -1,636 +1,636 @@ -## Implementing a book module in DotKernel 3 API - -### File structure - -The below file structure is just an example, you can have multiple components such as event listeners, wrappers, etc. - - /src/ - /Book/ - /src/ - /Collection/ - /BookCollection.php - /Entity/ - /Book.php - /Handler/ - /BookHandler.php - /Repository/ - /BookRepository.php - /Service/ - /BookService.php - /InputFilter/ - /Input/ - /NameInput.php - /AuthorInput.php - /ReleaseDateInput.php - /BookInputFilter.php - ConfigProvider.php - RoutesDelegator.php - - -* `src/Book/src/Collection/BookCollection.php` - a collection refers to a container for a group of related objects, typically used to manage sets of related entities fetched from a database -* `src/Book/src/Entity/Book.php` - an entity refers to a PHP class that represents a persistent object or data structure -* `src/Book/src/Handler/BookHandler.php` - handlers are middleware that can handle requests based on an action -* `src/Book/src/Repository/BookRepository.php` - a repository is a class responsible for querying and retrieving entities from the database -* `src/Book/src/Service/BookService.php` - is a class or component responsible for performing a specific task or providing functionality to other parts of the application -* `src/Book/src/ConfigProvider.php` - is a class that provides configuration for various aspects of the framework or application -* `src/Book/src/RoutesDelegator.php` - a routes delegator is a delegator factory responsible for configuring routing middleware based on routing configuration provided by the application -* `src/Book/src/InputFilter/BookInputFilter.php` - input filters and validators -* `src/Book/src/InputFilter/Input/*` - input filters and validator configurations - -### File creation and contents - -* `src/Book/src/Collection/BookCollection.php` - -```php -setName($name); - $this->setAuthor($author); - $this->setReleaseDate($releaseDate); - } - - public function getName(): string - { - return $this->name; - } - - public function setName(string $name): self - { - $this->name = $name; - - return $this; - } - - public function getAuthor(): string - { - return $this->author; - } - - public function setAuthor(string $author): self - { - $this->author = $author; - - return $this; - } - - public function getReleaseDate(): DateTimeImmutable - { - return $this->releaseDate; - } - - public function setReleaseDate(DateTimeImmutable $releaseDate): self - { - $this->releaseDate = $releaseDate; - - return $this; - } - - public function getArrayCopy(): array - { - return [ - 'uuid' => $this->getUuid()->toString(), - 'name' => $this->getName(), - 'author' => $this->getAuthor(), - 'releaseDate' => $this->getReleaseDate(), - ]; - } -} -``` - -* `src/Book/src/Repository/BookRepository.php` - -```php - - */ -class BookRepository extends EntityRepository -{ - public function saveBook(Book $book): Book - { - $this->getEntityManager()->persist($book); - $this->getEntityManager()->flush(); - - return $book; - } - - public function getBooks(array $filters = []): BookCollection - { - $page = PaginationHelper::getOffsetAndLimit($filters); - - $qb = $this - ->getEntityManager() - ->createQueryBuilder() - ->select('book') - ->from(Book::class, 'book') - ->orderBy($filters['order'] ?? 'book.created', $filters['dir'] ?? 'desc') - ->setFirstResult($page['offset']) - ->setMaxResults($page['limit']); - - $qb->getQuery()->useQueryCache(true); - - return new BookCollection($qb, false); - } -} -``` -* `src/Book/src/Service/BookService.php` - -```php -bookRepository->saveBook($book); - } - - public function getBooks(array $filters = []) - { - return $this->bookRepository->getBooks($filters); - } -} -``` - -* `src/Book/src/Service/BookServiceInterface.php` - -```php - $this->getDependencies(), - MetadataMap::class => $this->getHalConfig(), - ]; - } - - public function getDependencies(): array - { - return [ - 'factories' => [ - BookHandler::class => AnnotatedServiceFactory::class, - BookService::class => AnnotatedServiceFactory::class, - BookRepository::class => AnnotatedRepositoryFactory::class, - ], - 'aliases' => [ - BookServiceInterface::class => BookService::class, - ], - ]; - } - - public function getHalConfig(): array - { - return [ - AppConfigProvider::getCollection(BookCollection::class, 'books.list', 'books'), - AppConfigProvider::getResource(Book::class, 'book.create'), - ]; - } -} -``` - -* `src/Book/src/RoutesDelegator.php` - -```php -get( - '/books', - BookHandler::class, - 'books.list' - ); - - $app->post( - '/book', - BookHandler::class, - 'book.create' - ); - - return $app; - } -} -``` - -* `src/Book/src/InputFilter/BookInputFilter.php` - - -```php -add(new NameInput('name')); - $this->add(new AuthorInput('author')); - $this->add(new ReleaseDateInput('releaseDate')); - } -} -``` - -* `src/Book/src/InputFilter/Input/AuthorInput.php` - -```php -setRequired($isRequired); - - $this->getFilterChain() - ->attachByName(StringTrim::class) - ->attachByName(StripTags::class); - - $this->getValidatorChain() - ->attachByName(NotEmpty::class, [ - 'message' => sprintf(Message::VALIDATOR_REQUIRED_FIELD_BY_NAME, 'author'), - ], true); - } -} -``` - -* `src/Book/src/InputFilter/Input/NameInput.php` - -```php -setRequired($isRequired); - - $this->getFilterChain() - ->attachByName(StringTrim::class) - ->attachByName(StripTags::class); - - $this->getValidatorChain() - ->attachByName(NotEmpty::class, [ - 'message' => sprintf(Message::VALIDATOR_REQUIRED_FIELD_BY_NAME, 'name'), - ], true); - } -} -``` - -* `src/Book/src/InputFilter/Input/ReleaseDateInput.php` - -```php -setRequired($isRequired); - - $this->getFilterChain() - ->attachByName(StringTrim::class) - ->attachByName(StripTags::class); - - $this->getValidatorChain() - ->attachByName(Date::class, [ - 'message' => sprintf(Message::INVALID_VALUE, 'releaseDate'), - ], true); - } -} -``` - -* `src/Book/src/Handler/BookHandler.php` - -```php -bookService->getBooks($request->getQueryParams()); - - return $this->createResponse($request, $books); - } - - public function post(ServerRequestInterface $request): ResponseInterface - { - $inputFilter = (new BookInputFilter())->setData($request->getParsedBody()); - if (! $inputFilter->isValid()) { - return $this->errorResponse($inputFilter->getMessages()); - } - - $book = $this->bookService->createBook($inputFilter->getValues()); - - return $this->createResponse($request, $book); - } -} -``` - -### Configuring and registering the new module - -Once you set up all the files as in the example above, you will need to do a few additional configurations: - -* Register the namespace by adding this line `"Api\\Book\\": "src/Book/src/",` in `composer.json` under the `autoload.psr-4` key. -* Register the module by adding `Api\Book\ConfigProvider::class,` under `Api\User\ConfigProvider::class,`. -* Register the module's routes by adding `\Api\Book\RoutesDelegator::class,` under `\Api\User\RoutesDelegator::class,` in `src/App/src/ConfigProvider.php`. - -It should look like this: - -```php -public function getDependencies(): array -{ - return [ - 'delegators' => [ - Application::class => [ - RoutesDelegator::class, - \Api\Admin\RoutesDelegator::class, - \Api\User\RoutesDelegator::class, - \Api\Book\RoutesDelegator::class, - ], - ], - 'factories' => [ - ... - ] - ... -``` - -* In `src/config/autoload/doctrine.global.php` add under the `doctrine.driver` key: - * ```php - 'BookEntities' => [ - 'class' => AttributeDriver::class, - 'cache' => 'array', - 'paths' => __DIR__ . '/../../src/Book/src/Entity', - ], - ``` - add this under the `doctrine.driver` key: - * ``'Api\\Book\Entity' => 'BookEntities',`` add this under the `doctrine.driver.drivers` class - -Example: - -```php - [ - ... - 'driver' => [ - 'orm_default' => [ - 'class' => MappingDriverChain::class, - 'drivers' => [ - 'Api\\App\Entity' => 'AppEntities', - 'Api\\Admin\\Entity' => 'AdminEntities', - 'Api\\User\\Entity' => 'UserEntities', - 'Api\\Book\Entity' => 'BookEntities', - ], - ], - 'AdminEntities' => [ - 'class' => AttributeDriver::class, - 'cache' => 'array', - 'paths' => __DIR__ . '/../../src/Admin/src/Entity', - ], - 'UserEntities' => [ - 'class' => AttributeDriver::class, - 'cache' => 'array', - 'paths' => __DIR__ . '/../../src/User/src/Entity', - ], - 'AppEntities' => [ - 'class' => AttributeDriver::class, - 'cache' => 'array', - 'paths' => __DIR__ . '/../../src/App/src/Entity', - ], - 'BookEntities' => [ - 'class' => AttributeDriver::class, - 'cache' => 'array', - 'paths' => __DIR__ . '/../../src/Book/src/Entity', - ], - ], - ... -``` - -Next we need to configure access to the newly created endpoints, add `books.list` and `book.create` to the authorization rbac array, under the `UserRole::ROLE_GUEST` key. -> Make sure you read and understand the rbac documentation. - -### Migrations - -We created the `Book` entity, but we didn't create the associated table for it. - -Doctrine can handle the table creation, run the following command: - - vendor/bin/doctrine-migrations diff --filter-expression='/^(?!oauth_)/' - -This will check for differences between your entities and database structure and create migration files if necessary, in `data/doctrine/migrations`. - -To execute the migrations run: - - vendor/bin/doctrine-migrations migrate - -### Checking endpoints - -If we did everything as planned we can call the `http://localhost/books` endpoint and create a new book: - - curl -X POST http://localhost/book - -H "Content-Type: application/json" - -d '{"name": "test", "author": "author name", "releaseDate": "2023-03-03"}' - -To list the books use : - +## Implementing a book module in DotKernel 3 API + +### File structure + +The below file structure is just an example, you can have multiple components such as event listeners, wrappers, etc. + + /src/ + /Book/ + /src/ + /Collection/ + /BookCollection.php + /Entity/ + /Book.php + /Handler/ + /BookHandler.php + /Repository/ + /BookRepository.php + /Service/ + /BookService.php + /InputFilter/ + /Input/ + /NameInput.php + /AuthorInput.php + /ReleaseDateInput.php + /BookInputFilter.php + ConfigProvider.php + RoutesDelegator.php + + +* `src/Book/src/Collection/BookCollection.php` - a collection refers to a container for a group of related objects, typically used to manage sets of related entities fetched from a database +* `src/Book/src/Entity/Book.php` - an entity refers to a PHP class that represents a persistent object or data structure +* `src/Book/src/Handler/BookHandler.php` - handlers are middleware that can handle requests based on an action +* `src/Book/src/Repository/BookRepository.php` - a repository is a class responsible for querying and retrieving entities from the database +* `src/Book/src/Service/BookService.php` - is a class or component responsible for performing a specific task or providing functionality to other parts of the application +* `src/Book/src/ConfigProvider.php` - is a class that provides configuration for various aspects of the framework or application +* `src/Book/src/RoutesDelegator.php` - a routes delegator is a delegator factory responsible for configuring routing middleware based on routing configuration provided by the application +* `src/Book/src/InputFilter/BookInputFilter.php` - input filters and validators +* `src/Book/src/InputFilter/Input/*` - input filters and validator configurations + +### File creation and contents + +* `src/Book/src/Collection/BookCollection.php` + +```php +setName($name); + $this->setAuthor($author); + $this->setReleaseDate($releaseDate); + } + + public function getName(): string + { + return $this->name; + } + + public function setName(string $name): self + { + $this->name = $name; + + return $this; + } + + public function getAuthor(): string + { + return $this->author; + } + + public function setAuthor(string $author): self + { + $this->author = $author; + + return $this; + } + + public function getReleaseDate(): DateTimeImmutable + { + return $this->releaseDate; + } + + public function setReleaseDate(DateTimeImmutable $releaseDate): self + { + $this->releaseDate = $releaseDate; + + return $this; + } + + public function getArrayCopy(): array + { + return [ + 'uuid' => $this->getUuid()->toString(), + 'name' => $this->getName(), + 'author' => $this->getAuthor(), + 'releaseDate' => $this->getReleaseDate(), + ]; + } +} +``` + +* `src/Book/src/Repository/BookRepository.php` + +```php + + */ +class BookRepository extends EntityRepository +{ + public function saveBook(Book $book): Book + { + $this->getEntityManager()->persist($book); + $this->getEntityManager()->flush(); + + return $book; + } + + public function getBooks(array $filters = []): BookCollection + { + $page = PaginationHelper::getOffsetAndLimit($filters); + + $qb = $this + ->getEntityManager() + ->createQueryBuilder() + ->select('book') + ->from(Book::class, 'book') + ->orderBy($filters['order'] ?? 'book.created', $filters['dir'] ?? 'desc') + ->setFirstResult($page['offset']) + ->setMaxResults($page['limit']); + + $qb->getQuery()->useQueryCache(true); + + return new BookCollection($qb, false); + } +} +``` +* `src/Book/src/Service/BookService.php` + +```php +bookRepository->saveBook($book); + } + + public function getBooks(array $filters = []) + { + return $this->bookRepository->getBooks($filters); + } +} +``` + +* `src/Book/src/Service/BookServiceInterface.php` + +```php + $this->getDependencies(), + MetadataMap::class => $this->getHalConfig(), + ]; + } + + public function getDependencies(): array + { + return [ + 'factories' => [ + BookHandler::class => AnnotatedServiceFactory::class, + BookService::class => AnnotatedServiceFactory::class, + BookRepository::class => AnnotatedRepositoryFactory::class, + ], + 'aliases' => [ + BookServiceInterface::class => BookService::class, + ], + ]; + } + + public function getHalConfig(): array + { + return [ + AppConfigProvider::getCollection(BookCollection::class, 'books.list', 'books'), + AppConfigProvider::getResource(Book::class, 'book.create'), + ]; + } +} +``` + +* `src/Book/src/RoutesDelegator.php` + +```php +get( + '/books', + BookHandler::class, + 'books.list' + ); + + $app->post( + '/book', + BookHandler::class, + 'book.create' + ); + + return $app; + } +} +``` + +* `src/Book/src/InputFilter/BookInputFilter.php` + + +```php +add(new NameInput('name')); + $this->add(new AuthorInput('author')); + $this->add(new ReleaseDateInput('releaseDate')); + } +} +``` + +* `src/Book/src/InputFilter/Input/AuthorInput.php` + +```php +setRequired($isRequired); + + $this->getFilterChain() + ->attachByName(StringTrim::class) + ->attachByName(StripTags::class); + + $this->getValidatorChain() + ->attachByName(NotEmpty::class, [ + 'message' => sprintf(Message::VALIDATOR_REQUIRED_FIELD_BY_NAME, 'author'), + ], true); + } +} +``` + +* `src/Book/src/InputFilter/Input/NameInput.php` + +```php +setRequired($isRequired); + + $this->getFilterChain() + ->attachByName(StringTrim::class) + ->attachByName(StripTags::class); + + $this->getValidatorChain() + ->attachByName(NotEmpty::class, [ + 'message' => sprintf(Message::VALIDATOR_REQUIRED_FIELD_BY_NAME, 'name'), + ], true); + } +} +``` + +* `src/Book/src/InputFilter/Input/ReleaseDateInput.php` + +```php +setRequired($isRequired); + + $this->getFilterChain() + ->attachByName(StringTrim::class) + ->attachByName(StripTags::class); + + $this->getValidatorChain() + ->attachByName(Date::class, [ + 'message' => sprintf(Message::INVALID_VALUE, 'releaseDate'), + ], true); + } +} +``` + +* `src/Book/src/Handler/BookHandler.php` + +```php +bookService->getBooks($request->getQueryParams()); + + return $this->createResponse($request, $books); + } + + public function post(ServerRequestInterface $request): ResponseInterface + { + $inputFilter = (new BookInputFilter())->setData($request->getParsedBody()); + if (! $inputFilter->isValid()) { + return $this->errorResponse($inputFilter->getMessages()); + } + + $book = $this->bookService->createBook($inputFilter->getValues()); + + return $this->createResponse($request, $book); + } +} +``` + +### Configuring and registering the new module + +Once you set up all the files as in the example above, you will need to do a few additional configurations: + +* Register the namespace by adding this line `"Api\\Book\\": "src/Book/src/",` in `composer.json` under the `autoload.psr-4` key. +* Register the module by adding `Api\Book\ConfigProvider::class,` under `Api\User\ConfigProvider::class,`. +* Register the module's routes by adding `\Api\Book\RoutesDelegator::class,` under `\Api\User\RoutesDelegator::class,` in `src/App/src/ConfigProvider.php`. + +It should look like this: + +```php +public function getDependencies(): array +{ + return [ + 'delegators' => [ + Application::class => [ + RoutesDelegator::class, + \Api\Admin\RoutesDelegator::class, + \Api\User\RoutesDelegator::class, + \Api\Book\RoutesDelegator::class, + ], + ], + 'factories' => [ + ... + ] + ... +``` + +* In `src/config/autoload/doctrine.global.php` add under the `doctrine.driver` key: + * ```php + 'BookEntities' => [ + 'class' => AttributeDriver::class, + 'cache' => 'array', + 'paths' => __DIR__ . '/../../src/Book/src/Entity', + ], + ``` + add this under the `doctrine.driver` key: + * ``'Api\\Book\Entity' => 'BookEntities',`` add this under the `doctrine.driver.drivers` class + +Example: + +```php + [ + ... + 'driver' => [ + 'orm_default' => [ + 'class' => MappingDriverChain::class, + 'drivers' => [ + 'Api\\App\Entity' => 'AppEntities', + 'Api\\Admin\\Entity' => 'AdminEntities', + 'Api\\User\\Entity' => 'UserEntities', + 'Api\\Book\Entity' => 'BookEntities', + ], + ], + 'AdminEntities' => [ + 'class' => AttributeDriver::class, + 'cache' => 'array', + 'paths' => __DIR__ . '/../../src/Admin/src/Entity', + ], + 'UserEntities' => [ + 'class' => AttributeDriver::class, + 'cache' => 'array', + 'paths' => __DIR__ . '/../../src/User/src/Entity', + ], + 'AppEntities' => [ + 'class' => AttributeDriver::class, + 'cache' => 'array', + 'paths' => __DIR__ . '/../../src/App/src/Entity', + ], + 'BookEntities' => [ + 'class' => AttributeDriver::class, + 'cache' => 'array', + 'paths' => __DIR__ . '/../../src/Book/src/Entity', + ], + ], + ... +``` + +Next we need to configure access to the newly created endpoints, add `books.list` and `book.create` to the authorization rbac array, under the `UserRole::ROLE_GUEST` key. +> Make sure you read and understand the rbac documentation. + +### Migrations + +We created the `Book` entity, but we didn't create the associated table for it. + +Doctrine can handle the table creation, run the following command: + + vendor/bin/doctrine-migrations diff --filter-expression='/^(?!oauth_)/' + +This will check for differences between your entities and database structure and create migration files if necessary, in `data/doctrine/migrations`. + +To execute the migrations run: + + vendor/bin/doctrine-migrations migrate + +### Checking endpoints + +If we did everything as planned we can call the `http://localhost/books` endpoint and create a new book: + + curl -X POST http://localhost/book + -H "Content-Type: application/json" + -d '{"name": "test", "author": "author name", "releaseDate": "2023-03-03"}' + +To list the books use : + curl http://localhost/books \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index ffed7a7..9b5d8f1 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,24 +1,24 @@ -docs_dir: docs/book -site_dir: docs/html -extra: - project: DotKernel 3 API - current_version: v4 - versions: - - v4 -nav: - - Home: index.md - - v4: - - Introduction: - - "Introduction": v4/introduction/introduction.md - - "Getting Started": v4/introduction/getting-started.md - - "Server Requirements": v4/introduction/server-requirements.md - - "File Structure": v4/introduction/file-structure.md - - "Installation": v4/introduction/installation.md - - "Packages": v4/introduction/packages.md - - Tutorials: - - "Creating a book module": v4/tutorials/create-book-module.md -site_name: api -site_description: "DotKernel 3 API" -repo_url: "https://github.com/dotkernel/api" -plugins: - - search \ No newline at end of file +docs_dir: docs/book +site_dir: docs/html +extra: + project: DotKernel 3 API + current_version: v4 + versions: + - v4 +nav: + - Home: index.md + - v4: + - Introduction: + - "Introduction": v4/introduction/introduction.md + - "Getting Started": v4/introduction/getting-started.md + - "Server Requirements": v4/introduction/server-requirements.md + - "File Structure": v4/introduction/file-structure.md + - "Installation": v4/introduction/installation.md + - "Packages": v4/introduction/packages.md + - Tutorials: + - "Creating a book module": v4/tutorials/create-book-module.md +site_name: api +site_description: "DotKernel 3 API" +repo_url: "https://github.com/dotkernel/api" +plugins: + - search From 1e82853562f24b4e0622267e3fb9fc73afec7aef Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Wed, 1 May 2024 18:10:30 +0300 Subject: [PATCH 07/48] documentation linting fix --- .github/workflows/continuous-integration.yml | 20 +- .github/workflows/docs-build.yml | 30 +-- README.md | 22 +- docs/book/v4/introduction/installation.md | 6 +- .../v4/introduction/server-requirements.md | 5 +- docs/book/v4/tutorials/create-book-module.md | 199 +++++++++--------- 6 files changed, 141 insertions(+), 141 deletions(-) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index eb6fdf1..2f02e70 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -1,11 +1,11 @@ -name: "Continuous Integration" - -on: - pull_request: - push: - branches: - tags: - -jobs: - ci: +name: "Continuous Integration" + +on: + pull_request: + push: + branches: + tags: + +jobs: + ci: uses: laminas/workflow-continuous-integration/.github/workflows/continuous-integration.yml@1.x \ No newline at end of file diff --git a/.github/workflows/docs-build.yml b/.github/workflows/docs-build.yml index f9be9e2..164e3d2 100644 --- a/.github/workflows/docs-build.yml +++ b/.github/workflows/docs-build.yml @@ -1,16 +1,16 @@ -name: docs-build - -on: - release: - types: [published] - workflow_dispatch: - -jobs: - build-deploy: - runs-on: ubuntu-latest - steps: - - name: Build Docs - uses: dotkernel/documentation-theme/github-actions/docs@main - env: - DEPLOY_TOKEN: ${{ secrets.GITHUB_TOKEN }} +name: docs-build + +on: + release: + types: [published] + workflow_dispatch: + +jobs: + build-deploy: + runs-on: ubuntu-latest + steps: + - name: Build Docs + uses: dotkernel/documentation-theme/github-actions/docs@main + env: + DEPLOY_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/README.md b/README.md index 7cca000..95caff7 100644 --- a/README.md +++ b/README.md @@ -16,21 +16,20 @@ Based on Enrico Zimuel's [Zend Expressive API - Skeleton example](https://github [![SymfonyInsight](https://insight.symfony.com/projects/7f9143cc-5e3c-4cfc-992c-377a001fde3e/big.svg)](https://insight.symfony.com/projects/7f9143cc-5e3c-4cfc-992c-377a001fde3e) - ## Getting Started -### Step 1: Clone the project +## Step 1: Clone the project + Using your terminal, navigate inside the directory you want to download the project files into. Make sure that the directory is empty before proceeding to the download process. Once there, run the following command: git clone https://github.com/dotkernel/api.git . - -### Step 2: Install project's dependencies +## Step 2: Install project's dependencies composer install +## Step 3: Development mode -### Step 3: Development mode If you're installing the project for development, make sure you have development mode enabled, by running: composer development-enable @@ -43,22 +42,21 @@ You can check if you have development mode enabled by running: composer development-status +## Step 4: Prepare config files -### Step 4: Prepare config files * duplicate `config/autoload/cors.local.php.dist` as `config/autoload/cors.local.php` <- if your API will be consumed by another application, make sure configure the `allowed_origins` * duplicate `config/autoload/local.php.dist` as `config/autoload/local.php` * duplicate `config/autoload/mail.local.php.dist` as `config/autoload/mail.local.php` <- if your API will send emails, make sure you fill in SMTP connection params * **optional**: in order to run/create tests, duplicate `config/autoload/local.test.php.dist` as `config/autoload/local.test.php` <- this creates a new in-memory database that your tests will run on +## Step 5: Setup database -### Step 5: Setup database +## Running migrations: -#### Running migrations: * create a new MySQL database - set collation to `utf8mb4_general_ci` * fill out the database connection params in `config/autoload/local.php` under `$databases['default']` * run the database migrations by using the following command: - php vendor/bin/doctrine-migrations migrate This command will prompt you to confirm that you want to run it: @@ -67,7 +65,8 @@ This command will prompt you to confirm that you want to run it: Hit `Enter` to confirm the operation. -#### Executing fixtures: +## Executing fixtures: + **Fixtures are used to seed the database with initial values and should be executed after migrating the database.** To list all the fixtures, run: @@ -86,7 +85,7 @@ To execute a specific fixture, run: More details on how fixtures work can be found here: https://github.com/dotkernel/dot-data-fixtures#creating-fixtures -### Step 6: Test the installation +## Step 6: Test the installation php -S 0.0.0.0:8080 -t public @@ -97,7 +96,6 @@ Sending a GET request to the [home page](http://localhost:8080/) should output t } ``` - ## Documentation In order to access DotKernel API documentation, check the provided [readme file](documentation/README.md). diff --git a/docs/book/v4/introduction/installation.md b/docs/book/v4/introduction/installation.md index b68b173..4acd049 100644 --- a/docs/book/v4/introduction/installation.md +++ b/docs/book/v4/introduction/installation.md @@ -25,12 +25,11 @@ You can check if you have development mode enabled by running: * duplicate `config/autoload/mail.local.php.dist` as `config/autoload/mail.local.php` <- if your API will send emails, make sure you fill in SMTP connection params * **optional**: in order to run/create tests, duplicate `config/autoload/local.test.php.dist` as `config/autoload/local.test.php` <- this creates a new in-memory database that your tests will run on. - ## Setup database Make sure you fill out the database credentials in `config/autoload/local.php` under `$databases['default']`. -## Running migrations: +## Running migrations * create a new MySQL database - set collation to `utf8mb4_general_ci` * run the database migrations by using the following command: @@ -43,7 +42,7 @@ This command will prompt you to confirm that you want to run it. Hit `Enter` to confirm the operation. -## Executing fixtures: +## Executing fixtures **Fixtures are used to seed the database with initial values and should be executed after migrating the database.** @@ -68,6 +67,7 @@ More details on how fixtures work can be found here: https://github.com/dotkerne php -S 0.0.0.0:8080 -t public Sending a GET request to the [home page](http://localhost:8080/) should output the following message: + ```json { "message": "Welcome to DotKernel API!" diff --git a/docs/book/v4/introduction/server-requirements.md b/docs/book/v4/introduction/server-requirements.md index f359b5f..d8a1336 100644 --- a/docs/book/v4/introduction/server-requirements.md +++ b/docs/book/v4/introduction/server-requirements.md @@ -5,8 +5,8 @@ For production, we highly recommend a *nix based system. ## Webserver * Apache >= 2.2 - * mod_rewrite - .htaccess support `(AllowOverride All)` +* mod_rewrite + * .htaccess support `(AllowOverride All)` * Nginx ## PHP >= 8.2 @@ -22,6 +22,7 @@ Both mod_php and FCGI (FPM) are supported. * Composer (added to $PATH) ## RDBMS + * MySQL / MariaDB >= 5.5.3 ## Recommended extensions diff --git a/docs/book/v4/tutorials/create-book-module.md b/docs/book/v4/tutorials/create-book-module.md index 9712700..436031b 100644 --- a/docs/book/v4/tutorials/create-book-module.md +++ b/docs/book/v4/tutorials/create-book-module.md @@ -1,6 +1,6 @@ -## Implementing a book module in DotKernel 3 API +# Implementing a book module in DotKernel 3 API -### File structure +## File structure The below file structure is just an example, you can have multiple components such as event listeners, wrappers, etc. @@ -26,7 +26,6 @@ The below file structure is just an example, you can have multiple components su ConfigProvider.php RoutesDelegator.php - * `src/Book/src/Collection/BookCollection.php` - a collection refers to a container for a group of related objects, typically used to manage sets of related entities fetched from a database * `src/Book/src/Entity/Book.php` - an entity refers to a PHP class that represents a persistent object or data structure * `src/Book/src/Handler/BookHandler.php` - handlers are middleware that can handle requests based on an action @@ -37,22 +36,22 @@ The below file structure is just an example, you can have multiple components su * `src/Book/src/InputFilter/BookInputFilter.php` - input filters and validators * `src/Book/src/InputFilter/Input/*` - input filters and validator configurations -### File creation and contents +## File creation and contents * `src/Book/src/Collection/BookCollection.php` ```php -setName($name); - $this->setAuthor($author); - $this->setReleaseDate($releaseDate); - } - - public function getName(): string - { - return $this->name; - } - - public function setName(string $name): self - { - $this->name = $name; - - return $this; - } - - public function getAuthor(): string - { - return $this->author; - } - - public function setAuthor(string $author): self - { - $this->author = $author; - - return $this; - } - - public function getReleaseDate(): DateTimeImmutable - { - return $this->releaseDate; - } - - public function setReleaseDate(DateTimeImmutable $releaseDate): self - { - $this->releaseDate = $releaseDate; - - return $this; - } - - public function getArrayCopy(): array - { - return [ - 'uuid' => $this->getUuid()->toString(), - 'name' => $this->getName(), - 'author' => $this->getAuthor(), - 'releaseDate' => $this->getReleaseDate(), - ]; - } -} + setName($name); + $this->setAuthor($author); + $this->setReleaseDate($releaseDate); + } + + public function getName(): string + { + return $this->name; + } + + public function setName(string $name): self + { + $this->name = $name; + + return $this; + } + + public function getAuthor(): string + { + return $this->author; + } + + public function setAuthor(string $author): self + { + $this->author = $author; + + return $this; + } + + public function getReleaseDate(): DateTimeImmutable + { + return $this->releaseDate; + } + + public function setReleaseDate(DateTimeImmutable $releaseDate): self + { + $this->releaseDate = $releaseDate; + + return $this; + } + + public function getArrayCopy(): array + { + return [ + 'uuid' => $this->getUuid()->toString(), + 'name' => $this->getName(), + 'author' => $this->getAuthor(), + 'releaseDate' => $this->getReleaseDate(), + ]; + } + } ``` * `src/Book/src/Repository/BookRepository.php` @@ -189,6 +188,7 @@ class BookRepository extends EntityRepository } } ``` + * `src/Book/src/Service/BookService.php` ```php @@ -337,7 +337,6 @@ class RoutesDelegator * `src/Book/src/InputFilter/BookInputFilter.php` - ```php [ 'class' => AttributeDriver::class, @@ -561,6 +561,7 @@ public function getDependencies(): array 'paths' => __DIR__ . '/../../src/Book/src/Entity', ], ``` + add this under the `doctrine.driver` key: * ``'Api\\Book\Entity' => 'BookEntities',`` add this under the `doctrine.driver.drivers` class @@ -609,7 +610,7 @@ return [ Next we need to configure access to the newly created endpoints, add `books.list` and `book.create` to the authorization rbac array, under the `UserRole::ROLE_GUEST` key. > Make sure you read and understand the rbac documentation. -### Migrations +## Migrations We created the `Book` entity, but we didn't create the associated table for it. @@ -623,7 +624,7 @@ To execute the migrations run: vendor/bin/doctrine-migrations migrate -### Checking endpoints +## Checking endpoints If we did everything as planned we can call the `http://localhost/books` endpoint and create a new book: @@ -633,4 +634,4 @@ If we did everything as planned we can call the `http://localhost/books` endpoin To list the books use : - curl http://localhost/books \ No newline at end of file + curl http://localhost/books From 6e3b66169551dbf254cd525d08285ad148a6391c Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Wed, 1 May 2024 18:22:27 +0300 Subject: [PATCH 08/48] documentation linting fix --- README.md | 17 ++++++++++------- docs/book/v4/introduction/installation.md | 10 +++++----- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 95caff7..f067f91 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ You can check if you have development mode enabled by running: ## Step 5: Setup database -## Running migrations: +## Running migrations * create a new MySQL database - set collation to `utf8mb4_general_ci` * fill out the database connection params in `config/autoload/local.php` under `$databases['default']` @@ -65,9 +65,9 @@ This command will prompt you to confirm that you want to run it: Hit `Enter` to confirm the operation. -## Executing fixtures: +## Executing fixtures -**Fixtures are used to seed the database with initial values and should be executed after migrating the database.** +**Fixtures are used to seed the database with initial values and should be executed after migrating the database.** To list all the fixtures, run: @@ -75,7 +75,7 @@ To list all the fixtures, run: This will output all the fixtures in the order of execution. -To execute all fixtures, run: +To execute all fixtures, run: php bin/doctrine fixtures:execute @@ -90,16 +90,19 @@ More details on how fixtures work can be found here: https://github.com/dotkerne php -S 0.0.0.0:8080 -t public Sending a GET request to the [home page](http://localhost:8080/) should output the following message: -```json + +``` { - "message": "Welcome to DotKernel API!" -} +"message": "Welcome to DotKernel API!" +} ``` ## Documentation + In order to access DotKernel API documentation, check the provided [readme file](documentation/README.md). Additionally, each CLI command available has it's own documentation: + * [Create admin account](documentation/command/admin-create.md) * [Generate database migrations](documentation/command/migrations-diff.md) * [Display available endpoints](documentation/command/route-list.md) diff --git a/docs/book/v4/introduction/installation.md b/docs/book/v4/introduction/installation.md index 4acd049..5d7aa93 100644 --- a/docs/book/v4/introduction/installation.md +++ b/docs/book/v4/introduction/installation.md @@ -68,11 +68,11 @@ More details on how fixtures work can be found here: https://github.com/dotkerne Sending a GET request to the [home page](http://localhost:8080/) should output the following message: -```json -{ - "message": "Welcome to DotKernel API!" -} -``` + ``` + { + "message": "Welcome to DotKernel API!" + } + ``` ## Running tests From 1cbae4cdac03b8bca19c482218dd70784ed7e495 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Wed, 1 May 2024 18:26:20 +0300 Subject: [PATCH 09/48] documentation linting fix --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f067f91..4e77ea1 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ Hit `Enter` to confirm the operation. **Fixtures are used to seed the database with initial values and should be executed after migrating the database.** -To list all the fixtures, run: +To list all the fixtures, run: php bin/doctrine fixtures:list @@ -91,11 +91,11 @@ More details on how fixtures work can be found here: https://github.com/dotkerne Sending a GET request to the [home page](http://localhost:8080/) should output the following message: -``` -{ -"message": "Welcome to DotKernel API!" -} -``` + ``` + { + "message": "Welcome to DotKernel API!" + } + ``` ## Documentation From 5d9384965c76cf4906d6d0cc22b2b9ebf585bd8d Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Wed, 1 May 2024 18:35:47 +0300 Subject: [PATCH 10/48] documentation linting fix --- README.md | 8 +- docs/book/v4/introduction/installation.md | 8 +- .../v4/introduction/server-requirements.md | 2 +- docs/book/v4/tutorials/create-book-module.md | 980 +++++++++--------- 4 files changed, 482 insertions(+), 516 deletions(-) diff --git a/README.md b/README.md index 4e77ea1..b533206 100644 --- a/README.md +++ b/README.md @@ -91,11 +91,9 @@ More details on how fixtures work can be found here: https://github.com/dotkerne Sending a GET request to the [home page](http://localhost:8080/) should output the following message: - ``` - { - "message": "Welcome to DotKernel API!" - } - ``` + { + "message": "Welcome to DotKernel API!" + } ## Documentation diff --git a/docs/book/v4/introduction/installation.md b/docs/book/v4/introduction/installation.md index 5d7aa93..c395411 100644 --- a/docs/book/v4/introduction/installation.md +++ b/docs/book/v4/introduction/installation.md @@ -68,11 +68,9 @@ More details on how fixtures work can be found here: https://github.com/dotkerne Sending a GET request to the [home page](http://localhost:8080/) should output the following message: - ``` - { - "message": "Welcome to DotKernel API!" - } - ``` + { + "message": "Welcome to DotKernel API!" + } ## Running tests diff --git a/docs/book/v4/introduction/server-requirements.md b/docs/book/v4/introduction/server-requirements.md index d8a1336..b328a87 100644 --- a/docs/book/v4/introduction/server-requirements.md +++ b/docs/book/v4/introduction/server-requirements.md @@ -6,7 +6,7 @@ For production, we highly recommend a *nix based system. * Apache >= 2.2 * mod_rewrite - * .htaccess support `(AllowOverride All)` +* .htaccess support `(AllowOverride All)` * Nginx ## PHP >= 8.2 diff --git a/docs/book/v4/tutorials/create-book-module.md b/docs/book/v4/tutorials/create-book-module.md index 436031b..d135bed 100644 --- a/docs/book/v4/tutorials/create-book-module.md +++ b/docs/book/v4/tutorials/create-book-module.md @@ -40,489 +40,465 @@ The below file structure is just an example, you can have multiple components su * `src/Book/src/Collection/BookCollection.php` -```php - setName($name); - $this->setAuthor($author); - $this->setReleaseDate($releaseDate); - } - - public function getName(): string - { - return $this->name; - } - - public function setName(string $name): self - { - $this->name = $name; - - return $this; - } - - public function getAuthor(): string + author; } - - public function setAuthor(string $author): self - { - $this->author = $author; - - return $this; - } - - public function getReleaseDate(): DateTimeImmutable - { - return $this->releaseDate; - } - - public function setReleaseDate(DateTimeImmutable $releaseDate): self - { - $this->releaseDate = $releaseDate; - - return $this; - } - - public function getArrayCopy(): array - { - return [ - 'uuid' => $this->getUuid()->toString(), - 'name' => $this->getName(), - 'author' => $this->getAuthor(), - 'releaseDate' => $this->getReleaseDate(), - ]; - } - } -``` - -* `src/Book/src/Repository/BookRepository.php` -```php - - */ -class BookRepository extends EntityRepository -{ - public function saveBook(Book $book): Book + getEntityManager()->persist($book); - $this->getEntityManager()->flush(); - - return $book; + #[ORM\Column(name: "name", type: "string", length: 100)] + protected string $name; + + #[ORM\Column(name: "author", type: "string", length: 100)] + protected string $author; + + #[ORM\Column(name: "releaseDate", type: "datetime_immutable")] + protected DateTimeImmutable $releaseDate; + + public function __construct(string $name, string $author, DateTimeImmutable $releaseDate) + { + parent::__construct(); + + $this->setName($name); + $this->setAuthor($author); + $this->setReleaseDate($releaseDate); + } + + public function getName(): string + { + return $this->name; + } + + public function setName(string $name): self + { + $this->name = $name; + + return $this; + } + + public function getAuthor(): string + { + return $this->author; + } + + public function setAuthor(string $author): self + { + $this->author = $author; + + return $this; + } + + public function getReleaseDate(): DateTimeImmutable + { + return $this->releaseDate; + } + + public function setReleaseDate(DateTimeImmutable $releaseDate): self + { + $this->releaseDate = $releaseDate; + + return $this; + } + + public function getArrayCopy(): array + { + return [ + 'uuid' => $this->getUuid()->toString(), + 'name' => $this->getName(), + 'author' => $this->getAuthor(), + 'releaseDate' => $this->getReleaseDate(), + ]; + } } - public function getBooks(array $filters = []): BookCollection - { - $page = PaginationHelper::getOffsetAndLimit($filters); - - $qb = $this - ->getEntityManager() - ->createQueryBuilder() - ->select('book') - ->from(Book::class, 'book') - ->orderBy($filters['order'] ?? 'book.created', $filters['dir'] ?? 'desc') - ->setFirstResult($page['offset']) - ->setMaxResults($page['limit']); - - $qb->getQuery()->useQueryCache(true); +* `src/Book/src/Repository/BookRepository.php` - return new BookCollection($qb, false); - } -} -``` + + */ + class BookRepository extends EntityRepository + { + public function saveBook(Book $book): Book + { + $this->getEntityManager()->persist($book); + $this->getEntityManager()->flush(); + + return $book; + } + + public function getBooks(array $filters = []): BookCollection + { + $page = PaginationHelper::getOffsetAndLimit($filters); + + $qb = $this + ->getEntityManager() + ->createQueryBuilder() + ->select('book') + ->from(Book::class, 'book') + ->orderBy($filters['order'] ?? 'book.created', $filters['dir'] ?? 'desc') + ->setFirstResult($page['offset']) + ->setMaxResults($page['limit']); + + $qb->getQuery()->useQueryCache(true); + + return new BookCollection($qb, false); + } + } * `src/Book/src/Service/BookService.php` -```php -bookRepository->saveBook($book); - } - - public function getBooks(array $filters = []) - { - return $this->bookRepository->getBooks($filters); - } -} -``` + bookRepository->saveBook($book); + } + + public function getBooks(array $filters = []) + { + return $this->bookRepository->getBooks($filters); + } + } * `src/Book/src/Service/BookServiceInterface.php` -```php - $this->getDependencies(), - MetadataMap::class => $this->getHalConfig(), - ]; - } - - public function getDependencies(): array - { - return [ - 'factories' => [ - BookHandler::class => AnnotatedServiceFactory::class, - BookService::class => AnnotatedServiceFactory::class, - BookRepository::class => AnnotatedRepositoryFactory::class, - ], - 'aliases' => [ - BookServiceInterface::class => BookService::class, - ], - ]; - } - - public function getHalConfig(): array - { - return [ - AppConfigProvider::getCollection(BookCollection::class, 'books.list', 'books'), - AppConfigProvider::getResource(Book::class, 'book.create'), - ]; - } -} -``` + $this->getDependencies(), + MetadataMap::class => $this->getHalConfig(), + ]; + } + + public function getDependencies(): array + { + return [ + 'factories' => [ + BookHandler::class => AnnotatedServiceFactory::class, + BookService::class => AnnotatedServiceFactory::class, + BookRepository::class => AnnotatedRepositoryFactory::class, + ], + 'aliases' => [ + BookServiceInterface::class => BookService::class, + ], + ]; + } + + public function getHalConfig(): array + { + return [ + AppConfigProvider::getCollection(BookCollection::class, 'books.list', 'books'), + AppConfigProvider::getResource(Book::class, 'book.create'), + ]; + } + } * `src/Book/src/RoutesDelegator.php` -```php -get( - '/books', - BookHandler::class, - 'books.list' - ); - - $app->post( - '/book', - BookHandler::class, - 'book.create' - ); - - return $app; - } -} -``` + get( + '/books', + BookHandler::class, + 'books.list' + ); + + $app->post( + '/book', + BookHandler::class, + 'book.create' + ); + + return $app; + } + } * `src/Book/src/InputFilter/BookInputFilter.php` -```php -add(new NameInput('name')); - $this->add(new AuthorInput('author')); - $this->add(new ReleaseDateInput('releaseDate')); - } -} -``` + add(new NameInput('name')); + $this->add(new AuthorInput('author')); + $this->add(new ReleaseDateInput('releaseDate')); + } + } * `src/Book/src/InputFilter/Input/AuthorInput.php` -```php -setRequired($isRequired); - - $this->getFilterChain() - ->attachByName(StringTrim::class) - ->attachByName(StripTags::class); - - $this->getValidatorChain() - ->attachByName(NotEmpty::class, [ - 'message' => sprintf(Message::VALIDATOR_REQUIRED_FIELD_BY_NAME, 'author'), - ], true); - } -} -``` + setRequired($isRequired); + + $this->getFilterChain() + ->attachByName(StringTrim::class) + ->attachByName(StripTags::class); + + $this->getValidatorChain() + ->attachByName(NotEmpty::class, [ + 'message' => sprintf(Message::VALIDATOR_REQUIRED_FIELD_BY_NAME, 'author'), + ], true); + } + } * `src/Book/src/InputFilter/Input/NameInput.php` -```php -setRequired($isRequired); - - $this->getFilterChain() - ->attachByName(StringTrim::class) - ->attachByName(StripTags::class); - - $this->getValidatorChain() - ->attachByName(NotEmpty::class, [ - 'message' => sprintf(Message::VALIDATOR_REQUIRED_FIELD_BY_NAME, 'name'), - ], true); - } -} -``` + setRequired($isRequired); + + $this->getFilterChain() + ->attachByName(StringTrim::class) + ->attachByName(StripTags::class); + + $this->getValidatorChain() + ->attachByName(NotEmpty::class, [ + 'message' => sprintf(Message::VALIDATOR_REQUIRED_FIELD_BY_NAME, 'name'), + ], true); + } + } * `src/Book/src/InputFilter/Input/ReleaseDateInput.php` -```php -setRequired($isRequired); - - $this->getFilterChain() - ->attachByName(StringTrim::class) - ->attachByName(StripTags::class); - - $this->getValidatorChain() - ->attachByName(Date::class, [ - 'message' => sprintf(Message::INVALID_VALUE, 'releaseDate'), - ], true); - } -} -``` + setRequired($isRequired); + + $this->getFilterChain() + ->attachByName(StringTrim::class) + ->attachByName(StripTags::class); + + $this->getValidatorChain() + ->attachByName(Date::class, [ + 'message' => sprintf(Message::INVALID_VALUE, 'releaseDate'), + ], true); + } + } * `src/Book/src/Handler/BookHandler.php` -```php -bookService->getBooks($request->getQueryParams()); - - return $this->createResponse($request, $books); - } - - public function post(ServerRequestInterface $request): ResponseInterface - { - $inputFilter = (new BookInputFilter())->setData($request->getParsedBody()); - if (! $inputFilter->isValid()) { - return $this->errorResponse($inputFilter->getMessages()); - } - - $book = $this->bookService->createBook($inputFilter->getValues()); - - return $this->createResponse($request, $book); - } -} -``` + bookService->getBooks($request->getQueryParams()); + + return $this->createResponse($request, $books); + } + + public function post(ServerRequestInterface $request): ResponseInterface + { + $inputFilter = (new BookInputFilter())->setData($request->getParsedBody()); + if (! $inputFilter->isValid()) { + return $this->errorResponse($inputFilter->getMessages()); + } + + $book = $this->bookService->createBook($inputFilter->getValues()); + + return $this->createResponse($request, $book); + } + } ## Configuring and registering the new module @@ -534,78 +510,72 @@ Once you set up all the files as in the example above, you will need to do a few It should look like this: -```php -public function getDependencies(): array -{ - return [ - 'delegators' => [ - Application::class => [ - RoutesDelegator::class, - \Api\Admin\RoutesDelegator::class, - \Api\User\RoutesDelegator::class, - \Api\Book\RoutesDelegator::class, - ], - ], - 'factories' => [ - ... - ] - ... -``` - -* In `src/config/autoload/doctrine.global.php` add under the `doctrine.driver` key: + public function getDependencies(): array + { + return [ + 'delegators' => [ + Application::class => [ + RoutesDelegator::class, + \Api\Admin\RoutesDelegator::class, + \Api\User\RoutesDelegator::class, + \Api\Book\RoutesDelegator::class, + ], + ], + 'factories' => [ + ... + ] + ... + +* In `src/config/autoload/doctrine.global.php` add this under the `doctrine.driver` key: - * ```php 'BookEntities' => [ 'class' => AttributeDriver::class, 'cache' => 'array', 'paths' => __DIR__ . '/../../src/Book/src/Entity', ], - ``` add this under the `doctrine.driver` key: * ``'Api\\Book\Entity' => 'BookEntities',`` add this under the `doctrine.driver.drivers` class Example: -```php - [ - ... - 'driver' => [ - 'orm_default' => [ - 'class' => MappingDriverChain::class, - 'drivers' => [ - 'Api\\App\Entity' => 'AppEntities', - 'Api\\Admin\\Entity' => 'AdminEntities', - 'Api\\User\\Entity' => 'UserEntities', - 'Api\\Book\Entity' => 'BookEntities', + [ + ... + 'driver' => [ + 'orm_default' => [ + 'class' => MappingDriverChain::class, + 'drivers' => [ + 'Api\\App\Entity' => 'AppEntities', + 'Api\\Admin\\Entity' => 'AdminEntities', + 'Api\\User\\Entity' => 'UserEntities', + 'Api\\Book\Entity' => 'BookEntities', + ], + ], + 'AdminEntities' => [ + 'class' => AttributeDriver::class, + 'cache' => 'array', + 'paths' => __DIR__ . '/../../src/Admin/src/Entity', + ], + 'UserEntities' => [ + 'class' => AttributeDriver::class, + 'cache' => 'array', + 'paths' => __DIR__ . '/../../src/User/src/Entity', + ], + 'AppEntities' => [ + 'class' => AttributeDriver::class, + 'cache' => 'array', + 'paths' => __DIR__ . '/../../src/App/src/Entity', + ], + 'BookEntities' => [ + 'class' => AttributeDriver::class, + 'cache' => 'array', + 'paths' => __DIR__ . '/../../src/Book/src/Entity', ], ], - 'AdminEntities' => [ - 'class' => AttributeDriver::class, - 'cache' => 'array', - 'paths' => __DIR__ . '/../../src/Admin/src/Entity', - ], - 'UserEntities' => [ - 'class' => AttributeDriver::class, - 'cache' => 'array', - 'paths' => __DIR__ . '/../../src/User/src/Entity', - ], - 'AppEntities' => [ - 'class' => AttributeDriver::class, - 'cache' => 'array', - 'paths' => __DIR__ . '/../../src/App/src/Entity', - ], - 'BookEntities' => [ - 'class' => AttributeDriver::class, - 'cache' => 'array', - 'paths' => __DIR__ . '/../../src/Book/src/Entity', - ], - ], - ... -``` + ... Next we need to configure access to the newly created endpoints, add `books.list` and `book.create` to the authorization rbac array, under the `UserRole::ROLE_GUEST` key. > Make sure you read and understand the rbac documentation. From 93027705c86427a5b4b0bc8c78d0fd3052275f44 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Wed, 1 May 2024 18:41:30 +0300 Subject: [PATCH 11/48] documentation linting fix --- docs/book/v4/introduction/introduction.md | 3 +-- docs/book/v4/introduction/server-requirements.md | 2 +- docs/book/v4/tutorials/create-book-module.md | 13 +++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/book/v4/introduction/introduction.md b/docs/book/v4/introduction/introduction.md index df9e203..3e9e209 100644 --- a/docs/book/v4/introduction/introduction.md +++ b/docs/book/v4/introduction/introduction.md @@ -1,4 +1,4 @@ -# Introduction +# Introduction Based on Enrico Zimuel’s Zend Expressive API – Skeleton example, DotKernel API runs on Laminas and Mezzio components and implements standards like PSR-3, PSR-4, PSR-7, PSR-11 and PSR-15. @@ -46,7 +46,6 @@ For our API payloads ( a value object for describing the API resource, its relat By using `MezzioCorsMiddlewareCorsMiddleware`, the CORS preflight will be recognized and the middleware will start to detect the proper CORS configuration. The Router is used to detect every allowed request method by executing a route match with all possible request methods. Therefore, for every preflight request, there is at least one Router request. - ## OAuth 2 OAuth 2 is an authorization framework that enables applications to obtain limited access to user accounts on your Dotkernel API. We are using mezzio/mezzio-authentication-oauth2 which provides OAuth2 authentication for Mezzio and PSR-7/PSR-15 applications by using league/oauth2-server package. diff --git a/docs/book/v4/introduction/server-requirements.md b/docs/book/v4/introduction/server-requirements.md index b328a87..1a06768 100644 --- a/docs/book/v4/introduction/server-requirements.md +++ b/docs/book/v4/introduction/server-requirements.md @@ -5,7 +5,7 @@ For production, we highly recommend a *nix based system. ## Webserver * Apache >= 2.2 -* mod_rewrite +* mod_rewrite * .htaccess support `(AllowOverride All)` * Nginx diff --git a/docs/book/v4/tutorials/create-book-module.md b/docs/book/v4/tutorials/create-book-module.md index d135bed..c66c6d1 100644 --- a/docs/book/v4/tutorials/create-book-module.md +++ b/docs/book/v4/tutorials/create-book-module.md @@ -508,7 +508,7 @@ Once you set up all the files as in the example above, you will need to do a few * Register the module by adding `Api\Book\ConfigProvider::class,` under `Api\User\ConfigProvider::class,`. * Register the module's routes by adding `\Api\Book\RoutesDelegator::class,` under `\Api\User\RoutesDelegator::class,` in `src/App/src/ConfigProvider.php`. -It should look like this: +It should look like this: public function getDependencies(): array { @@ -533,11 +533,12 @@ It should look like this: 'cache' => 'array', 'paths' => __DIR__ . '/../../src/Book/src/Entity', ], - - add this under the `doctrine.driver` key: - * ``'Api\\Book\Entity' => 'BookEntities',`` add this under the `doctrine.driver.drivers` class -Example: +* add this under the `doctrine.driver` key: + + ``'Api\\Book\Entity' => 'BookEntities',`` add this under the `doctrine.driver.drivers` class + +Example: Date: Wed, 1 May 2024 18:46:37 +0300 Subject: [PATCH 12/48] documentation linting fix --- docs/book/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/book/index.md b/docs/book/index.md index ae42a26..2eceefd 100644 --- a/docs/book/index.md +++ b/docs/book/index.md @@ -1 +1 @@ -../../README.md +# ../../README.md From e2e930670f168a534d96c474a76fc260a9009ea0 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 14:39:33 +0300 Subject: [PATCH 13/48] pre run hook tst --- .laminas-ci/pre-run.sh | 1 + 1 file changed, 1 insertion(+) create mode 100755 .laminas-ci/pre-run.sh diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh new file mode 100755 index 0000000..d49fcc4 --- /dev/null +++ b/.laminas-ci/pre-run.sh @@ -0,0 +1 @@ +echo "hello world!" \ No newline at end of file From 158508b918eb2b35c77316e19e38fe7eed828b33 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 14:46:10 +0300 Subject: [PATCH 14/48] pre run hook tst --- .laminas-ci/pre-run.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index d49fcc4..1b18a16 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -1 +1,5 @@ -echo "hello world!" \ No newline at end of file +cd ../ + +mv config/autoload/local.php.dist config/autoload/local.php +mv config/autoload/mail.local.php.dist config/autoload/mail.local.php +mv config/autoload/local.test.php.dist config/autoload/local.test.php \ No newline at end of file From b4b231900eb29eb4bb9762a5a440cac7883bf9a9 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 14:49:35 +0300 Subject: [PATCH 15/48] pre run hook tst --- .laminas-ci/pre-run.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index 1b18a16..2cf87b2 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -1,5 +1,9 @@ +echo "$PWD" + cd ../ +echo "$PWD" + mv config/autoload/local.php.dist config/autoload/local.php mv config/autoload/mail.local.php.dist config/autoload/mail.local.php mv config/autoload/local.test.php.dist config/autoload/local.test.php \ No newline at end of file From a77df8429e7c9ea210f2cc3f8cd7e11e30f8c833 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 14:57:49 +0300 Subject: [PATCH 16/48] pre run hook tst --- .laminas-ci/pre-run.sh | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index 2cf87b2..5ebaef0 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -4,6 +4,16 @@ cd ../ echo "$PWD" -mv config/autoload/local.php.dist config/autoload/local.php -mv config/autoload/mail.local.php.dist config/autoload/mail.local.php -mv config/autoload/local.test.php.dist config/autoload/local.test.php \ No newline at end of file +echo "$2" + +JOB=$3 +COMMAND=$(echo "${JOB}" | jq -r '.command') + +echo "$COMMAND" +#if [[ ! ${COMMAND} =~ phpunit ]];then +# exit 0 +#fi + +#mv config/autoload/local.php.dist config/autoload/local.php +#mv config/autoload/mail.local.php.dist config/autoload/mail.local.php +#mv config/autoload/local.test.php.dist config/autoload/local.test.php \ No newline at end of file From c1b93621ce0ac7f9da7c35a9f15f23b77b4a841b Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 15:05:43 +0300 Subject: [PATCH 17/48] pre run hook tst --- .laminas-ci/pre-run.sh | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index 5ebaef0..e3d054f 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -9,11 +9,12 @@ echo "$2" JOB=$3 COMMAND=$(echo "${JOB}" | jq -r '.command') +ls -la + echo "$COMMAND" -#if [[ ! ${COMMAND} =~ phpunit ]];then -# exit 0 -#fi +if [[ ${COMMAND} =~ phpunit ]];then + #mv config/autoload/local.php.dist config/autoload/local.php + #mv config/autoload/mail.local.php.dist config/autoload/mail.local.php + #mv config/autoload/local.test.php.dist config/autoload/local.test.php -#mv config/autoload/local.php.dist config/autoload/local.php -#mv config/autoload/mail.local.php.dist config/autoload/mail.local.php -#mv config/autoload/local.test.php.dist config/autoload/local.test.php \ No newline at end of file +fi \ No newline at end of file From bd49d4b2dabe957f7cd426e0c822e717dff800d1 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 15:12:37 +0300 Subject: [PATCH 18/48] pre run hook tst --- .laminas-ci/pre-run.sh | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index e3d054f..fc67bfa 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -1,9 +1,5 @@ echo "$PWD" -cd ../ - -echo "$PWD" - echo "$2" JOB=$3 @@ -12,9 +8,9 @@ COMMAND=$(echo "${JOB}" | jq -r '.command') ls -la echo "$COMMAND" -if [[ ${COMMAND} =~ phpunit ]];then +#if [[ ${COMMAND} =~ phpunit ]];then #mv config/autoload/local.php.dist config/autoload/local.php #mv config/autoload/mail.local.php.dist config/autoload/mail.local.php #mv config/autoload/local.test.php.dist config/autoload/local.test.php -fi \ No newline at end of file +#fi \ No newline at end of file From 21a1b469bfa4bab489b9c41f5de84f0cf34127b2 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 15:17:56 +0300 Subject: [PATCH 19/48] pre run hook tst --- .laminas-ci/pre-run.sh | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index fc67bfa..fba6433 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -1,16 +1,15 @@ -echo "$PWD" +#echo "$PWD" -echo "$2" +#echo "$2" -JOB=$3 -COMMAND=$(echo "${JOB}" | jq -r '.command') +#JOB=$3 +#COMMAND=$(echo "${JOB}" | jq -r '.command') -ls -la +#ls -la -echo "$COMMAND" -#if [[ ${COMMAND} =~ phpunit ]];then - #mv config/autoload/local.php.dist config/autoload/local.php - #mv config/autoload/mail.local.php.dist config/autoload/mail.local.php - #mv config/autoload/local.test.php.dist config/autoload/local.test.php - -#fi \ No newline at end of file +#echo "$COMMAND" +if [[ ${COMMAND} =~ phpunit ]];then + mv config/autoload/local.php.dist config/autoload/local.php + mv config/autoload/mail.local.php.dist config/autoload/mail.local.php + mv config/autoload/local.test.php.dist config/autoload/local.test.php +fi \ No newline at end of file From 9fddf1e3c6e924a5f2c462c0f838290a5cb1327d Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 15:26:32 +0300 Subject: [PATCH 20/48] pre run hook tst --- .laminas-ci/pre-run.sh | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index fba6433..64edbf3 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -1,14 +1,9 @@ -#echo "$PWD" +JOB=$3 +COMMAND=$(echo "${JOB}" | jq -r '.command') -#echo "$2" +echo "Running $COMMAND" -#JOB=$3 -#COMMAND=$(echo "${JOB}" | jq -r '.command') - -#ls -la - -#echo "$COMMAND" -if [[ ${COMMAND} =~ phpunit ]];then +if [[ ${COMMAND} =~ phpunit || ${COMMAND} =~ psalm ]];then mv config/autoload/local.php.dist config/autoload/local.php mv config/autoload/mail.local.php.dist config/autoload/mail.local.php mv config/autoload/local.test.php.dist config/autoload/local.test.php From a030c6a497d4ec4e5d91606984e479b6e081ece8 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 16:05:51 +0300 Subject: [PATCH 21/48] pre run hook test --- .laminas-ci/pre-run.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index 64edbf3..c8e016d 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -3,7 +3,9 @@ COMMAND=$(echo "${JOB}" | jq -r '.command') echo "Running $COMMAND" -if [[ ${COMMAND} =~ phpunit || ${COMMAND} =~ psalm ]];then +pecl install sqlite3 + +if [[ ${COMMAND} =~ phpunit ]];then mv config/autoload/local.php.dist config/autoload/local.php mv config/autoload/mail.local.php.dist config/autoload/mail.local.php mv config/autoload/local.test.php.dist config/autoload/local.test.php From db218d39baef7782838a4f33d46e82ed092d78a5 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 16:10:40 +0300 Subject: [PATCH 22/48] pre run hook test --- .laminas-ci/pre-run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index c8e016d..544c9d1 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -3,7 +3,7 @@ COMMAND=$(echo "${JOB}" | jq -r '.command') echo "Running $COMMAND" -pecl install sqlite3 +pecl install sqlite if [[ ${COMMAND} =~ phpunit ]];then mv config/autoload/local.php.dist config/autoload/local.php From 6ea4e916e0bcfb26a2899f3116fcf8b99c484a20 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 16:14:36 +0300 Subject: [PATCH 23/48] pre run hook test --- .laminas-ci/pre-run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index 544c9d1..e9b8221 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -3,7 +3,7 @@ COMMAND=$(echo "${JOB}" | jq -r '.command') echo "Running $COMMAND" -pecl install sqlite +pecl install php-sqlite3 if [[ ${COMMAND} =~ phpunit ]];then mv config/autoload/local.php.dist config/autoload/local.php From 8d52c6359c1703cb3b64d65715e2fe8d85f7b3ca Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 16:21:45 +0300 Subject: [PATCH 24/48] pre run hook test --- .laminas-ci/pre-run.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index e9b8221..1fef5b7 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -3,7 +3,10 @@ COMMAND=$(echo "${JOB}" | jq -r '.command') echo "Running $COMMAND" -pecl install php-sqlite3 +pecl install sqlite +pecl install pdo_sqlite + +php -i | grep sqlite if [[ ${COMMAND} =~ phpunit ]];then mv config/autoload/local.php.dist config/autoload/local.php From 4e259b71acc4453f8230df9f7857e04342312711 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 16:29:56 +0300 Subject: [PATCH 25/48] pre run hook test --- .laminas-ci/pre-run.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index 1fef5b7..b1e961b 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -3,10 +3,10 @@ COMMAND=$(echo "${JOB}" | jq -r '.command') echo "Running $COMMAND" -pecl install sqlite -pecl install pdo_sqlite +#pecl install sqlite +pecl install php8.2-sqlite3 -php -i | grep sqlite +#php -i | grep sqlite if [[ ${COMMAND} =~ phpunit ]];then mv config/autoload/local.php.dist config/autoload/local.php From c1d7f3ee3df681d86f8335195b19c851f453f1f8 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 16:41:26 +0300 Subject: [PATCH 26/48] pre run hook test --- .laminas-ci/pre-run.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index b1e961b..5bb6888 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -4,7 +4,13 @@ COMMAND=$(echo "${JOB}" | jq -r '.command') echo "Running $COMMAND" #pecl install sqlite -pecl install php8.2-sqlite3 +#pecl install php8-sqlite3 + +apt-get install php8.2-sqlite3 + +echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + +apt-get install php8.2-sqlite #php -i | grep sqlite @@ -12,4 +18,4 @@ if [[ ${COMMAND} =~ phpunit ]];then mv config/autoload/local.php.dist config/autoload/local.php mv config/autoload/mail.local.php.dist config/autoload/mail.local.php mv config/autoload/local.test.php.dist config/autoload/local.test.php -fi \ No newline at end of file +fi From f1f7ff672da04b525a36b83a0e60e42ce4af5d0c Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 16:49:07 +0300 Subject: [PATCH 27/48] pre run hook test --- .laminas-ci/pre-run.sh | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index 5bb6888..13bf3f5 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -1,18 +1,12 @@ JOB=$3 +PHP_VERSION=$5 + COMMAND=$(echo "${JOB}" | jq -r '.command') echo "Running $COMMAND" -#pecl install sqlite -#pecl install php8-sqlite3 - -apt-get install php8.2-sqlite3 - -echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - -apt-get install php8.2-sqlite -#php -i | grep sqlite +apt-get install "php${PHP_VERSION}-sqlite3" if [[ ${COMMAND} =~ phpunit ]];then mv config/autoload/local.php.dist config/autoload/local.php From 61847a1a05cc09dfaee9545a932cddc96cf4d386 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 16:54:10 +0300 Subject: [PATCH 28/48] pre run hook test --- .laminas-ci/pre-run.sh | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index 13bf3f5..f21800c 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -1,12 +1,20 @@ JOB=$3 -PHP_VERSION=$5 - COMMAND=$(echo "${JOB}" | jq -r '.command') echo "Running $COMMAND" +#pecl install sqlite +#pecl install php8-sqlite3 + +apt-get install php8.2-sqlite3 +apt-get install php8.3-sqlite3 + +echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + +apt-get install php8.2-sqlite +apt-get install php8.3-sqlite -apt-get install "php${PHP_VERSION}-sqlite3" +#php -i | grep sqlite if [[ ${COMMAND} =~ phpunit ]];then mv config/autoload/local.php.dist config/autoload/local.php From aeb79fb66789c78d67a8983652fb4a5a390214ce Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 16:57:05 +0300 Subject: [PATCH 29/48] pre run hook test --- .laminas-ci/pre-run.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index f21800c..de222a8 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -1,7 +1,9 @@ JOB=$3 +PHP_VERSION=$5 COMMAND=$(echo "${JOB}" | jq -r '.command') -echo "Running $COMMAND" +echo "Running $COMMAND @@@@@@@@@@@@@@@" +echo "$PHP_VERSION" #pecl install sqlite #pecl install php8-sqlite3 @@ -11,8 +13,8 @@ apt-get install php8.3-sqlite3 echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" -apt-get install php8.2-sqlite -apt-get install php8.3-sqlite +#apt-get install php8.2-sqlite +#apt-get install php8.3-sqlite #php -i | grep sqlite From 5cb921dcf0e55fb8ace123aaebcd47b9d6c33234 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 17:01:56 +0300 Subject: [PATCH 30/48] pre run hook test --- .laminas-ci/pre-run.sh | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index de222a8..a84c8f4 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -3,21 +3,11 @@ PHP_VERSION=$5 COMMAND=$(echo "${JOB}" | jq -r '.command') echo "Running $COMMAND @@@@@@@@@@@@@@@" -echo "$PHP_VERSION" - -#pecl install sqlite -#pecl install php8-sqlite3 +echo "PHP VERSION : ${PHP_VERSION}" apt-get install php8.2-sqlite3 apt-get install php8.3-sqlite3 -echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - -#apt-get install php8.2-sqlite -#apt-get install php8.3-sqlite - -#php -i | grep sqlite - if [[ ${COMMAND} =~ phpunit ]];then mv config/autoload/local.php.dist config/autoload/local.php mv config/autoload/mail.local.php.dist config/autoload/mail.local.php From 71a9f39e0f426987f1acaeb12b5a13219e8b0009 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 17:05:39 +0300 Subject: [PATCH 31/48] pre run hook test --- .laminas-ci/pre-run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index a84c8f4..8350816 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -1,5 +1,5 @@ JOB=$3 -PHP_VERSION=$5 +PHP_VERSION=$4 COMMAND=$(echo "${JOB}" | jq -r '.command') echo "Running $COMMAND @@@@@@@@@@@@@@@" From 0b6d23bfd94fa4139409edb0399376b2ef6612c3 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 17:10:28 +0300 Subject: [PATCH 32/48] pre run hook test --- .laminas-ci/pre-run.sh | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index 8350816..eb8123b 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -3,13 +3,15 @@ PHP_VERSION=$4 COMMAND=$(echo "${JOB}" | jq -r '.command') echo "Running $COMMAND @@@@@@@@@@@@@@@" -echo "PHP VERSION : ${PHP_VERSION}" -apt-get install php8.2-sqlite3 -apt-get install php8.3-sqlite3 +#apt-get install php8.2-sqlite3 +#apt-get install php8.3-sqlite3 if [[ ${COMMAND} =~ phpunit ]];then - mv config/autoload/local.php.dist config/autoload/local.php - mv config/autoload/mail.local.php.dist config/autoload/mail.local.php - mv config/autoload/local.test.php.dist config/autoload/local.test.php + + apt-get install php${PHP_VERSION}-sqlite3 + + cp config/autoload/local.php.dist config/autoload/local.php + cp config/autoload/mail.local.php.dist config/autoload/mail.local.php + cp config/autoload/local.test.php.dist config/autoload/local.test.php fi From 61e6d17e4facb1c7e07f792379ad4c8532499f96 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 17:14:02 +0300 Subject: [PATCH 33/48] pre run script fix --- .github/workflows/continuous-integration.yml | 2 +- .github/workflows/docs-build.yml | 2 +- .laminas-ci/pre-run.sh | 8 +++----- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 2f02e70..26c5802 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -8,4 +8,4 @@ on: jobs: ci: - uses: laminas/workflow-continuous-integration/.github/workflows/continuous-integration.yml@1.x \ No newline at end of file + uses: laminas/workflow-continuous-integration/.github/workflows/continuous-integration.yml@1.x diff --git a/.github/workflows/docs-build.yml b/.github/workflows/docs-build.yml index 164e3d2..1a7aa24 100644 --- a/.github/workflows/docs-build.yml +++ b/.github/workflows/docs-build.yml @@ -13,4 +13,4 @@ jobs: uses: dotkernel/documentation-theme/github-actions/docs@main env: DEPLOY_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index eb8123b..f6351b8 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -2,16 +2,14 @@ JOB=$3 PHP_VERSION=$4 COMMAND=$(echo "${JOB}" | jq -r '.command') -echo "Running $COMMAND @@@@@@@@@@@@@@@" - -#apt-get install php8.2-sqlite3 -#apt-get install php8.3-sqlite3 +echo "Running $COMMAND" if [[ ${COMMAND} =~ phpunit ]];then - apt-get install php${PHP_VERSION}-sqlite3 + apt-get install php"${PHP_VERSION}"-sqlite3 cp config/autoload/local.php.dist config/autoload/local.php cp config/autoload/mail.local.php.dist config/autoload/mail.local.php cp config/autoload/local.test.php.dist config/autoload/local.test.php + fi From 565c602fe6fd2fb4a3e8f23ee336713221a65b7e Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 17:32:04 +0300 Subject: [PATCH 34/48] pre run script fix --- .laminas-ci/pre-run.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index f6351b8..1e32ee3 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -6,6 +6,7 @@ echo "Running $COMMAND" if [[ ${COMMAND} =~ phpunit ]];then + apt-get update apt-get install php"${PHP_VERSION}"-sqlite3 cp config/autoload/local.php.dist config/autoload/local.php From 069d44b7e614905c4b2054d288f27162eb46f1d6 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 17:35:12 +0300 Subject: [PATCH 35/48] pre run script fix --- .laminas-ci/pre-run.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index 1e32ee3..993a425 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -6,8 +6,10 @@ echo "Running $COMMAND" if [[ ${COMMAND} =~ phpunit ]];then - apt-get update - apt-get install php"${PHP_VERSION}"-sqlite3 +# apt-get update +# apt-get install php"${PHP_VERSION}"-sqlite3 + apt-get install php8.2-sqlite3 + apt-get install php8.3-sqlite3 cp config/autoload/local.php.dist config/autoload/local.php cp config/autoload/mail.local.php.dist config/autoload/mail.local.php From a5563e968e3c9996e0a4394467c44bc2e0410b9a Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 17:42:48 +0300 Subject: [PATCH 36/48] pre run script fix --- .laminas-ci/pre-run.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index 993a425..82cd778 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -7,9 +7,9 @@ echo "Running $COMMAND" if [[ ${COMMAND} =~ phpunit ]];then # apt-get update -# apt-get install php"${PHP_VERSION}"-sqlite3 - apt-get install php8.2-sqlite3 - apt-get install php8.3-sqlite3 + apt-get install php"${PHP_VERSION}"-sqlite3 >= 8.2.18 +# apt-get install php8.2-sqlite3 +# apt-get install php8.3-sqlite3 cp config/autoload/local.php.dist config/autoload/local.php cp config/autoload/mail.local.php.dist config/autoload/mail.local.php From 365aee7b9dcf75783f478e0aee353b8d7c348293 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 17:46:45 +0300 Subject: [PATCH 37/48] pre run script fix --- .laminas-ci/pre-run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index 82cd778..4efae52 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -7,7 +7,7 @@ echo "Running $COMMAND" if [[ ${COMMAND} =~ phpunit ]];then # apt-get update - apt-get install php"${PHP_VERSION}"-sqlite3 >= 8.2.18 + apt-get install php"${PHP_VERSION}"-sqlite3=8.2.18 # apt-get install php8.2-sqlite3 # apt-get install php8.3-sqlite3 From c7a16998de6637aaf92d4c67cc2f1ebc39430cdd Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 17:48:41 +0300 Subject: [PATCH 38/48] pre run script fix --- .laminas-ci/pre-run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index 4efae52..c96d9f1 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -7,7 +7,7 @@ echo "Running $COMMAND" if [[ ${COMMAND} =~ phpunit ]];then # apt-get update - apt-get install php"${PHP_VERSION}"-sqlite3=8.2.18 + apt-get install php"${PHP_VERSION}"-sqlite3=8.2.16 # apt-get install php8.2-sqlite3 # apt-get install php8.3-sqlite3 From a9f2f455876a6c1e16b95584f289b2aabdc4e5d9 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 17:52:44 +0300 Subject: [PATCH 39/48] pre run script fix --- .laminas-ci/pre-run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index c96d9f1..5e640eb 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -7,7 +7,7 @@ echo "Running $COMMAND" if [[ ${COMMAND} =~ phpunit ]];then # apt-get update - apt-get install php"${PHP_VERSION}"-sqlite3=8.2.16 + apt-get install php"${PHP_VERSION}"-sqlite3=8.3.6 # apt-get install php8.2-sqlite3 # apt-get install php8.3-sqlite3 From 4d7b1e191ab55a176a46c5782a3ef2801aeb847c Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 17:54:52 +0300 Subject: [PATCH 40/48] pre run script fix --- .laminas-ci/pre-run.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index 5e640eb..17ba9cb 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -6,8 +6,8 @@ echo "Running $COMMAND" if [[ ${COMMAND} =~ phpunit ]];then -# apt-get update - apt-get install php"${PHP_VERSION}"-sqlite3=8.3.6 + apt-get update -y + apt-get install php"${PHP_VERSION}"-sqlite3 # apt-get install php8.2-sqlite3 # apt-get install php8.3-sqlite3 From 40395f5a29710e0660ebd643c1acc4a32676a470 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 17:59:01 +0300 Subject: [PATCH 41/48] pre run script fix --- .laminas-ci/pre-run.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index 17ba9cb..bc50216 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -7,6 +7,7 @@ echo "Running $COMMAND" if [[ ${COMMAND} =~ phpunit ]];then apt-get update -y + apt-get upgrade -y apt-get install php"${PHP_VERSION}"-sqlite3 # apt-get install php8.2-sqlite3 # apt-get install php8.3-sqlite3 From b9522cb880d4d244447eccc1f592fa60b8746f98 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 18:08:09 +0300 Subject: [PATCH 42/48] added ext-gd --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index ea0dddf..d9c4f10 100644 --- a/composer.json +++ b/composer.json @@ -44,6 +44,7 @@ "require": { "php": "~8.2.0 || ~8.3.0", "ext-json": "*", + "ext-gd": "*", "dotkernel/dot-annotated-services": "^4.1.7", "dotkernel/dot-cache": "^4.0", "dotkernel/dot-cli": "^3.5.0", From d01650de8052de4e11547128852d816d1a87331a Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 18:15:56 +0300 Subject: [PATCH 43/48] added ext-gd --- .laminas-ci/pre-run.sh | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index bc50216..a666cee 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -6,11 +6,9 @@ echo "Running $COMMAND" if [[ ${COMMAND} =~ phpunit ]];then - apt-get update -y - apt-get upgrade -y +# apt-get update -y +# apt-get upgrade -y apt-get install php"${PHP_VERSION}"-sqlite3 -# apt-get install php8.2-sqlite3 -# apt-get install php8.3-sqlite3 cp config/autoload/local.php.dist config/autoload/local.php cp config/autoload/mail.local.php.dist config/autoload/mail.local.php From 1d30a4561b0431256fb2fe82cd0816c45ccde1c5 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Thu, 2 May 2024 18:19:06 +0300 Subject: [PATCH 44/48] added ext-gd --- .laminas-ci/pre-run.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index a666cee..f6351b8 100755 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -6,8 +6,6 @@ echo "Running $COMMAND" if [[ ${COMMAND} =~ phpunit ]];then -# apt-get update -y -# apt-get upgrade -y apt-get install php"${PHP_VERSION}"-sqlite3 cp config/autoload/local.php.dist config/autoload/local.php From 556e7c5ff2ebf6de101fa4237e220aa97c01f40f Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Fri, 3 May 2024 10:36:59 +0300 Subject: [PATCH 45/48] requested changes --- README.md | 2 +- docs/book/v4/introduction/file-structure.md | 2 +- docs/book/v4/introduction/introduction.md | 4 ++-- docs/book/v4/introduction/server-requirements.md | 5 ++--- docs/book/v4/tutorials/create-book-module.md | 6 ++---- mkdocs.yml | 4 ++-- 6 files changed, 10 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 60b8d9b..b925fbc 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Based on Enrico Zimuel's [Zend Expressive API - Skeleton example](https://github [![GitHub stars](https://img.shields.io/github/stars/dotkernel/api)](https://github.com/dotkernel/api/stargazers) [![GitHub license](https://img.shields.io/github/license/dotkernel/api)](https://github.com/dotkernel/api/blob/4.0/LICENSE.md) -[![Build Static](https://github.com/dotkernel/api/actions/workflows/static-analysis.yml/badge.svg?branch=4.0)](https://github.com/dotkernel/api/actions/workflows/static-analysis.yml) +[![Build Static](https://github.com/dotkernel/api/actions/workflows/continuous-integration.yml/badge.svg?branch=4.0)](https://github.com/dotkernel/api/actions/workflows/continuous-integration.yml) [![Build Static](https://github.com/dotkernel/api/actions/workflows/run-tests.yml/badge.svg?branch=4.0)](https://github.com/dotkernel/api/actions/workflows/run-tests.yml) [![codecov](https://codecov.io/gh/dotkernel/api/graph/badge.svg?token=53FN78G5CK)](https://codecov.io/gh/dotkernel/api) [![Qodana](https://github.com/dotkernel/api/actions/workflows/qodana_code_quality.yml/badge.svg)](https://github.com/dotkernel/api/actions/workflows/qodana_code_quality.yml) diff --git a/docs/book/v4/introduction/file-structure.md b/docs/book/v4/introduction/file-structure.md index 0283758..177143c 100644 --- a/docs/book/v4/introduction/file-structure.md +++ b/docs/book/v4/introduction/file-structure.md @@ -2,7 +2,7 @@ It is a good practice to standardize the file structure of projects. This way it’s easier to keep a clean overview of multiple projects, and less time is wasted trying to find the correct class. -When using DotKernel 3 API the following structure is recommended: +When using DotKernel API the following structure is recommended: ## Main directories diff --git a/docs/book/v4/introduction/introduction.md b/docs/book/v4/introduction/introduction.md index 3e9e209..9bba1b7 100644 --- a/docs/book/v4/introduction/introduction.md +++ b/docs/book/v4/introduction/introduction.md @@ -48,11 +48,11 @@ By using `MezzioCorsMiddlewareCorsMiddleware`, the CORS preflight will be recogn ## OAuth 2 -OAuth 2 is an authorization framework that enables applications to obtain limited access to user accounts on your Dotkernel API. We are using mezzio/mezzio-authentication-oauth2 which provides OAuth2 authentication for Mezzio and PSR-7/PSR-15 applications by using league/oauth2-server package. +OAuth 2 is an authorization framework that enables applications to obtain limited access to user accounts on your DotKernel API. We are using mezzio/mezzio-authentication-oauth2 which provides OAuth2 authentication for Mezzio and PSR-7/PSR-15 applications by using league/oauth2-server package. ## Email -It is not unlikely for an API to send emails depending on the use case. Here is another area where Dotkernel API shines. Using `DotMailServiceMailService` provided by dotkernel/dot-mail you can easily send custom email templates. +It is not unlikely for an API to send emails depending on the use case. Here is another area where DotKernel API shines. Using `DotMailServiceMailService` provided by dotkernel/dot-mail you can easily send custom email templates. ## Configuration diff --git a/docs/book/v4/introduction/server-requirements.md b/docs/book/v4/introduction/server-requirements.md index 1a06768..789238b 100644 --- a/docs/book/v4/introduction/server-requirements.md +++ b/docs/book/v4/introduction/server-requirements.md @@ -4,10 +4,9 @@ For production, we highly recommend a *nix based system. ## Webserver -* Apache >= 2.2 +* Apache >= 2.2 **or** Nginx * mod_rewrite * .htaccess support `(AllowOverride All)` -* Nginx ## PHP >= 8.2 @@ -28,7 +27,7 @@ Both mod_php and FCGI (FPM) are supported. ## Recommended extensions * opcache -* pdo_mysql or mysqli (if using MySql or MariaDb as RDBMS) +* pdo_mysql or mysqli (if using MySQL or MariaDB as RDBMS) * dom - if working with markup files structure (html, xml, etc) * simplexml - working with xml files * gd, exif - if working with images diff --git a/docs/book/v4/tutorials/create-book-module.md b/docs/book/v4/tutorials/create-book-module.md index c66c6d1..bd554a0 100644 --- a/docs/book/v4/tutorials/create-book-module.md +++ b/docs/book/v4/tutorials/create-book-module.md @@ -1,4 +1,4 @@ -# Implementing a book module in DotKernel 3 API +# Implementing a book module in DotKernel API ## File structure @@ -534,9 +534,7 @@ It should look like this: 'paths' => __DIR__ . '/../../src/Book/src/Entity', ], -* add this under the `doctrine.driver` key: - - ``'Api\\Book\Entity' => 'BookEntities',`` add this under the `doctrine.driver.drivers` class +* `Api\\Book\Entity' => 'BookEntities',` add this under the `doctrine.driver.drivers` key Example: diff --git a/mkdocs.yml b/mkdocs.yml index 9b5d8f1..65010a9 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,7 +1,7 @@ docs_dir: docs/book site_dir: docs/html extra: - project: DotKernel 3 API + project: DotKernel API current_version: v4 versions: - v4 @@ -18,7 +18,7 @@ nav: - Tutorials: - "Creating a book module": v4/tutorials/create-book-module.md site_name: api -site_description: "DotKernel 3 API" +site_description: "DotKernel API" repo_url: "https://github.com/dotkernel/api" plugins: - search From b528101b39447dd0041caaaecf7a5295578173b1 Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Fri, 3 May 2024 12:07:05 +0300 Subject: [PATCH 46/48] documentation linting fix --- docs/book/v4/introduction/file-structure.md | 2 +- docs/book/v4/tutorials/create-book-module.md | 4 ++-- mkdocs.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/book/v4/introduction/file-structure.md b/docs/book/v4/introduction/file-structure.md index 177143c..6ac3990 100644 --- a/docs/book/v4/introduction/file-structure.md +++ b/docs/book/v4/introduction/file-structure.md @@ -39,7 +39,7 @@ The `src` directory should also contain 2 files: This directory contains the template files, used for example to help render e-mail templates. -> DotKernel3 API uses twig as Templating Engine. All template files have the extension .html.twig +> DotKernel API uses twig as Templating Engine. All template files have the extension .html.twig ## The `data` directory diff --git a/docs/book/v4/tutorials/create-book-module.md b/docs/book/v4/tutorials/create-book-module.md index bd554a0..4dca277 100644 --- a/docs/book/v4/tutorials/create-book-module.md +++ b/docs/book/v4/tutorials/create-book-module.md @@ -597,10 +597,10 @@ To execute the migrations run: If we did everything as planned we can call the `http://localhost/books` endpoint and create a new book: - curl -X POST http://localhost/book + curl -X POST http://0.0.0.0:8080/book -H "Content-Type: application/json" -d '{"name": "test", "author": "author name", "releaseDate": "2023-03-03"}' To list the books use : - curl http://localhost/books + curl http://0.0.0.0:8080/books diff --git a/mkdocs.yml b/mkdocs.yml index 65010a9..ec0644c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,7 +1,7 @@ docs_dir: docs/book site_dir: docs/html extra: - project: DotKernel API + project: "DotKernel API" current_version: v4 versions: - v4 From 6a2571ea82d4b2aa7d2012a8e75907bfd392be0e Mon Sep 17 00:00:00 2001 From: MarioRadu Date: Fri, 3 May 2024 12:11:03 +0300 Subject: [PATCH 47/48] documentation linting fix --- README.md | 2 +- docs/book/v4/introduction/installation.md | 2 +- docs/book/v4/tutorials/create-book-module.md | 2 +- documentation/README.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b925fbc..f82fd80 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ More details on how fixtures work can be found here: https://github.com/dotkerne php -S 0.0.0.0:8080 -t public -Sending a GET request to the [home page](http://localhost:8080/) should output the following message: +Sending a GET request to the [home page](http://0.0.0.0:8080/) should output the following message: { "message": "Welcome to DotKernel API!" diff --git a/docs/book/v4/introduction/installation.md b/docs/book/v4/introduction/installation.md index c395411..2e11b81 100644 --- a/docs/book/v4/introduction/installation.md +++ b/docs/book/v4/introduction/installation.md @@ -66,7 +66,7 @@ More details on how fixtures work can be found here: https://github.com/dotkerne php -S 0.0.0.0:8080 -t public -Sending a GET request to the [home page](http://localhost:8080/) should output the following message: +Sending a GET request to the [home page](http://0.0.0.0:8080/) should output the following message: { "message": "Welcome to DotKernel API!" diff --git a/docs/book/v4/tutorials/create-book-module.md b/docs/book/v4/tutorials/create-book-module.md index 4dca277..2698b82 100644 --- a/docs/book/v4/tutorials/create-book-module.md +++ b/docs/book/v4/tutorials/create-book-module.md @@ -595,7 +595,7 @@ To execute the migrations run: ## Checking endpoints -If we did everything as planned we can call the `http://localhost/books` endpoint and create a new book: +If we did everything as planned we can call the `http://0.0.0.0:8080/books` endpoint and create a new book: curl -X POST http://0.0.0.0:8080/book -H "Content-Type: application/json" diff --git a/documentation/README.md b/documentation/README.md index cbb02ed..0f6968c 100644 --- a/documentation/README.md +++ b/documentation/README.md @@ -17,7 +17,7 @@ At this point, we assume you already have Postman installed. The following steps You should see a new collection (`DotKernel_API`) added to your collection list, containing the documentation of all DotKernel API endpoints. Also, you should see a new environment (`DotKernel_API`) added to your environments. -This contains a variable, called `APPLICATION_URL` set to `http://localhost:8080`. +This contains a variable, called `APPLICATION_URL` set to `http://0.0.0.0:8080`. If your application runs on a different URL/port, modify this variable accordingly. ## Usage From 0ae59399bda43d2e52752f8edb494cd3e98217f4 Mon Sep 17 00:00:00 2001 From: Alex Karajos Date: Fri, 3 May 2024 12:22:27 +0300 Subject: [PATCH 48/48] Update docs/book/v4/tutorials/create-book-module.md --- docs/book/v4/tutorials/create-book-module.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/book/v4/tutorials/create-book-module.md b/docs/book/v4/tutorials/create-book-module.md index 2698b82..eb1fac9 100644 --- a/docs/book/v4/tutorials/create-book-module.md +++ b/docs/book/v4/tutorials/create-book-module.md @@ -595,7 +595,7 @@ To execute the migrations run: ## Checking endpoints -If we did everything as planned we can call the `http://0.0.0.0:8080/books` endpoint and create a new book: +If we did everything as planned we can call the `http://0.0.0.0:8080/book` endpoint and create a new book: curl -X POST http://0.0.0.0:8080/book -H "Content-Type: application/json"