├── .env.dist ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── apache ├── conf │ └── 000-default.conf └── php │ └── php.ini ├── app └── config │ ├── bootstrap.php │ ├── config.php │ └── routing.php ├── codeception.yml ├── composer.json ├── composer.lock ├── docker-compose.yml ├── mysql ├── data │ └── status.sql ├── rebuild.sql └── schema │ ├── customer.sql │ ├── invoice.sql │ ├── invoice_item.sql │ └── status.sql ├── notes.php ├── public ├── .htaccess ├── 404.html ├── assets │ └── css │ │ └── .gitkeep ├── index.php └── views │ ├── home │ └── index.php │ ├── invoice │ ├── dashboard.php │ ├── edit.php │ └── index.php │ └── templates │ ├── base.php │ └── primary-menu.php ├── src ├── Controller │ ├── AbstractController.php │ ├── Home.php │ └── Invoice.php ├── DB │ ├── Builder │ │ ├── Builder.php │ │ ├── CollectionInterface.php │ │ ├── FieldCollection.php │ │ └── WhereCollection.php │ ├── Connection.php │ ├── QueryBuilder.php │ ├── QueryBuilderInterface.php │ └── QueryCreate.php ├── Entity │ ├── AbstractEntity.php │ ├── Customer.php │ ├── GenericEntityInterface.php │ ├── Invoice.php │ ├── InvoiceItem.php │ └── Status.php ├── Form │ └── .gitkeep ├── Helper │ ├── .gitkeep │ ├── HTTP │ │ ├── Locator │ │ │ └── Locator.php │ │ ├── Request │ │ │ ├── Factory │ │ │ │ ├── FactoryInterface.php │ │ │ │ └── Type │ │ │ │ │ └── ServerFactory.php │ │ │ ├── Request.php │ │ │ └── RequestAdaptorInterface.php │ │ ├── Response │ │ │ └── View.php │ │ ├── Route │ │ │ ├── Factory.php │ │ │ ├── Route.php │ │ │ ├── Router.php │ │ │ └── Validator.php │ │ ├── URI │ │ │ └── URIBuilder.php │ │ └── Validation │ │ │ ├── AbstractType.php │ │ │ ├── InterfaceValidator.php │ │ │ ├── Type │ │ │ ├── ActionValidator.php │ │ │ ├── ControllerValidator.php │ │ │ ├── MethodValidator.php │ │ │ └── PatternValidator.php │ │ │ └── Validation.php │ └── Kernel │ │ └── Kernel.php ├── Hydration │ ├── AbstractHydrator.php │ ├── CustomerHydrator.php │ ├── InvoiceHydrator.php │ ├── InvoiceItemHydrator.php │ └── StatusHydrator.php ├── Manager │ ├── AbstractManager.php │ ├── CustomerManager.php │ ├── InvoiceItemManager.php │ ├── InvoiceManager.php │ ├── ManagerInterface.php │ └── StatusManager.php └── Repository │ ├── AbstractRepository.php │ ├── CustomerRepository.php │ ├── InvoiceItemRepository.php │ ├── InvoiceRepository.php │ ├── RepositoryFactory.php │ ├── RepositoryInterface.php │ └── StatusRepository.php └── tests ├── .DS_Store ├── _data ├── .gitkeep └── dump.sql ├── _output └── .gitignore ├── _support ├── AcceptanceTester.php ├── Code.php ├── FunctionalTester.php ├── Helper │ ├── Acceptance.php │ ├── Functional.php │ ├── Integration.php │ └── Unit.php ├── UnitTester.php └── _generated │ └── .gitignore ├── acceptance.suite.yml ├── acceptance ├── DBCustomerEntityCest.php ├── DBInvoiceEntityCest.php ├── DBStatusCest.php ├── DBStatusEntityCest.php ├── HomePageCest.php ├── InvoicePageCest.php └── NotFoundPageCest.php ├── functional.suite.yml ├── integration.suite.yml ├── integration ├── DBCustomerEntityTest.php ├── DBInvoiceEntityTest.php ├── DBInvoiceItemEntityTest.php └── DBStatusEntityTest.php ├── unit.suite.yml └── unit ├── DB ├── BuilderTest.php ├── ConnectionTest.php ├── FieldCollectionTest.php ├── QueryBuilderTest.php ├── StatusQueryBuilderTest.php └── WhereCollectionTest.php ├── Entity ├── AddCustomerToInvoiceTest.php ├── AddInvoiceItemToInvoiceTest.php ├── CustomerTest.php ├── InvoiceItemTest.php ├── InvoiceTest.php ├── SetStatusToInvoiceTest.php └── StatusTest.php ├── Helper └── HTTP │ ├── Locator │ └── LocatorTest.php │ ├── Request │ ├── Factory │ │ └── Type │ │ │ └── ServerFactoryTest.php │ └── RequestTest.php │ ├── Route │ ├── FactoryTest.php │ ├── RouteTest.php │ └── RouterTest.php │ ├── URI │ └── URIBuilderTest.php │ └── Validation │ ├── Type │ ├── ActionValidatorTest.php │ ├── ControllerValidatorTest.php │ ├── MethodValidatorTest.php │ └── PatternValidatorTest.php │ └── ValidationTest.php └── Hydrator ├── CustomerTest.php ├── InvoiceItemTest.php ├── InvoiceTest.php └── StatusTest.php /.env.dist: -------------------------------------------------------------------------------- 1 | # Development 2 | DEV_MYSQL_ROOT_PASSWORD=test 3 | DEV_MYSQL_DATABASE=invoice_app 4 | DEV_MYSQL_USERNAME=root 5 | DEV_MYSQL_HOST=db 6 | 7 | # Test 8 | TEST_MYSQL_ROOT_PASSWORD=test 9 | TEST_MYSQL_DATABASE=test_invoice_app 10 | TEST_MYSQL_USERNAME=root 11 | TEST_MYSQL_HOST=db_test 12 | 13 | ENV=TEST -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | !.gitkeep 3 | .env 4 | /vendor/ 5 | notes.php 6 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:7.3-apache 2 | 3 | LABEL maintainer="Peter Fisher" 4 | 5 | RUN apt-get update \ 6 | && apt-get install -y \ 7 | git \ 8 | zlib1g-dev \ 9 | zip \ 10 | unzip \ 11 | libxml2-dev \ 12 | libgd-dev \ 13 | libpng-dev \ 14 | libfreetype6-dev \ 15 | libjpeg62-turbo-dev \ 16 | libzip-dev \ 17 | && pecl install xdebug \ 18 | && docker-php-ext-install mysqli pdo_mysql iconv simplexml \ 19 | && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \ 20 | && docker-php-ext-configure zip --with-libzip \ 21 | && docker-php-ext-install gd zip \ 22 | && docker-php-ext-enable xdebug \ 23 | && apt-get clean all \ 24 | && rm -rvf /var/lib/apt/lists/* \ 25 | && a2enmod rewrite headers 26 | 27 | RUN curl -sS https://getcomposer.org/installer | php -- --filename=composer --install-dir=/bin 28 | ENV PATH /root/.composer/vendor/bin:$PATH 29 | 30 | WORKDIR /var/www/html -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Peter Fisher 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FreeCodeCamp PHP OOP Course 2 | ### By Peter Fisher How To Code Well 3 | 4 | - [Installation](#installation) 5 | - [Database](#database) 6 | - [Requirements](#requirements) 7 | - [Testing](#testing) 8 | 9 | ## Installation 10 | Create `.env` 11 | ``` 12 | $ cp .env.dist .env 13 | ``` 14 | Modify values in `.env` 15 | 16 | Creating Docker Machine (Optional) 17 | ``` 18 | $ docker-machine create howtocodewell-oop-php 19 | $ docker-machine env howtocodewell-oop-php 20 | $ eval $(docker-machine env howtocodewell-oop-php) 21 | ``` 22 | 23 | Create the containers and build the images 24 | ``` 25 | $ docker-compose up -d --build 26 | ``` 27 | 28 | Find IP of Docker machine 29 | ``` 30 | $ docker-machine ip howtocodewell-oop-php 31 | 192.168.99.100 32 | ``` 33 | 34 | Put the IP in a browser 35 | 36 | ### Database 37 | *Please note: This will delete the database and create a new one. All data will be lost* 38 | 39 | To rebuild the database run the following command from the host machine. (Change ) 40 | ``` 41 | $ docker-compose exec -T db mysql -u root --password= < mysql/rebuild.sql 42 | ``` 43 | Or from within the container 44 | ``` 45 | $ docker-compose exec db mysql -u root -p 46 | Enter password: 47 | 48 | mysql> use invoice_app; 49 | mysql> source /scripts/rebuild.sql 50 | ``` 51 | ## Requirements 52 | - Docker 18.09.2 53 | - Docker Machine 0.16.1 (Optional) 54 | - Docker Compose 1.23.2 55 | 56 | ## Testing 57 | Run unit tests 58 | ``` 59 | $ docker-compose exec web vendor/bin/codecept run unit 60 | ``` 61 | 62 | Run unit tests with code coverage 63 | ``` 64 | $ docker-compose exec web vendor/bin/codecept run unit --coverage --coverage-xml --coverage-html 65 | $ open tests/_output/coverage/index.html 66 | ``` 67 | 68 | Run acceptance tests 69 | ``` 70 | $ docker-compose exec web vendor/bin/codecept run acceptance 71 | ``` -------------------------------------------------------------------------------- /apache/conf/000-default.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | ServerAdmin webmaster@localhost 4 | ServerName invoice-test 5 | DocumentRoot ${APACHE_DOCUMENT_ROOT} 6 | 7 | 8 | Options Indexes FollowSymLinks 9 | AllowOverride All 10 | Require all granted 11 | 12 | 13 | ErrorLog ${APACHE_LOG_DIR}/error.log 14 | CustomLog ${APACHE_LOG_DIR}/access.log combined 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/config/bootstrap.php: -------------------------------------------------------------------------------- 1 | setValidators([ 14 | new Type\PatternValidator(), 15 | new Type\ControllerValidator(), 16 | new Type\ActionValidator() 17 | ]); 18 | 19 | // Make routes 20 | $routeFactory = new Factory(); 21 | $routes = $routeFactory->makeRoutes($routeData); 22 | Validator::validate($routes, $validation); 23 | 24 | return $routes; 25 | -------------------------------------------------------------------------------- /app/config/config.php: -------------------------------------------------------------------------------- 1 | '/', 8 | 'controller' => Controller\Home::class, 9 | 'method' => ['GET'], 10 | 'action' => 'index' 11 | ], 12 | [ 13 | 'pattern' => '/invoice', 14 | 'controller' => Controller\Invoice::class, 15 | 'method' => ['GET'], 16 | 'action' => 'dashboard' 17 | ], 18 | [ 19 | 'pattern' => '/invoice/{id}', 20 | 'controller' => Controller\Invoice::class, 21 | 'method' => ['GET'], 22 | 'action' => 'index', 23 | 'parameters' => [ 24 | 'id' => '([0-9]*)' 25 | ] 26 | ], 27 | [ 28 | 'pattern' => '/invoice/{id}/edit', 29 | 'controller' => Controller\Invoice::class, 30 | 'method' => ['GET'], 31 | 'action' => 'edit', 32 | 'parameters' => [ 33 | 'id' => '([0-9]*)' 34 | ] 35 | ], 36 | ]; -------------------------------------------------------------------------------- /codeception.yml: -------------------------------------------------------------------------------- 1 | paths: 2 | tests: tests 3 | output: tests/_output 4 | data: tests/_data 5 | support: tests/_support 6 | envs: tests/_envs 7 | actor_suffix: Tester 8 | extensions: 9 | enabled: 10 | - Codeception\Extension\RunFailed 11 | coverage: 12 | enabled: true 13 | include: 14 | - src/* -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "howtocodewell/oop-php", 3 | "type": "project", 4 | "license": "MIT", 5 | "require": { 6 | "ext-pdo": "*" 7 | }, 8 | "autoload": { 9 | "psr-4": { 10 | "App\\": "src/" 11 | } 12 | }, 13 | "require-dev": { 14 | "codeception/codeception": "^3.0", 15 | "phpstan/phpstan": "^0.11.8", 16 | "phpunit/phpunit": "8.1.*" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | volumes: 4 | mysql_data: 5 | mysql_data_test: 6 | 7 | networks: 8 | php_course: 9 | 10 | services: 11 | web: 12 | build: 13 | context: . 14 | ports: 15 | - 80:80 16 | volumes: 17 | - .:/var/www/html 18 | - ./apache/conf/000-default.conf:/etc/apache2/sites-enabled/000-default.conf 19 | - ./apache/php/php.ini:/usr/local/etc/php/php.ini 20 | 21 | environment: 22 | - APACHE_DOCUMENT_ROOT=/var/www/html/public 23 | env_file: 24 | - .env 25 | restart: always 26 | networks: 27 | - php_course 28 | 29 | db: 30 | image: mysql:5.7 31 | volumes: 32 | - mysql_data:/var/lib/mysql 33 | - ./mysql:/scripts 34 | environment: 35 | - MYSQL_DATABASE=${DEV_MYSQL_DATABASE} 36 | - MYSQL_ROOT_PASSWORD=${DEV_MYSQL_ROOT_PASSWORD} 37 | networks: 38 | - php_course 39 | restart: always 40 | 41 | 42 | db_test: 43 | image: mysql:5.7 44 | volumes: 45 | - mysql_data_test:/var/lib/mysql 46 | - ./mysql:/scripts 47 | environment: 48 | - MYSQL_DATABASE=${TEST_MYSQL_DATABASE} 49 | - MYSQL_ROOT_PASSWORD=${TEST_MYSQL_ROOT_PASSWORD} 50 | networks: 51 | - php_course 52 | restart: always 53 | -------------------------------------------------------------------------------- /mysql/data/status.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO `status` (`name`, `internal_name`) 2 | VALUES 3 | ('Draft', 'DRAFT'), 4 | ('Sent', 'SENT'), 5 | ('Overdue', 'OVERDUE') 6 | ; 7 | -------------------------------------------------------------------------------- /mysql/rebuild.sql: -------------------------------------------------------------------------------- 1 | DROP DATABASE IF EXISTS `invoice_app`; 2 | CREATE DATABASE `invoice_app`; 3 | 4 | use `invoice_app`; 5 | 6 | -- Build the tables 7 | source /scripts/schema/status.sql 8 | source /scripts/schema/customer.sql 9 | source /scripts/schema/invoice.sql 10 | source /scripts/schema/invoice_item.sql 11 | 12 | -- Insert data 13 | source /scripts/data/status.sql -------------------------------------------------------------------------------- /mysql/schema/customer.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS `customer`; 2 | 3 | CREATE TABLE IF NOT EXISTS `customer` ( 4 | `id` int(11) NOT NULL auto_increment, 5 | `company_name` varchar(250) NOT NULL, 6 | `first_name` varchar(250) NOT NULL, 7 | `last_name` varchar(250) NULL, 8 | `date_created` DATETIME DEFAULT CURRENT_TIMESTAMP, 9 | `date_updated` DATETIME ON UPDATE CURRENT_TIMESTAMP, 10 | PRIMARY KEY (`id`) 11 | ); 12 | -------------------------------------------------------------------------------- /mysql/schema/invoice.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS `invoice`; 2 | 3 | CREATE TABLE IF NOT EXISTS `invoice` ( 4 | `id` INT (11) NOT NULL auto_increment, 5 | `reference` VARCHAR (250) NOT NULL, 6 | `total` DECIMAL, 7 | `vat` DECIMAL, 8 | `status_id` INT(11), 9 | `customer_id` INT(11) NULL, 10 | `date_created` DATETIME DEFAULT CURRENT_TIMESTAMP, 11 | `date_updated` DATETIME ON UPDATE CURRENT_TIMESTAMP, 12 | FOREIGN KEY fk_status(status_id) 13 | REFERENCES status(id), 14 | FOREIGN KEY fk_customer(customer_id) 15 | REFERENCES customer(id), 16 | PRIMARY KEY (id) 17 | ); 18 | -------------------------------------------------------------------------------- /mysql/schema/invoice_item.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS `invoice_item`; 2 | 3 | CREATE TABLE IF NOT EXISTS `invoice_item` ( 4 | `id` INT (11) NOT NULL auto_increment, 5 | `reference` VARCHAR (250) NULL, 6 | `description` VARCHAR (250) NOT NULL, 7 | `unit_price` DECIMAL NOT NULL, 8 | `units` INT(11) NOT NULL, 9 | `total` DECIMAL NOT NULL, 10 | `invoice_id` INT(11) NOT NULL, 11 | `date_created` DATETIME DEFAULT CURRENT_TIMESTAMP, 12 | `date_updated` DATETIME ON UPDATE CURRENT_TIMESTAMP, 13 | FOREIGN KEY fk_invoice(invoice_id) 14 | REFERENCES invoice(id), 15 | PRIMARY KEY (id) 16 | ); 17 | -------------------------------------------------------------------------------- /mysql/schema/status.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS `status`; 2 | 3 | CREATE TABLE IF NOT EXISTS `status` ( 4 | `id` int(11) NOT NULL auto_increment, 5 | `name` varchar(250) NOT NULL, 6 | `internal_name` varchar(250) NOT NULL, 7 | `date_created` DATETIME DEFAULT CURRENT_TIMESTAMP, 8 | `date_updated` DATETIME ON UPDATE CURRENT_TIMESTAMP, 9 | PRIMARY KEY (`id`) 10 | ); 11 | -------------------------------------------------------------------------------- /notes.php: -------------------------------------------------------------------------------- 1 | getDoctrine()->getRepository(\App\Entity\Status::class)->findAll() 32 | * $this->repostioryFactory()->make(\App\Entity\Status::class)->findAll() 33 | * 34 | * $this->getDB()->getRepository(\App\Entity\Invoice::class)->findAll(); 35 | * 36 | * $this->repositoryLoader->getStatus()->findAll(); 37 | * 38 | * @todo Add abstraction layer for managers to allow controller to pull out 39 | * managers from a factory 40 | * $this->getDB()->getManager(\App\Entity\Status::class)->save($status); 41 | * 42 | * 43 | * 44 | */ 45 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | DirectoryIndex index.php 2 | ErrorDocument 404 /var/www/html/public/404.html 3 | 4 | # Enable rewrite engine 5 | RewriteEngine on 6 | 7 | # Set the base 8 | RewriteBase / 9 | 10 | # Deliver files and folders if they exist 11 | RewriteCond %{REQUEST_FILENAME} !-f 12 | RewriteCond %{REQUEST_FILENAME} !-d 13 | 14 | # Push every request to the index.php 15 | RewriteRule ^(.*)$ index.php [QSA] 16 | -------------------------------------------------------------------------------- /public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Page Not Found 6 | 7 | 8 |

Page Not Found

9 | 10 | -------------------------------------------------------------------------------- /public/assets/css/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pfwd/freecodecamp-PHP-OOP/d211e83f2fec6d314226728dc29cbd985fa384fa/public/assets/css/.gitkeep -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | getCode() === 404) { 10 | header("HTTP/1.0 404 Not Found"); 11 | exit; 12 | } 13 | } 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /public/views/home/index.php: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /public/views/invoice/edit.php: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Home Page 7 | 8 | 9 |
10 |
11 | 14 |
15 |
16 | 17 |
18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /public/views/templates/primary-menu.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Controller/AbstractController.php: -------------------------------------------------------------------------------- 1 | $request->getParameter('id') 13 | ] 14 | ); 15 | } 16 | 17 | public function edit(Request $request) 18 | { 19 | return View::render('views/invoice/edit.php',[ 20 | 'id' => $request->getParameter('id') 21 | ] 22 | ); 23 | } 24 | 25 | public function dashboard(Request $request) 26 | { 27 | return View::render('views/invoice/dashboard.php'); 28 | } 29 | } -------------------------------------------------------------------------------- /src/DB/Builder/Builder.php: -------------------------------------------------------------------------------- 1 | collections as $collection) { 16 | if($collection instanceof $className) { 17 | $found = $collection; 18 | break; 19 | } 20 | } 21 | 22 | if(FALSE === $found instanceof CollectionInterface) { 23 | $found = new $className(); 24 | $this->collections[] = $found; 25 | } 26 | 27 | return $found; 28 | } 29 | 30 | /** 31 | * @return WhereCollection 32 | */ 33 | public function where(): WhereCollection 34 | { 35 | 36 | return $this->make(WhereCollection::class); 37 | } 38 | 39 | /** 40 | * @return FieldCollection 41 | */ 42 | public function fields(): FieldCollection 43 | { 44 | return $this->make(FieldCollection::class); 45 | } 46 | } -------------------------------------------------------------------------------- /src/DB/Builder/CollectionInterface.php: -------------------------------------------------------------------------------- 1 | fields[] = $name; 19 | return $this; 20 | } 21 | 22 | /** 23 | * @param array $fields 24 | * @return FieldCollection 25 | */ 26 | public function set(array $fields = []):CollectionInterface 27 | { 28 | $this->fields = []; 29 | for ($i = 0; $i < count($fields); $i++) { 30 | $this->add($fields[$i]); 31 | } 32 | return $this; 33 | } 34 | 35 | /** 36 | * @return string 37 | */ 38 | public function getSQL(): string 39 | { 40 | $sql = '*'; 41 | if(count($this->fields) > 0) { 42 | $sql = ''; 43 | for ($i = 0; $i < count($this->fields); $i++) { 44 | if ($i > 0) { 45 | $sql .= ", "; 46 | } 47 | $sql .= "`" . $this->fields[$i] . "`"; 48 | } 49 | } 50 | return $sql; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/DB/Builder/WhereCollection.php: -------------------------------------------------------------------------------- 1 | whereClause[$field] = $value; 20 | return $this; 21 | } 22 | 23 | /** 24 | * @param array $where 25 | * @return WhereCollection 26 | */ 27 | public function set(array $where = []): CollectionInterface 28 | { 29 | $this->whereClause = $where; 30 | 31 | return $this; 32 | } 33 | 34 | /** 35 | * @return string 36 | */ 37 | public function getSQL(): string 38 | { 39 | $sql = ''; 40 | $counter = 0; 41 | $count = count($this->whereClause); 42 | 43 | if($count > 0) { 44 | $sql.='WHERE '; 45 | } 46 | foreach ($this->whereClause as $field => $value) { 47 | $counter++; 48 | $sql .= '`' . $field . '` =:' . $field; 49 | 50 | if ($counter < $count) { 51 | $sql .= ' AND '; 52 | } 53 | 54 | } 55 | return $sql; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/DB/Connection.php: -------------------------------------------------------------------------------- 1 | env = $env; 23 | } 24 | 25 | public function getCreds():array 26 | { 27 | return [ 28 | 'username' => getenv( strtoupper($this->env) . '_MYSQL_USERNAME'), 29 | 'password' => getenv(strtoupper($this->env) . '_MYSQL_ROOT_PASSWORD'), 30 | 'host' => getenv(strtoupper($this->env) . '_MYSQL_HOST'), 31 | 'database' => getenv(strtoupper($this->env) . '_MYSQL_DATABASE') 32 | ]; 33 | } 34 | 35 | /** 36 | * @return PDO 37 | */ 38 | public function open():PDO 39 | { 40 | $creds = $this->getCreds(); 41 | 42 | if(!self::$conn instanceof PDO) { 43 | $username = $creds['username']; 44 | $password = $creds['password']; 45 | $host = $creds['host']; 46 | $database = $creds['database']; 47 | 48 | $dsn = 'mysql:host=' . $host . ';dbname=' . $database; 49 | 50 | self::$conn = new PDO($dsn, $username, $password); 51 | } 52 | return self::$conn; 53 | } 54 | } -------------------------------------------------------------------------------- /src/DB/QueryBuilder.php: -------------------------------------------------------------------------------- 1 | 0) { 43 | $sql .= ", "; 44 | } 45 | $sql .= ':'.$placeholders[$i]; 46 | } 47 | 48 | return $sql; 49 | } 50 | 51 | /** 52 | * @param array $data 53 | * @return string 54 | */ 55 | public static function fields(array $data = []):string 56 | { 57 | $placeholders = array_keys($data); 58 | $sql = ''; 59 | for ($i = 0; $i < count($placeholders); $i++) { 60 | if ($i > 0) { 61 | $sql .= ", "; 62 | } 63 | $sql .= "`".$placeholders[$i]."`"; 64 | } 65 | 66 | return $sql; 67 | } 68 | 69 | 70 | /** 71 | * @param array $data 72 | * @return string 73 | */ 74 | public static function updatePlaceholders(array $data = []):string 75 | { 76 | $sql = ''; 77 | $counter = 0; 78 | $total = count($data); 79 | foreach($data as $field => $value) { 80 | $counter ++; 81 | $sql.='`'.$field.'` =:'.$field; 82 | if($counter < $total) { 83 | $sql.= ', '; 84 | } else{ 85 | $sql.= ' '; 86 | } 87 | } 88 | return $sql; 89 | } 90 | 91 | /** 92 | * @param array $data 93 | * @param string $table 94 | * @param array $where 95 | * @return string 96 | */ 97 | public static function insertOrUpdate(array $data, string $table, array $where = []): string 98 | { 99 | if(empty($where)) { 100 | $sql = self::insert($data, $table); 101 | } else { 102 | $sql = self::update($data, $table, $where); 103 | } 104 | 105 | return $sql; 106 | } 107 | 108 | /** 109 | * @param string $table 110 | * @return string 111 | */ 112 | public static function findOneBy(string $table) 113 | { 114 | return "SELECT * FROM `".$table."` WHERE id=:id"; 115 | } 116 | 117 | /** 118 | * @param string $table 119 | * @return string 120 | */ 121 | public static function findAll(string $table) 122 | { 123 | return "SELECT * FROM `".$table."`"; 124 | } 125 | 126 | /** 127 | * @param array $conditions 128 | * @return string 129 | */ 130 | public static function where(array $conditions = []) { 131 | $sql =''; 132 | 133 | $total = count($conditions); 134 | $num = 0; 135 | foreach($conditions as $field => $value) { 136 | $num ++; 137 | $sql.='`'.$field.'` =:'.$field; 138 | if($num < $total) { 139 | $sql.=' AND '; 140 | } 141 | 142 | } 143 | 144 | return $sql; 145 | } 146 | 147 | /** 148 | * @param string $table 149 | * @param array $where 150 | * @return string 151 | */ 152 | public static function findAllBy(string $table, array $where = []) 153 | { 154 | $sql = "SELECT * FROM `".$table."` WHERE " .self::where($where); 155 | 156 | return $sql; 157 | } 158 | } -------------------------------------------------------------------------------- /src/DB/QueryBuilderInterface.php: -------------------------------------------------------------------------------- 1 | builder = $builder; 14 | } 15 | 16 | private $sql = ''; 17 | 18 | /** 19 | * @param string $tableName 20 | * @param array $fields 21 | * @return QueryBuilderInterface 22 | */ 23 | public function select(string $tableName, array $fields = []): QueryBuilderInterface 24 | { 25 | $fieldCollection = $this->builder->fields()->set($fields); 26 | 27 | $this->sql.= "SELECT " . $fieldCollection->getSQL() . " FROM `" . $tableName . "` "; 28 | 29 | return $this; 30 | } 31 | 32 | 33 | 34 | /** 35 | * @param string $field 36 | * @param $value 37 | * @return QueryBuilderInterface 38 | */ 39 | public function andWhere(string $field, $value): QueryBuilderInterface 40 | { 41 | $this->builder->where()->add($field, $value); 42 | 43 | $this->sql.=$this->builder->where()->getSQL(); 44 | 45 | return $this; 46 | } 47 | 48 | /** 49 | * @return string 50 | */ 51 | public function getSQL(): string 52 | { 53 | return trim($this->sql); 54 | } 55 | 56 | 57 | } -------------------------------------------------------------------------------- /src/Entity/AbstractEntity.php: -------------------------------------------------------------------------------- 1 | id; 29 | } 30 | 31 | /** 32 | * @param int|null $id 33 | * @return AbstractEntity 34 | */ 35 | public function setId(?int $id): AbstractEntity 36 | { 37 | $this->id = $id; 38 | return $this; 39 | } 40 | 41 | /** 42 | * @return DateTime|null 43 | */ 44 | public function getDateCreated(): ?DateTime 45 | { 46 | return $this->dateCreated; 47 | } 48 | 49 | /** 50 | * @param DateTime|null $dateCreated 51 | * @return AbstractEntity 52 | */ 53 | public function setDateCreated(?DateTime $dateCreated): AbstractEntity 54 | { 55 | $this->dateCreated = $dateCreated; 56 | return $this; 57 | } 58 | 59 | /** 60 | * @return DateTime|null 61 | */ 62 | public function getDateUpdated(): ?DateTime 63 | { 64 | return $this->dateUpdated; 65 | } 66 | 67 | /** 68 | * @param DateTime|null $dateUpdated 69 | * @return AbstractEntity 70 | */ 71 | public function setDateUpdated(?DateTime $dateUpdated): AbstractEntity 72 | { 73 | $this->dateUpdated = $dateUpdated; 74 | return $this; 75 | } 76 | 77 | 78 | } -------------------------------------------------------------------------------- /src/Entity/Customer.php: -------------------------------------------------------------------------------- 1 | firstName)) { 29 | $names[] = $this->firstName; 30 | } 31 | 32 | if(false === empty($this->lastName)) { 33 | $names[] = $this->lastName; 34 | } 35 | 36 | return implode(' ', $names); 37 | } 38 | 39 | /** 40 | * @return string 41 | */ 42 | public function getCompanyName(): string 43 | { 44 | return $this->companyName; 45 | } 46 | 47 | /** 48 | * @return string 49 | */ 50 | public function getFirstName(): string 51 | { 52 | return $this->firstName; 53 | } 54 | 55 | /** 56 | * @return string 57 | */ 58 | public function getLastName(): string 59 | { 60 | return $this->lastName; 61 | } 62 | 63 | /** 64 | * @param string $companyName 65 | * @return Customer 66 | */ 67 | public function setCompanyName(string $companyName): Customer 68 | { 69 | $this->companyName = $companyName; 70 | return $this; 71 | } 72 | 73 | /** 74 | * @param string $firstName 75 | * @return Customer 76 | */ 77 | public function setFirstName(string $firstName): Customer 78 | { 79 | $this->firstName = $firstName; 80 | return $this; 81 | } 82 | 83 | /** 84 | * @param string $lastName 85 | * @return Customer 86 | */ 87 | public function setLastName(string $lastName): Customer 88 | { 89 | $this->lastName = $lastName; 90 | return $this; 91 | } 92 | 93 | 94 | } -------------------------------------------------------------------------------- /src/Entity/GenericEntityInterface.php: -------------------------------------------------------------------------------- 1 | reference; 42 | } 43 | 44 | /** 45 | * @return null 46 | */ 47 | public function getCustomer() 48 | { 49 | return $this->customer; 50 | } 51 | 52 | /** 53 | * @return array 54 | */ 55 | public function getItems(): array 56 | { 57 | return $this->items; 58 | } 59 | 60 | /** 61 | * @return null|Status 62 | */ 63 | public function getStatus():?Status 64 | { 65 | return $this->status; 66 | } 67 | 68 | /** 69 | * @return float 70 | */ 71 | public function getTotal(): float 72 | { 73 | return $this->total; 74 | } 75 | 76 | /** 77 | * @return float 78 | */ 79 | public function getVat(): float 80 | { 81 | return $this->vat; 82 | } 83 | 84 | /** 85 | * @param string $reference 86 | * 87 | * @return Invoice 88 | */ 89 | public function setReference(string $reference): Invoice 90 | { 91 | $this->reference = $reference; 92 | return $this; 93 | } 94 | 95 | /** 96 | * @param float $total 97 | * 98 | * @return Invoice 99 | */ 100 | public function setTotal(float $total): Invoice 101 | { 102 | $this->total = $total; 103 | return $this; 104 | } 105 | 106 | /** 107 | * @param float $vat 108 | * 109 | * @return Invoice 110 | */ 111 | public function setVAT(float $vat): Invoice 112 | { 113 | $this->vat = $vat; 114 | return $this; 115 | } 116 | 117 | /** 118 | * @param InvoiceItem $invoiceItem 119 | * 120 | * @return Invoice 121 | */ 122 | public function addItem(InvoiceItem $invoiceItem): Invoice 123 | { 124 | if(false === $this->doesItemsContain($invoiceItem)) { 125 | $this->items[] = $invoiceItem; 126 | } 127 | 128 | return $this; 129 | } 130 | 131 | /** 132 | * @param array $items 133 | * @return Invoice 134 | */ 135 | public function setItems(array $items): Invoice 136 | { 137 | $this->resetItems(); 138 | foreach($items as $item) { 139 | $this->addItem($item); 140 | } 141 | return $this; 142 | } 143 | 144 | /** 145 | * @return Invoice 146 | */ 147 | public function resetItems(): Invoice 148 | { 149 | $this->items = []; 150 | return $this; 151 | } 152 | 153 | /** 154 | * @param InvoiceItem $object 155 | * @return bool 156 | */ 157 | public function doesItemsContain(InvoiceItem $object):bool 158 | { 159 | foreach ($this->getItems() as $item) { 160 | if($item === $object) { 161 | return true; 162 | } 163 | } 164 | return false; 165 | } 166 | 167 | /** 168 | * @param null $status 169 | * @return Invoice 170 | */ 171 | public function setStatus($status):Invoice 172 | { 173 | $this->status = $status; 174 | return $this; 175 | } 176 | 177 | /** 178 | * @param null $customer 179 | * @return Invoice 180 | */ 181 | public function setCustomer($customer):Invoice 182 | { 183 | $this->customer = $customer; 184 | return $this; 185 | } 186 | 187 | } -------------------------------------------------------------------------------- /src/Entity/InvoiceItem.php: -------------------------------------------------------------------------------- 1 | reference; 43 | } 44 | 45 | 46 | /** 47 | * @param string $reference 48 | * 49 | * @return InvoiceItem 50 | */ 51 | public function setReference(string $reference): InvoiceItem 52 | { 53 | $this->reference = $reference; 54 | return $this; 55 | } 56 | 57 | /** 58 | * @return string 59 | */ 60 | public function getDescription(): string 61 | { 62 | return $this->description; 63 | } 64 | 65 | /** 66 | * @return float 67 | */ 68 | public function getUnitPrice(): float 69 | { 70 | return $this->unitPrice; 71 | } 72 | 73 | /** 74 | * @return int 75 | */ 76 | public function getUnits(): int 77 | { 78 | return $this->units; 79 | } 80 | 81 | /** 82 | * @return float 83 | */ 84 | public function getTotal(): float 85 | { 86 | return $this->total; 87 | } 88 | 89 | /** 90 | * @param string $description 91 | * @return InvoiceItem 92 | */ 93 | public function setDescription(string $description): InvoiceItem 94 | { 95 | $this->description = $description; 96 | return $this; 97 | } 98 | 99 | /** 100 | * @param int $units 101 | * @return InvoiceItem 102 | */ 103 | public function setUnits(int $units): InvoiceItem 104 | { 105 | $this->units = $units; 106 | return $this; 107 | } 108 | 109 | /** 110 | * @param float $unitPrice 111 | * @return InvoiceItem 112 | */ 113 | public function setUnitPrice(float $unitPrice): InvoiceItem 114 | { 115 | $this->unitPrice = $unitPrice; 116 | return $this; 117 | } 118 | 119 | /** 120 | * @param float $total 121 | * @return InvoiceItem 122 | */ 123 | public function setTotal(float $total): InvoiceItem 124 | { 125 | $this->total = $total; 126 | return $this; 127 | } 128 | 129 | /** 130 | * @return Invoice 131 | */ 132 | public function getInvoice(): Invoice 133 | { 134 | return $this->invoice; 135 | } 136 | 137 | /** 138 | * @param Invoice $invoice 139 | * @return InvoiceItem 140 | */ 141 | public function setInvoice(Invoice $invoice): InvoiceItem 142 | { 143 | $this->invoice = $invoice; 144 | return $this; 145 | } 146 | 147 | 148 | } -------------------------------------------------------------------------------- /src/Entity/Status.php: -------------------------------------------------------------------------------- 1 | name; 22 | } 23 | 24 | /** 25 | * @return string 26 | */ 27 | public function getInternalName(): string 28 | { 29 | return $this->internalName; 30 | } 31 | 32 | /** 33 | * @param string $name 34 | * @return Status 35 | */ 36 | public function setName(string $name): Status 37 | { 38 | $this->name = $name; 39 | $this->setInternalName($name); 40 | return $this; 41 | } 42 | 43 | /** 44 | * @param string $internalName 45 | * @return Status 46 | */ 47 | public function setInternalName(string $internalName): Status 48 | { 49 | $this->internalName = strtoupper(str_replace(' ', '_', $internalName)); 50 | return $this; 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /src/Form/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pfwd/freecodecamp-PHP-OOP/d211e83f2fec6d314226728dc29cbd985fa384fa/src/Form/.gitkeep -------------------------------------------------------------------------------- /src/Helper/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pfwd/freecodecamp-PHP-OOP/d211e83f2fec6d314226728dc29cbd985fa384fa/src/Helper/.gitkeep -------------------------------------------------------------------------------- /src/Helper/HTTP/Locator/Locator.php: -------------------------------------------------------------------------------- 1 | routes = $routes; 29 | 30 | if(null === $request) { 31 | $request = new Request(); 32 | } 33 | 34 | $this->request = $request; 35 | } 36 | 37 | /** 38 | * @param string $URI 39 | * @param string $queryString 40 | * 41 | * @return null|array 42 | */ 43 | public function matchURI(string $URI, string $queryString):?array 44 | { 45 | $foundRoute = null; 46 | preg_match($URI, $queryString, $matches); 47 | 48 | if(false === empty($matches)) { 49 | return $matches; 50 | } 51 | 52 | return null; 53 | } 54 | 55 | /** 56 | * @return Route|null 57 | */ 58 | public function locate():?Route 59 | { 60 | $foundRoute = null; 61 | $queryString = $this->request->getPath(); 62 | 63 | foreach($this->routes as $route) { 64 | 65 | $URI = URIBuilder::build($route->getPattern(), $route->getParameters()); 66 | 67 | $matches = $this->matchURI($URI, $queryString); 68 | if(false === empty($matches)) { 69 | $this->handleRequestParameters($route, $matches); 70 | $foundRoute = $route; 71 | break; 72 | } 73 | } 74 | 75 | return $foundRoute; 76 | } 77 | 78 | /** 79 | * @param Route $route 80 | * @param array $parameters 81 | * 82 | * @return Request 83 | */ 84 | public function handleRequestParameters(Route $route, array $parameters = []): Request 85 | { 86 | if(isset($parameters[0])) { 87 | unset($parameters[0]); 88 | } 89 | 90 | $parameters = array_values($parameters); 91 | 92 | // Parameters: [0] => 123 93 | // $route->getParameters() : ['id'] => ([0-9]*) 94 | // $route->getParameters() Keys : [0] => 'id' 95 | // Updated Parameters ['id'] => 123 96 | // [] = [] 97 | 98 | 99 | $updated = array_combine(array_keys($route->getParameters()), $parameters); 100 | 101 | if($updated) { 102 | $this->request->setParameters($updated); 103 | } 104 | 105 | return $this->request; 106 | } 107 | } -------------------------------------------------------------------------------- /src/Helper/HTTP/Request/Factory/FactoryInterface.php: -------------------------------------------------------------------------------- 1 | setPath($_SERVER['REQUEST_URI']); 28 | $request->setMethod($_SERVER['REQUEST_METHOD']); 29 | 30 | return $request; 31 | 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /src/Helper/HTTP/Request/Request.php: -------------------------------------------------------------------------------- 1 | setPath($queryString); 30 | } 31 | 32 | if( false === empty($method)) { 33 | $this->setMethod($method); 34 | } 35 | } 36 | 37 | /** 38 | * @return string 39 | */ 40 | public function getPath(): string 41 | { 42 | return $this->path; 43 | } 44 | 45 | /** 46 | * @param string $queryString 47 | * @return Request 48 | */ 49 | public function setPath(string $queryString): Request 50 | { 51 | $path = parse_url($queryString, PHP_URL_PATH); 52 | if(false === empty($path)) { 53 | $this->path = $path; 54 | } 55 | 56 | return $this; 57 | } 58 | 59 | /** 60 | * @return string 61 | */ 62 | public function getMethod(): string 63 | { 64 | return $this->method; 65 | } 66 | 67 | /** 68 | * @param string $method 69 | * @return Request 70 | */ 71 | public function setMethod(string $method): Request 72 | { 73 | $this->method = strtoupper($method); 74 | return $this; 75 | } 76 | 77 | /** 78 | * @return array 79 | */ 80 | public function getParameters(): array 81 | { 82 | return $this->parameters; 83 | } 84 | 85 | /** 86 | * @param array $parameters 87 | * @return Request 88 | */ 89 | public function setParameters(array $parameters): Request 90 | { 91 | $this->parameters = $parameters; 92 | foreach($parameters as $key => $value) { 93 | $this->addParameter($key, $value); 94 | } 95 | return $this; 96 | } 97 | 98 | /** 99 | * @param string $key 100 | * @param null|mixed $value 101 | * @return Request 102 | */ 103 | public function addParameter(string $key, $value = null) :Request 104 | { 105 | $this->parameters[$key] = $value; 106 | 107 | return $this; 108 | } 109 | 110 | /** 111 | * @param string $key 112 | * @param null|mixed $default 113 | * 114 | * @return mixed 115 | */ 116 | public function getParameter(string $key, $default = null) 117 | { 118 | $value = $default; 119 | if(isset($this->parameters[$key])) { 120 | $value = $this->parameters[$key]; 121 | } 122 | 123 | return $value; 124 | } 125 | 126 | } -------------------------------------------------------------------------------- /src/Helper/HTTP/Request/RequestAdaptorInterface.php: -------------------------------------------------------------------------------- 1 | routes[] = $this->addRoute($routeData); 21 | } 22 | 23 | return $this->routes; 24 | 25 | } 26 | 27 | /** 28 | * @param array $options 29 | * 30 | * @return null|Route 31 | */ 32 | public function addRoute(array $options):?Route 33 | { 34 | $route = new Route(); 35 | $route->setAction($options['action']) 36 | ->setController($options['controller']) 37 | ->setMethods($options['method']) 38 | ->setPattern($options['pattern']) 39 | ->setParameters((isset($options['parameters']) ? $options['parameters'] : []) ) 40 | ; 41 | 42 | return $route; 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /src/Helper/HTTP/Route/Route.php: -------------------------------------------------------------------------------- 1 | pattern; 34 | } 35 | 36 | /** 37 | * @param string $pattern 38 | * @return Route 39 | */ 40 | public function setPattern(string $pattern): Route 41 | { 42 | $this->pattern = $pattern; 43 | return $this; 44 | } 45 | 46 | /** 47 | * @return string 48 | */ 49 | public function getController(): string 50 | { 51 | return $this->controller; 52 | } 53 | 54 | /** 55 | * @param string $controller 56 | * @return Route 57 | */ 58 | public function setController(string $controller): Route 59 | { 60 | $this->controller = $controller; 61 | return $this; 62 | } 63 | 64 | /** 65 | * @return array 66 | */ 67 | public function getMethods(): array 68 | { 69 | return $this->methods; 70 | } 71 | 72 | /** 73 | * @param array $methods 74 | * @return Route 75 | */ 76 | public function setMethods(array $methods): Route 77 | { 78 | $this->methods = array_map('strtoupper', $methods); 79 | 80 | return $this; 81 | } 82 | 83 | /** 84 | * @return string 85 | */ 86 | public function getAction(): string 87 | { 88 | return $this->action; 89 | } 90 | 91 | /** 92 | * @param string $action 93 | * @return Route 94 | */ 95 | public function setAction(string $action): Route 96 | { 97 | $this->action = $action; 98 | return $this; 99 | } 100 | 101 | /** 102 | * @return array 103 | */ 104 | public function getParameters(): array 105 | { 106 | return $this->parameters; 107 | } 108 | 109 | /** 110 | * @param array $parameters 111 | * @return Route 112 | */ 113 | public function setParameters(array $parameters): Route 114 | { 115 | $this->parameters = $parameters; 116 | return $this; 117 | } 118 | 119 | 120 | } -------------------------------------------------------------------------------- /src/Helper/HTTP/Route/Router.php: -------------------------------------------------------------------------------- 1 | getPattern()] = $route; 16 | } 17 | 18 | /** 19 | * @return array 20 | */ 21 | public function getRoutes():array 22 | { 23 | return self::$routes; 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /src/Helper/HTTP/Route/Validator.php: -------------------------------------------------------------------------------- 1 | validate($route); 22 | if(false === $isValid) { 23 | throw new Exception('Validator failed '. get_class($route)); 24 | break; 25 | } 26 | } 27 | 28 | return $isValid; 29 | } 30 | 31 | 32 | 33 | } -------------------------------------------------------------------------------- /src/Helper/HTTP/URI/URIBuilder.php: -------------------------------------------------------------------------------- 1 | $pattern) { 15 | $URI = str_replace('{'.$parameter.'}', $pattern, $URI); 16 | } 17 | return '#^' .$URI.'$#'; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/Helper/HTTP/Validation/AbstractType.php: -------------------------------------------------------------------------------- 1 | route = $route; 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /src/Helper/HTTP/Validation/InterfaceValidator.php: -------------------------------------------------------------------------------- 1 | route->getController(); 17 | $actionName = $this->route->getAction(); 18 | 19 | $isValid = false; 20 | if(false === empty($actionName) && false === empty($className)) { 21 | $isValid = $this->doesExist($className, $actionName); 22 | } 23 | 24 | return $isValid; 25 | } 26 | 27 | /** 28 | * @param string $className 29 | * @param string $actionName 30 | * 31 | * @return bool 32 | */ 33 | public function doesExist(string $className, string $actionName):bool 34 | { 35 | $isValid = true; 36 | try { 37 | new ReflectionMethod($className, $actionName); 38 | } catch (ReflectionException $exception){ 39 | $isValid = false; 40 | } 41 | 42 | return $isValid; 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /src/Helper/HTTP/Validation/Type/ControllerValidator.php: -------------------------------------------------------------------------------- 1 | route->getController(); 19 | 20 | if(false === empty($className)) { 21 | $isValid = $this->doesExist($className); 22 | } 23 | 24 | return $isValid; 25 | } 26 | 27 | /** 28 | * @param string $string 29 | * 30 | * @return bool 31 | */ 32 | public function doesExist(string $string): bool 33 | { 34 | $isValid = true; 35 | try { 36 | new ReflectionClass($string); 37 | } catch (ReflectionException $exception){ 38 | $isValid = false; 39 | } 40 | return $isValid; 41 | 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /src/Helper/HTTP/Validation/Type/MethodValidator.php: -------------------------------------------------------------------------------- 1 | route->getMethods(); 16 | 17 | if(is_array($value)) { 18 | $isValid = $this->isValueCorrect($value); 19 | } 20 | 21 | return $isValid; 22 | } 23 | 24 | /** 25 | * @param array $values 26 | * 27 | * @return bool 28 | */ 29 | public function isValueCorrect(array $values) 30 | { 31 | $possible = [ 32 | 'GET', 33 | 'POST' 34 | ]; 35 | 36 | foreach($values as $value) { 37 | if(false === in_array($value, $possible)) { 38 | return false; 39 | } 40 | } 41 | 42 | return true; 43 | } 44 | 45 | 46 | 47 | } -------------------------------------------------------------------------------- /src/Helper/HTTP/Validation/Type/PatternValidator.php: -------------------------------------------------------------------------------- 1 | route->getPattern()); 14 | } 15 | 16 | 17 | } -------------------------------------------------------------------------------- /src/Helper/HTTP/Validation/Validation.php: -------------------------------------------------------------------------------- 1 | validators[get_class($validator)] = $validator; 20 | } 21 | } 22 | 23 | /** 24 | * @param InterfaceValidator $interfaceValidation 25 | */ 26 | public function addValidator(InterfaceValidator $interfaceValidation) 27 | { 28 | $this->setValidators([$interfaceValidation]); 29 | } 30 | 31 | /** 32 | * @param string $className 33 | * 34 | * @return bool 35 | */ 36 | public function hasValidator($className):bool 37 | { 38 | return key_exists($className, $this->validators); 39 | } 40 | 41 | /** 42 | * @param Route $route 43 | * 44 | * @return bool 45 | */ 46 | public function validate(Route $route):bool 47 | { 48 | $isValid = false; 49 | 50 | foreach($this->validators as $validator) { 51 | if($validator instanceof InterfaceValidator) { 52 | $validator->setRoute($route); 53 | $isValid = $validator->isValid(); 54 | 55 | if(false === $isValid) { 56 | break; 57 | } 58 | } 59 | } 60 | 61 | return $isValid; 62 | } 63 | } -------------------------------------------------------------------------------- /src/Helper/Kernel/Kernel.php: -------------------------------------------------------------------------------- 1 | locate(); 23 | 24 | if(false === $route instanceof Route) { 25 | throw new Exception('Cannot find page', 404); 26 | } 27 | $controllerName = $route->getController(); 28 | 29 | $controller = new $controllerName(); 30 | 31 | return $controller->{$route->getAction()}($request); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/Hydration/AbstractHydrator.php: -------------------------------------------------------------------------------- 1 | setDateCreated($dateCreated); 16 | $entity->setDateUpdated($dateUpdate); 17 | $entity->setId($data['id']); 18 | return $entity; 19 | 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /src/Hydration/CustomerHydrator.php: -------------------------------------------------------------------------------- 1 | setCompanyName($data['company_name']) 13 | ->setFirstName($data['first_name']) 14 | ->setLastName($data['last_name']) 15 | ; 16 | parent::hydrateRest($data, $entity); 17 | 18 | return $entity; 19 | 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /src/Hydration/InvoiceHydrator.php: -------------------------------------------------------------------------------- 1 | setReference($data['reference']) 13 | ->setTotal($data['total']) 14 | ->setVAT($data['vat']) 15 | ; 16 | parent::hydrateRest($data, $entity); 17 | 18 | return $entity; 19 | 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /src/Hydration/InvoiceItemHydrator.php: -------------------------------------------------------------------------------- 1 | setReference($data['reference']) 13 | ->setDescription($data['description']) 14 | ->setTotal($data['total']) 15 | ->setUnitPrice($data['unit_price']) 16 | ->setUnits($data['units']) 17 | ; 18 | parent::hydrateRest($data, $entity); 19 | 20 | return $entity; 21 | 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /src/Hydration/StatusHydrator.php: -------------------------------------------------------------------------------- 1 | setName($data['name']) 13 | ->setInternalName($data['internal_name']) 14 | ; 15 | parent::hydrateRest($data, $entity); 16 | 17 | return $entity; 18 | 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /src/Manager/AbstractManager.php: -------------------------------------------------------------------------------- 1 | repository = $repository; 23 | } 24 | 25 | /** 26 | * @param int $id 27 | * 28 | * @return null|Customer 29 | */ 30 | public function findOne(int $id): ?Customer 31 | { 32 | $entity = $this->repository->findOne($id); 33 | return $entity; 34 | } 35 | 36 | /** 37 | * @inheritDoc 38 | */ 39 | public function findAll(): array 40 | { 41 | $results = []; 42 | $rows = $this->repository->findAll('customer'); 43 | 44 | if (is_array($rows)) { 45 | foreach ($rows as $row) { 46 | $results[] = CustomerHydrator::hydrate($row); 47 | } 48 | } 49 | 50 | return $results; 51 | } 52 | 53 | /** 54 | * @param Customer $entity 55 | * @return Customer 56 | */ 57 | public function save(Customer $entity) 58 | { 59 | $savedEntity = $this->repository->save($entity); 60 | 61 | return $savedEntity; 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /src/Manager/InvoiceItemManager.php: -------------------------------------------------------------------------------- 1 | repository = $repository; 23 | } 24 | 25 | /** 26 | * @param int $id 27 | * 28 | * @return null|InvoiceItem 29 | */ 30 | public function findOne(int $id): ?InvoiceItem 31 | { 32 | $entity = $this->repository->findOne($id); 33 | return $entity; 34 | } 35 | 36 | /** 37 | * @inheritDoc 38 | */ 39 | public function findAll(): array 40 | { 41 | $results = []; 42 | $rows = $this->repository->findAll('invoice_item'); 43 | 44 | if (is_array($rows)) { 45 | foreach ($rows as $row) { 46 | $results[] = InvoiceItemHydrator::hydrate($row); 47 | } 48 | } 49 | 50 | return $results; 51 | } 52 | 53 | /** 54 | * @param int $id 55 | * @return array 56 | */ 57 | public function findAllByInvoiceID(int $id): array 58 | { 59 | return $this->repository->findAllByInvoiceID($id); 60 | } 61 | 62 | /** 63 | * @param InvoiceItem $entity 64 | * @return InvoiceItem 65 | */ 66 | public function save(InvoiceItem $entity) 67 | { 68 | $savedEntity = $this->repository->save($entity); 69 | 70 | return $savedEntity; 71 | } 72 | 73 | } -------------------------------------------------------------------------------- /src/Manager/InvoiceManager.php: -------------------------------------------------------------------------------- 1 | repository = $repository; 23 | } 24 | 25 | 26 | /** 27 | * @param int $id 28 | * 29 | * @return Invoice|null 30 | */ 31 | public function findOne(int $id): ?Invoice 32 | { 33 | $entity = $this->repository->findOne($id); 34 | return $entity; 35 | } 36 | 37 | /** 38 | * @inheritDoc 39 | */ 40 | public function findAll(): array 41 | { 42 | $results = []; 43 | $rows = $this->repository->findAll('invoice'); 44 | if (is_array($rows)) { 45 | foreach ($rows as $row) { 46 | $results[] = InvoiceHydrator::hydrate($row); 47 | } 48 | } 49 | return $results; 50 | } 51 | 52 | /** 53 | * @param Invoice $entity 54 | * @return Invoice 55 | */ 56 | public function save(Invoice $entity): Invoice 57 | { 58 | $savedEntity = $this->repository->save($entity); 59 | return $savedEntity; 60 | } 61 | } -------------------------------------------------------------------------------- /src/Manager/ManagerInterface.php: -------------------------------------------------------------------------------- 1 | repository = $repository; 23 | } 24 | 25 | /** 26 | * @param int $id 27 | * 28 | * @return null|Status 29 | */ 30 | public function findOne(int $id): ?Status 31 | { 32 | $entity = $this->repository->findOne($id); 33 | return $entity; 34 | } 35 | 36 | /** 37 | * @inheritDoc 38 | */ 39 | public function findAll(): array 40 | { 41 | $results = []; 42 | $rows = $this->repository->findAll('status'); 43 | 44 | if (is_array($rows)) { 45 | foreach ($rows as $row) { 46 | $results[] = StatusHydrator::hydrate($row); 47 | } 48 | } 49 | 50 | return $results; 51 | } 52 | 53 | /** 54 | * @param Status $entity 55 | * @return Status 56 | */ 57 | public function save(Status $entity) 58 | { 59 | $savedEntity = $this->repository->save($entity); 60 | 61 | return $savedEntity; 62 | } 63 | } -------------------------------------------------------------------------------- /src/Repository/AbstractRepository.php: -------------------------------------------------------------------------------- 1 | connection = $connection; 27 | $this->queryBuilder = $queryBuilder; 28 | } 29 | 30 | /** 31 | * Find one entity by ID 32 | * 33 | * @param int $id 34 | * @return mixed 35 | */ 36 | abstract public function findOne(int $id); 37 | 38 | 39 | /** 40 | * @param string $tableName 41 | * @return array 42 | */ 43 | public function findAll(string $tableName): array 44 | { 45 | $this->queryBuilder->select($tableName); 46 | $sql = $this->queryBuilder->getSQL(); 47 | 48 | $dbCon = $this->connection->open(); 49 | $statement = $dbCon->prepare($sql); 50 | $statement->execute(); 51 | 52 | return $statement->fetchAll(); 53 | } 54 | } -------------------------------------------------------------------------------- /src/Repository/CustomerRepository.php: -------------------------------------------------------------------------------- 1 | $entity->getFirstName(), 21 | 'last_name' => $entity->getLastName(), 22 | 'company_name' => $entity->getCompanyName(), 23 | ]; 24 | $table = 'customer'; 25 | $where = []; 26 | if (null !== $entity->getId()) { 27 | $where['id'] = $entity->getId(); 28 | } 29 | $sql = QueryBuilder::insertOrUpdate($data, $table, $where); 30 | 31 | if (null !== $entity->getId()) { 32 | $data['id'] = $entity->getId(); 33 | } 34 | 35 | $dbCon = $this->connection->open(); 36 | 37 | $statement = $dbCon->prepare($sql); 38 | $statement->execute($data); 39 | 40 | if (null === $entity->getId()) { 41 | $entity->setId((int)$dbCon->lastInsertId()); 42 | } 43 | 44 | return $entity; 45 | } 46 | 47 | /** 48 | * @param int $id 49 | * @return mixed 50 | */ 51 | public function findOne(int $id) 52 | { 53 | $entity = null; 54 | $sql = QueryBuilder::findOneBy('customer'); 55 | $dbCon = $this->connection->open(); 56 | 57 | $statement = $dbCon->prepare($sql); 58 | $statement->execute([ 59 | 'id' => $id 60 | ]); 61 | $row = $statement->fetch(); 62 | 63 | if ($row) { 64 | $entity = CustomerHydrator::hydrate($row); 65 | } 66 | return $entity; 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /src/Repository/InvoiceItemRepository.php: -------------------------------------------------------------------------------- 1 | connection->open(); 21 | 22 | $statement = $dbCon->prepare($sql); 23 | $statement->execute([ 24 | 'id' => $id 25 | ]); 26 | $row = $statement->fetch(); 27 | 28 | if ($row) { 29 | $entity = InvoiceItemHydrator::hydrate($row); 30 | } 31 | return $entity; 32 | } 33 | 34 | /** 35 | * @param int $id 36 | * @return array 37 | */ 38 | public function findAllByInvoiceID(int $id):array 39 | { 40 | $results = []; 41 | $data = [ 42 | 'invoice_id' => $id 43 | ]; 44 | $sql = QueryBuilder::findAllBy('invoice_item', $data); 45 | 46 | $dbCon = $this->connection->open(); 47 | $statement = $dbCon->prepare($sql); 48 | $statement->execute($data); 49 | $rows = $statement->fetchAll(); 50 | 51 | if (is_array($rows)) { 52 | foreach ($rows as $row) { 53 | $results[] = InvoiceItemHydrator::hydrate($row); 54 | } 55 | } 56 | return $results; 57 | } 58 | 59 | /** 60 | * @param InvoiceItem $entity 61 | * @return InvoiceItem 62 | */ 63 | public function save(InvoiceItem $entity) 64 | { 65 | 66 | $data = [ 67 | 'reference' => $entity->getReference(), 68 | 'total' => $entity->getTotal(), 69 | 'unit_price' => $entity->getUnitPrice(), 70 | 'units' => $entity->getUnits(), 71 | 'description' => $entity->getDescription(), 72 | 'invoice_id' => $entity->getInvoice()->getId() 73 | ]; 74 | $table = 'invoice_item'; 75 | $where = []; 76 | if (null !== $entity->getId()) { 77 | $where['id'] = $entity->getId(); 78 | } 79 | $sql = QueryBuilder::insertOrUpdate($data, $table, $where); 80 | 81 | if (null !== $entity->getId()) { 82 | $data['id'] = $entity->getId(); 83 | } 84 | 85 | $dbCon = $this->connection->open(); 86 | 87 | $statement = $dbCon->prepare($sql); 88 | $statement->execute($data); 89 | 90 | if (null === $entity->getId()) { 91 | $entity->setId((int)$dbCon->lastInsertId()); 92 | } 93 | 94 | return $entity; 95 | } 96 | 97 | } -------------------------------------------------------------------------------- /src/Repository/InvoiceRepository.php: -------------------------------------------------------------------------------- 1 | connection->open(); 22 | 23 | $statement = $dbCon->prepare($sql); 24 | $statement->execute([ 25 | 'id' => $id 26 | ]); 27 | $row = $statement->fetch(); 28 | 29 | if ($row) { 30 | $entity = InvoiceHydrator::hydrate($row); 31 | } 32 | return $entity; 33 | } 34 | 35 | /** 36 | * @param Invoice $entity 37 | * @return Invoice 38 | */ 39 | public function save(Invoice $entity): Invoice 40 | { 41 | $data = [ 42 | 'reference' => $entity->getReference(), 43 | 'total' => $entity->getTotal(), 44 | 'vat' => $entity->getVat() 45 | ]; 46 | if ($entity->getStatus() instanceof Status) { 47 | $data['status_id'] = $entity->getStatus()->getId(); 48 | } 49 | $where = []; 50 | if (null !== $entity->getId()) { 51 | $where['id'] = $entity->getId(); 52 | } 53 | 54 | $table = 'invoice'; 55 | 56 | $sql = QueryBuilder::insertOrUpdate($data, $table, $where); 57 | 58 | if (null !== $entity->getId()) { 59 | $data['id'] = $entity->getId(); 60 | } 61 | $dbCon = $this->connection->open(); 62 | 63 | $statement = $dbCon->prepare($sql); 64 | $statement->execute($data); 65 | 66 | if (null === $entity->getId()) { 67 | $entity->setId($dbCon->lastInsertId()); 68 | } 69 | 70 | return $entity; 71 | } 72 | 73 | } -------------------------------------------------------------------------------- /src/Repository/RepositoryFactory.php: -------------------------------------------------------------------------------- 1 | connection = $connection; 32 | $this->queryBuilder = $queryBuilder; 33 | } 34 | 35 | /** 36 | * @param string $entityClassName 37 | * @return mixed 38 | */ 39 | public function make(string $entityClassName): RepositoryInterface 40 | { 41 | if (key_exists($entityClassName, $this->repositories)) { 42 | return $this->repositories[$entityClassName]; 43 | } 44 | 45 | $map = [ 46 | Status::class => StatusRepository::class, 47 | Invoice::class => InvoiceRepository::class 48 | ]; 49 | 50 | if(key_exists($entityClassName, $map)) { 51 | $repo = $map[$entityClassName]; 52 | } 53 | 54 | 55 | return $this->repositories[$entityClassName] = new $repo($this->connection, $this->queryBuilder); 56 | } 57 | } 58 | 59 | $connection = new Connection(); 60 | $builder = new Builder(); 61 | $queryBuilder = new QueryBuilder($builder); 62 | $respositoryFactory = new RepositoryFactory($connection, $queryBuilder); 63 | 64 | $statusRepo = $respositoryFactory->make(Status::class)->findAll(); -------------------------------------------------------------------------------- /src/Repository/RepositoryInterface.php: -------------------------------------------------------------------------------- 1 | connection->open(); 20 | 21 | $statement = $dbCon->prepare($sql); 22 | $statement->execute([ 23 | 'id' => $id 24 | ]); 25 | $row = $statement->fetch(); 26 | 27 | if ($row) { 28 | $entity = StatusHydrator::hydrate($row); 29 | } 30 | return $entity; 31 | } 32 | 33 | /** 34 | * @param Status $entity 35 | * @return Status 36 | */ 37 | public function saveBKP(Status $entity) 38 | { 39 | $data = [ 40 | 'name' => $entity->getName(), 41 | 'internal_name' => $entity->getInternalName(), 42 | ]; 43 | $table = 'status'; 44 | $where = []; 45 | if (null !== $entity->getId()) { 46 | $where['id'] = $entity->getId(); 47 | } 48 | $sql = QueryBuilder::insertOrUpdate($data, $table, $where); 49 | 50 | if (null !== $entity->getId()) { 51 | $data['id'] = $entity->getId(); 52 | } 53 | 54 | $dbCon = $this->connection->open(); 55 | 56 | $statement = $dbCon->prepare($sql); 57 | $statement->execute(array_values($data)); 58 | 59 | if (null === $entity->getId()) { 60 | $entity->setId((int)$dbCon->lastInsertId()); 61 | } 62 | 63 | return $entity; 64 | } 65 | 66 | 67 | /** 68 | * @param Status $entity 69 | * @return Status 70 | */ 71 | public function save(Status $entity) 72 | { 73 | $values = [ 74 | 'name' => $entity->getName(), 75 | 'internal_name' => $entity->getInternalName(), 76 | 77 | ]; 78 | if (null !== $entity->getId()) { 79 | $values['id'] = $entity->getId(); 80 | } 81 | 82 | $data = [ 83 | 'name' => 'name', 84 | 'internal_name' => 'internal_name' 85 | ]; 86 | $table = 'status'; 87 | $where = []; 88 | if (null !== $entity->getId()) { 89 | $where['id'] = 'id'; 90 | } 91 | $sql = QueryBuilder::insertOrUpdate($data, $table, $where); 92 | 93 | if (null !== $entity->getId()) { 94 | $data['id'] = $entity->getId(); 95 | } 96 | 97 | $dbCon = $this->connection->open(); 98 | 99 | $statement = $dbCon->prepare($sql); 100 | $statement->execute($values); 101 | 102 | if (null === $entity->getId()) { 103 | $entity->setId((int)$dbCon->lastInsertId()); 104 | } 105 | 106 | return $entity; 107 | } 108 | 109 | } -------------------------------------------------------------------------------- /tests/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pfwd/freecodecamp-PHP-OOP/d211e83f2fec6d314226728dc29cbd985fa384fa/tests/.DS_Store -------------------------------------------------------------------------------- /tests/_data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pfwd/freecodecamp-PHP-OOP/d211e83f2fec6d314226728dc29cbd985fa384fa/tests/_data/.gitkeep -------------------------------------------------------------------------------- /tests/_data/dump.sql: -------------------------------------------------------------------------------- 1 | -- MySQL dump 10.13 Distrib 5.7.26, for Linux (x86_64) 2 | -- 3 | -- Host: localhost Database: test_invoice_app 4 | -- ------------------------------------------------------ 5 | -- Server version 5.7.26 6 | 7 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 8 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 9 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 10 | /*!40101 SET NAMES utf8 */; 11 | /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; 12 | /*!40103 SET TIME_ZONE='+00:00' */; 13 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; 14 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 15 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 16 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 17 | 18 | -- 19 | -- Table structure for table `customer` 20 | -- 21 | 22 | DROP TABLE IF EXISTS `customer`; 23 | /*!40101 SET @saved_cs_client = @@character_set_client */; 24 | /*!40101 SET character_set_client = utf8 */; 25 | CREATE TABLE `customer` ( 26 | `id` int(11) NOT NULL AUTO_INCREMENT, 27 | `company_name` varchar(250) NOT NULL, 28 | `first_name` varchar(250) NOT NULL, 29 | `last_name` varchar(250) DEFAULT NULL, 30 | `date_created` datetime DEFAULT CURRENT_TIMESTAMP, 31 | `date_updated` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, 32 | PRIMARY KEY (`id`) 33 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 34 | /*!40101 SET character_set_client = @saved_cs_client */; 35 | 36 | -- 37 | -- Dumping data for table `customer` 38 | -- 39 | 40 | LOCK TABLES `customer` WRITE; 41 | /*!40000 ALTER TABLE `customer` DISABLE KEYS */; 42 | /*!40000 ALTER TABLE `customer` ENABLE KEYS */; 43 | UNLOCK TABLES; 44 | 45 | -- 46 | -- Table structure for table `invoice` 47 | -- 48 | 49 | DROP TABLE IF EXISTS `invoice`; 50 | /*!40101 SET @saved_cs_client = @@character_set_client */; 51 | /*!40101 SET character_set_client = utf8 */; 52 | CREATE TABLE `invoice` ( 53 | `id` int(11) NOT NULL AUTO_INCREMENT, 54 | `reference` varchar(250) NOT NULL, 55 | `total` decimal(10,0) DEFAULT NULL, 56 | `vat` decimal(10,0) DEFAULT NULL, 57 | `status_id` int(11) DEFAULT NULL, 58 | `customer_id` int(11) DEFAULT NULL, 59 | `date_created` datetime DEFAULT CURRENT_TIMESTAMP, 60 | `date_updated` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, 61 | PRIMARY KEY (`id`), 62 | KEY `fk_status` (`status_id`), 63 | KEY `fk_customer` (`customer_id`), 64 | CONSTRAINT `invoice_ibfk_1` FOREIGN KEY (`status_id`) REFERENCES `status` (`id`), 65 | CONSTRAINT `invoice_ibfk_2` FOREIGN KEY (`customer_id`) REFERENCES `customer` (`id`) 66 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 67 | /*!40101 SET character_set_client = @saved_cs_client */; 68 | 69 | -- 70 | -- Dumping data for table `invoice` 71 | -- 72 | 73 | LOCK TABLES `invoice` WRITE; 74 | /*!40000 ALTER TABLE `invoice` DISABLE KEYS */; 75 | /*!40000 ALTER TABLE `invoice` ENABLE KEYS */; 76 | UNLOCK TABLES; 77 | 78 | -- 79 | -- Table structure for table `invoice_item` 80 | -- 81 | 82 | DROP TABLE IF EXISTS `invoice_item`; 83 | /*!40101 SET @saved_cs_client = @@character_set_client */; 84 | /*!40101 SET character_set_client = utf8 */; 85 | CREATE TABLE `invoice_item` ( 86 | `id` int(11) NOT NULL AUTO_INCREMENT, 87 | `reference` varchar(250) DEFAULT NULL, 88 | `description` varchar(250) NOT NULL, 89 | `unit_price` decimal(10,0) NOT NULL, 90 | `units` int(11) NOT NULL, 91 | `total` decimal(10,0) NOT NULL, 92 | `invoice_id` int(11) NOT NULL, 93 | `date_created` datetime DEFAULT CURRENT_TIMESTAMP, 94 | `date_updated` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, 95 | PRIMARY KEY (`id`), 96 | KEY `fk_invoice` (`invoice_id`), 97 | CONSTRAINT `invoice_item_ibfk_1` FOREIGN KEY (`invoice_id`) REFERENCES `invoice` (`id`) 98 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 99 | /*!40101 SET character_set_client = @saved_cs_client */; 100 | 101 | -- 102 | -- Dumping data for table `invoice_item` 103 | -- 104 | 105 | LOCK TABLES `invoice_item` WRITE; 106 | /*!40000 ALTER TABLE `invoice_item` DISABLE KEYS */; 107 | /*!40000 ALTER TABLE `invoice_item` ENABLE KEYS */; 108 | UNLOCK TABLES; 109 | 110 | -- 111 | -- Table structure for table `status` 112 | -- 113 | 114 | DROP TABLE IF EXISTS `status`; 115 | /*!40101 SET @saved_cs_client = @@character_set_client */; 116 | /*!40101 SET character_set_client = utf8 */; 117 | CREATE TABLE `status` ( 118 | `id` int(11) NOT NULL AUTO_INCREMENT, 119 | `name` varchar(250) NOT NULL, 120 | `internal_name` varchar(250) NOT NULL, 121 | `date_created` datetime DEFAULT CURRENT_TIMESTAMP, 122 | `date_updated` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, 123 | PRIMARY KEY (`id`) 124 | ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1; 125 | /*!40101 SET character_set_client = @saved_cs_client */; 126 | 127 | -- 128 | -- Dumping data for table `status` 129 | -- 130 | 131 | LOCK TABLES `status` WRITE; 132 | /*!40000 ALTER TABLE `status` DISABLE KEYS */; 133 | INSERT INTO `status` VALUES (1,'Draft','DRAFT','2019-07-25 07:07:59',NULL),(2,'Sent','SENT','2019-07-25 07:07:59',NULL),(3,'Overdue','OVERDUE','2019-07-25 07:07:59',NULL); 134 | /*!40000 ALTER TABLE `status` ENABLE KEYS */; 135 | UNLOCK TABLES; 136 | /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; 137 | 138 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; 139 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; 140 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; 141 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 142 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 143 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 144 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 145 | 146 | -- Dump completed on 2019-07-25 7:08:08 147 | -------------------------------------------------------------------------------- /tests/_output/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /tests/_support/AcceptanceTester.php: -------------------------------------------------------------------------------- 1 | setFirstName('Test First Name') 36 | ->setLastName('Test Last Name') 37 | ->setCompanyName('Test Company Name'); 38 | 39 | $this->getManager()->save($entity); 40 | 41 | $I->seeInDatabase('customer', [ 42 | 'first_name' => $entity->getFirstName(), 43 | 'last_name' => $entity->getLastName(), 44 | 'company_name' => $entity->getCompanyName() 45 | ]); 46 | } 47 | 48 | /** 49 | * @param AcceptanceTester $I 50 | * @group db 51 | * @group db-customer-entity-update 52 | */ 53 | public function updateTest(AcceptanceTester $I) 54 | { 55 | $entity = new Customer(); 56 | $entity->setFirstName('Test First Name') 57 | ->setLastName('Test Last Name') 58 | ->setCompanyName('Test Company Name'); 59 | $savedEntity = $this->getManager()->save($entity); 60 | 61 | $I->seeInDatabase('customer', [ 62 | 'first_name' => $entity->getFirstName(), 63 | 'last_name' => $entity->getLastName(), 64 | 'company_name' => $entity->getCompanyName(), 65 | 'id' => $savedEntity->getId() 66 | ]); 67 | 68 | $savedEntity->setCompanyName('Test Company Name 2'); 69 | $savedEntity = $this->getManager()->save($savedEntity); 70 | 71 | $I->seeInDatabase('customer', [ 72 | 'company_name' => $savedEntity->getCompanyName(), 73 | 'id' => $savedEntity->getId() 74 | ]); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /tests/acceptance/DBInvoiceEntityCest.php: -------------------------------------------------------------------------------- 1 | setVAT(1) 28 | ->setTotal(1) 29 | ->setReference('Test reference'); 30 | $manager = $this->getInvoiceManager(); 31 | $manager->save($entity); 32 | 33 | $I->seeInDatabase('invoice', [ 34 | 'vat' => $entity->getVat(), 35 | 'total' => $entity->getTotal(), 36 | 'reference' => $entity->getReference() 37 | ]); 38 | } 39 | 40 | /** 41 | * @return InvoiceManager 42 | */ 43 | protected function getInvoiceManager(): InvoiceManager 44 | { 45 | $connection = new Connection(); 46 | $builder = new Builder(); 47 | $queryBuilder = new QueryBuilder($builder); 48 | $repository = new InvoiceRepository($connection, $queryBuilder); 49 | return new InvoiceManager($repository); 50 | } 51 | 52 | /** 53 | * @return StatusManager 54 | */ 55 | protected function getStatusManager(): StatusManager 56 | { 57 | $connection = new Connection(); 58 | $builder = new Builder(); 59 | $queryBuilder = new QueryBuilder($builder); 60 | $repository = new StatusRepository($connection, $queryBuilder); 61 | return new StatusManager($repository); 62 | } 63 | 64 | /** 65 | * @param AcceptanceTester $I 66 | * @group db 67 | * @group db-invoice-entity-update 68 | */ 69 | public function updateTest(AcceptanceTester $I) 70 | { 71 | $entity = new Invoice(); 72 | $entity->setVAT(1) 73 | ->setTotal(1) 74 | ->setReference('Test reference'); 75 | $manager = $this->getInvoiceManager(); 76 | $savedEntity = $manager->save($entity); 77 | 78 | $I->seeInDatabase('invoice', [ 79 | 'vat' => $entity->getVat(), 80 | 'total' => $entity->getTotal(), 81 | 'reference' => $entity->getReference(), 82 | 'id' => $savedEntity->getId() 83 | ]); 84 | 85 | $savedEntity->setReference('Test updated reference'); 86 | $savedEntity->setTotal(3) 87 | ->setVAT(2); 88 | $manager->save($savedEntity); 89 | 90 | $I->seeInDatabase('invoice', [ 91 | 'vat' => $savedEntity->getVat(), 92 | 'total' => $savedEntity->getTotal(), 93 | 'reference' => $savedEntity->getReference(), 94 | 'id' => $savedEntity->getId() 95 | ]); 96 | 97 | } 98 | 99 | /** 100 | * @param AcceptanceTester $I 101 | * @group db 102 | * @group db-invoice-entity-insert-with-status 103 | */ 104 | public function insertWithStatusTest(AcceptanceTester $I) 105 | { 106 | $status = new Status(); 107 | $status->setName('temp') 108 | ->setInternalName('TEMP'); 109 | 110 | $savedStatus = $this->getStatusManager()->save($status); 111 | 112 | $invoice = new Invoice(); 113 | $invoice->setVAT(1) 114 | ->setTotal(1) 115 | ->setStatus($savedStatus) 116 | ->setReference('Test reference'); 117 | 118 | $manager = $this->getInvoiceManager();; 119 | $savedInvoice = $manager->save($invoice); 120 | 121 | $I->seeInDatabase('invoice', [ 122 | 'vat' => $invoice->getVat(), 123 | 'total' => $invoice->getTotal(), 124 | 'reference' => $invoice->getReference(), 125 | 'status_id' => $savedStatus->getId(), 126 | 'id' => $savedInvoice->getId() 127 | ]); 128 | 129 | 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /tests/acceptance/DBStatusCest.php: -------------------------------------------------------------------------------- 1 | seeInDatabase('status', [ 18 | 'name' => 'draft', 19 | 'internal_name' => 'DRAFT' 20 | ]); 21 | } 22 | 23 | /** 24 | * @param AcceptanceTester $I 25 | * @group db 26 | * @group db-status-sent 27 | */ 28 | public function StatusSentTest(AcceptanceTester $I) 29 | { 30 | $I->seeInDatabase('status', [ 31 | 'name' => 'sent', 32 | 'internal_name' => 'SENT' 33 | ]); 34 | } 35 | 36 | /** 37 | * @param AcceptanceTester $I 38 | * @group db 39 | * @group db-status-overdue 40 | */ 41 | public function OverdueSentTest(AcceptanceTester $I) 42 | { 43 | $I->seeInDatabase('status', [ 44 | 'name' => 'overdue', 45 | 'internal_name' => 'OVERDUE' 46 | ]); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /tests/acceptance/DBStatusEntityCest.php: -------------------------------------------------------------------------------- 1 | setName('Hello World2') 25 | ->setInternalName('HELLO_WORLD_2'); 26 | 27 | $manager = $this->getManager(); 28 | $manager->save($entity); 29 | 30 | $I->seeInDatabase('status', [ 31 | 'name' => $entity->getName(), 32 | 'internal_name' => $entity->getInternalName() 33 | ]); 34 | } 35 | 36 | /** 37 | * @return StatusManager 38 | */ 39 | public function getManager(): StatusManager 40 | { 41 | $connection = new Connection(); 42 | $builder = new Builder(); 43 | $queryBuilder = new QueryBuilder($builder); 44 | $repository = new StatusRepository($connection, $queryBuilder); 45 | return new StatusManager($repository); 46 | } 47 | 48 | /** 49 | * @param AcceptanceTester $I 50 | * @group db 51 | * @group db-status-entity-update 52 | */ 53 | public function updateTest(AcceptanceTester $I) 54 | { 55 | $entity = new Status(); 56 | $entity->setName('Test Status') 57 | ->setInternalName('TEST_STATUS'); 58 | $manager = $this->getManager(); 59 | $savedEntity = $manager->save($entity); 60 | 61 | $I->seeInDatabase('status', [ 62 | 'name' => $entity->getName(), 63 | 'internal_name' => $entity->getInternalName(), 64 | 'id' => $savedEntity->getId() 65 | ]); 66 | 67 | $savedEntity->setName('Test Status 2'); 68 | $savedEntity->setInternalName('TEST'); 69 | $manager->save($savedEntity); 70 | 71 | $I->seeInDatabase('status', [ 72 | 'name' => $savedEntity->getName(), 73 | 'id' => $savedEntity->getId() 74 | ]); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /tests/acceptance/HomePageCest.php: -------------------------------------------------------------------------------- 1 | wantTo('Test the response code for the homepage'); 17 | $I->amOnPage('/'); 18 | $I->seeResponseCodeIs(200); 19 | $I->canSee('Hello from the homepage'); 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/acceptance/InvoicePageCest.php: -------------------------------------------------------------------------------- 1 | wantTo('Test the response code for the invoice dashboard page'); 17 | $I->amOnPage('/invoice'); 18 | $I->canSee('This is the invoice dashboard'); 19 | $I->seeResponseCodeIs(200); 20 | } 21 | 22 | /** 23 | * @param AcceptanceTester $I 24 | * 25 | * @group invoice 26 | * @group invoice-get-by-id 27 | */ 28 | public function invoiceTest(AcceptanceTester $I) 29 | { 30 | $I->wantTo('Test the response code for the invoice'); 31 | $I->amOnPage('/invoice/123'); 32 | $I->canSee('This is the invoice page for invoice 123 '); 33 | $I->seeResponseCodeIs(200); 34 | } 35 | 36 | /** 37 | * @param AcceptanceTester $I 38 | * 39 | * @group invoice 40 | * @group invoice-not-found 41 | */ 42 | public function pageNotFoundTest(AcceptanceTester $I) 43 | { 44 | $I->wantTo('Test the response code for the invoice'); 45 | $I->amOnPage('/invoice/rrr/edit/aaa'); 46 | $I->seeResponseCodeIs(404); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /tests/acceptance/NotFoundPageCest.php: -------------------------------------------------------------------------------- 1 | wantTo('Test the response code for 404 page'); 17 | $I->amOnPage('/not-found'); 18 | $I->seeResponseCodeIs(404); 19 | // $I->canSee('Page Not Found'); 20 | // $I->canSeeInTitle('Page Not Found'); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/functional.suite.yml: -------------------------------------------------------------------------------- 1 | # Codeception Test Suite Configuration 2 | # 3 | # Suite for functional tests 4 | # Emulate web requests and make application process them 5 | # Include one of framework modules (Symfony2, Yii2, Laravel5) to use it 6 | # Remove this suite if you don't use frameworks 7 | 8 | actor: FunctionalTester 9 | modules: 10 | enabled: 11 | # add a framework module here 12 | - \Helper\Functional 13 | step_decorators: ~ -------------------------------------------------------------------------------- /tests/integration.suite.yml: -------------------------------------------------------------------------------- 1 | actor: Code 2 | modules: 3 | enabled: 4 | - \Helper\Integration 5 | - Asserts 6 | - Db 7 | config: 8 | Db: 9 | dsn: 'mysql:host=db_test;dbname=test_invoice_app' 10 | user: 'root' 11 | password: 'test' 12 | reconnect: true 13 | dump: 'tests/_data/dump.sql' 14 | populate: true 15 | cleanup: true 16 | step_decorators: ~ -------------------------------------------------------------------------------- /tests/integration/DBCustomerEntityTest.php: -------------------------------------------------------------------------------- 1 | setFirstName('Foo') 28 | ->setLastName('Bar') 29 | ->setCompanyName('FooBar'); 30 | $manager = $this->getManager(); 31 | $savedEntity = $manager->save($entity); 32 | 33 | $foundEntity = $manager->findOne($savedEntity->getId()); 34 | 35 | $this->assertSame($foundEntity->getFirstName(), $savedEntity->getFirstName()); 36 | $this->assertSame($foundEntity->getLastName(), $savedEntity->getLastName()); 37 | $this->assertSame($foundEntity->getCompanyName(), $savedEntity->getCompanyName()); 38 | } 39 | 40 | /** 41 | * @return CustomerManager 42 | */ 43 | protected function getManager(): CustomerManager 44 | { 45 | $connection = new Connection(); 46 | $builder = new Builder(); 47 | $queryBuilder = new QueryBuilder($builder); 48 | $repository = new CustomerRepository($connection, $queryBuilder); 49 | return new CustomerManager($repository); 50 | } 51 | 52 | /** 53 | * @group db-customer 54 | * @group db-customer-entity-find-one-by-id-not-exists 55 | */ 56 | public function testFindCustomerThatDoesNotExist() 57 | { 58 | $entity = new Customer(); 59 | $entity->setId(5001); 60 | $manager = $this->getManager(); 61 | 62 | $foundEntity = $manager->findOne($entity->getId()); 63 | $this->assertNull($foundEntity); 64 | 65 | } 66 | 67 | /** 68 | * @group db-customer 69 | * @group db-customer-entity-find-all 70 | */ 71 | public function testFindAll() 72 | { 73 | $entity1 = new Customer(); 74 | $entity1->setFirstName("Peter"); 75 | $entity1->setLastName("Fisher"); 76 | $entity1->setCompanyName("How To Code Well"); 77 | 78 | $entity2 = new Customer(); 79 | $entity2->setFirstName("Foo"); 80 | $entity2->setLastName("Bar"); 81 | $entity2->setCompanyName("FooBar"); 82 | 83 | $manager = $this->getManager(); 84 | 85 | $manager->save($entity1); 86 | $manager->save($entity2); 87 | $results = $manager->findAll(); 88 | 89 | $this->assertIsArray($results); 90 | $this->assertGreaterThan(1, count($results)); 91 | 92 | $foundEntity1 = $results[0]; 93 | 94 | $this->assertInstanceOf(Customer::class, $foundEntity1); 95 | } 96 | 97 | protected function _before() 98 | { 99 | } 100 | 101 | protected function _after() 102 | { 103 | } 104 | } -------------------------------------------------------------------------------- /tests/integration/DBInvoiceEntityTest.php: -------------------------------------------------------------------------------- 1 | setVAT(3) 26 | ->setTotal(3) 27 | ->setReference('FooBar'); 28 | $manager = $this->getManager(); 29 | $savedEntity = $manager->save($entity); 30 | 31 | $foundEntity = $manager->findOne($savedEntity->getId()); 32 | 33 | $this->assertSame($foundEntity->getVat(), $savedEntity->getVat()); 34 | $this->assertSame($foundEntity->getTotal(), $savedEntity->getTotal()); 35 | $this->assertSame($foundEntity->getReference(), $savedEntity->getReference()); 36 | } 37 | 38 | /** 39 | * @return InvoiceManager 40 | */ 41 | protected function getManager(): InvoiceManager 42 | { 43 | $connection = new Connection(); 44 | $builder = new Builder(); 45 | $queryBuilder = new QueryBuilder($builder); 46 | $repository = new InvoiceRepository($connection, $queryBuilder); 47 | return new InvoiceManager($repository); 48 | } 49 | 50 | /** 51 | * @group db-invoice 52 | * @group db-invoice-entity-find-one-by-id-not-exists 53 | */ 54 | public function testFindCustomerThatDoesNotExist() 55 | { 56 | $entity = new Invoice(); 57 | $entity->setId(5001); 58 | $manager = $this->getManager(); 59 | 60 | $foundEntity = $manager->findOne($entity->getId()); 61 | $this->assertNull($foundEntity); 62 | 63 | } 64 | 65 | /** 66 | * @group db-invoice 67 | * @group db-invoice-entity-find-all 68 | */ 69 | public function testFindAll() 70 | { 71 | $entity1 = new Invoice(); 72 | $entity1->setVAT(3) 73 | ->setTotal(3) 74 | ->setReference('Test 1'); 75 | 76 | $entity2 = new Invoice(); 77 | $entity2->setVAT(4) 78 | ->setTotal(4) 79 | ->setReference('Test 2'); 80 | 81 | $manager = $this->getManager(); 82 | 83 | $manager->save($entity1); 84 | $manager->save($entity2); 85 | $results = $manager->findAll(); 86 | 87 | $this->assertIsArray($results); 88 | $this->assertGreaterThan(1, count($results)); 89 | 90 | $foundEntity1 = $results[0]; 91 | 92 | $this->assertInstanceOf(Invoice::class, $foundEntity1); 93 | } 94 | 95 | protected function _before() 96 | { 97 | } 98 | 99 | protected function _after() 100 | { 101 | } 102 | } -------------------------------------------------------------------------------- /tests/integration/DBInvoiceItemEntityTest.php: -------------------------------------------------------------------------------- 1 | setReference('Test Invoice'); 29 | 30 | $invoiceManager = $this->getInvoiceManager(); 31 | $savedInvoice = $invoiceManager->save($invoice); 32 | 33 | $foundInvoice = $invoiceManager->findOne($savedInvoice->getId()); 34 | 35 | $this->assertSame($foundInvoice->getReference(), $savedInvoice->getReference()); 36 | 37 | $entity = new InvoiceItem(); 38 | $entity->setReference('Devtime') 39 | ->setTotal(150) 40 | ->setUnits(7) 41 | ->setUnitPrice(100) 42 | ->setDescription('Development time') 43 | ->setInvoice($invoice); 44 | 45 | $invoiceItemManager = $this->getManager(); 46 | $savedEntity = $invoiceItemManager->save($entity); 47 | 48 | $this->assertInstanceOf(InvoiceItem::class, $savedEntity); 49 | 50 | $foundEntity = $invoiceItemManager->findOne($savedEntity->getId()); 51 | 52 | $this->assertInstanceOf(InvoiceItem::class, $foundEntity); 53 | 54 | $this->assertSame($foundEntity->getReference(), $savedEntity->getReference()); 55 | $this->assertSame($foundEntity->getTotal(), $savedEntity->getTotal()); 56 | $this->assertSame($foundEntity->getUnits(), $savedEntity->getUnits()); 57 | $this->assertSame($foundEntity->getUnitPrice(), $savedEntity->getUnitPrice()); 58 | $this->assertSame($foundEntity->getDescription(), $savedEntity->getDescription()); 59 | } 60 | 61 | /** 62 | * @return InvoiceManager 63 | */ 64 | protected function getInvoiceManager(): InvoiceManager 65 | { 66 | $connection = new Connection(); 67 | $builder = new Builder(); 68 | $queryBuilder = new QueryBuilder($builder); 69 | $repository = new InvoiceRepository($connection, $queryBuilder); 70 | return new InvoiceManager($repository); 71 | } 72 | 73 | /** 74 | * @return InvoiceItemManager 75 | */ 76 | protected function getManager(): InvoiceItemManager 77 | { 78 | $connection = new Connection(); 79 | $builder = new Builder(); 80 | $queryBuilder = new QueryBuilder($builder); 81 | $repository = new InvoiceItemRepository($connection, $queryBuilder); 82 | return new InvoiceItemManager($repository); 83 | } 84 | 85 | /** 86 | * @group db-invoice-item 87 | * @group db-invoice-item-entity-find-one-by-id-not-exists 88 | */ 89 | public function testFindInvoiceItemThatDoesNotExist() 90 | { 91 | $entity = new InvoiceItem(); 92 | $entity->setId(5001); 93 | $manager = $this->getManager(); 94 | 95 | $foundEntity = $manager->findOne($entity->getId()); 96 | $this->assertNull($foundEntity); 97 | 98 | } 99 | 100 | /** 101 | * @group db-invoice-item 102 | * @group db-invoice-item-entity-find-all 103 | */ 104 | public function testFindAllInvoiceItems() 105 | { 106 | $invoice = new Invoice(); 107 | $invoice->setReference('Test Invoice'); 108 | 109 | $invoiceManager = $this->getInvoiceManager(); 110 | $savedInvoice = $invoiceManager->save($invoice); 111 | 112 | $foundInvoice = $invoiceManager->findOne($savedInvoice->getId()); 113 | 114 | $this->assertSame($foundInvoice->getReference(), $savedInvoice->getReference()); 115 | 116 | $entity1 = new InvoiceItem(); 117 | $entity1->setReference('Devtime') 118 | ->setTotal(150) 119 | ->setUnits(7) 120 | ->setUnitPrice(100) 121 | ->setDescription('Development time') 122 | ->setInvoice($invoice); 123 | 124 | $entity2 = new InvoiceItem(); 125 | $entity2->setReference('Devtime') 126 | ->setTotal(150) 127 | ->setUnits(7) 128 | ->setUnitPrice(100) 129 | ->setDescription('Development time') 130 | ->setInvoice($invoice); 131 | 132 | $manager = $this->getManager(); 133 | 134 | $manager->save($entity1); 135 | $manager->save($entity2); 136 | 137 | $results = $manager->findAll(); 138 | $this->assertIsArray($results); 139 | $this->assertGreaterThan(1, count($results)); 140 | 141 | $foundEntity1 = $results[0]; 142 | $this->assertInstanceOf(InvoiceItem::class, $foundEntity1); 143 | 144 | } 145 | 146 | 147 | /** 148 | * @group db-invoice-item 149 | * @group db-invoice-item-entity-find-all-by-invoice-id 150 | */ 151 | public function testFindAllInvoiceItemsByInvoiceID() 152 | { 153 | $invoice = new Invoice(); 154 | $invoice->setReference('Test Invoice'); 155 | 156 | $invoiceManager = $this->getInvoiceManager(); 157 | $savedInvoice = $invoiceManager->save($invoice); 158 | 159 | $foundInvoice = $invoiceManager->findOne($savedInvoice->getId()); 160 | 161 | $this->assertSame($foundInvoice->getReference(), $savedInvoice->getReference()); 162 | 163 | $entity1 = new InvoiceItem(); 164 | $entity1->setReference('Devtime') 165 | ->setTotal(150) 166 | ->setUnits(7) 167 | ->setUnitPrice(100) 168 | ->setDescription('Development time') 169 | ->setInvoice($invoice); 170 | 171 | $entity2 = new InvoiceItem(); 172 | $entity2->setReference('Devtime') 173 | ->setTotal(150) 174 | ->setUnits(7) 175 | ->setUnitPrice(100) 176 | ->setDescription('Development time') 177 | ->setInvoice($invoice); 178 | 179 | $manager = $this->getManager(); 180 | 181 | $manager->save($entity1); 182 | $manager->save($entity2); 183 | 184 | 185 | $results = $manager->findAllByInvoiceID($foundInvoice->getId()); 186 | $this->assertIsArray($results); 187 | $this->assertGreaterThan(1, count($results)); 188 | 189 | $foundEntity1 = $results[0]; 190 | $this->assertInstanceOf(InvoiceItem::class, $foundEntity1); 191 | 192 | } 193 | 194 | protected function _before() 195 | { 196 | } 197 | 198 | protected function _after() 199 | { 200 | } 201 | } -------------------------------------------------------------------------------- /tests/integration/DBStatusEntityTest.php: -------------------------------------------------------------------------------- 1 | setName('Hello World2') 26 | ->setInternalName('HELLO_WORLD_2'); 27 | 28 | $manager = $this->getManager(); 29 | $savedEntity = $manager->save($entity); 30 | 31 | $foundEntity = $manager->findOne($savedEntity->getId()); 32 | 33 | $this->assertSame($foundEntity->getName(), $savedEntity->getName()); 34 | $this->assertSame($foundEntity->getInternalName(), $savedEntity->getInternalName()); 35 | } 36 | 37 | /** 38 | * @return StatusManager 39 | */ 40 | protected function getManager(): StatusManager 41 | { 42 | $connection = new Connection(); 43 | $builder = new Builder(); 44 | $queryBuilder = new QueryBuilder($builder); 45 | $repository = new StatusRepository($connection, $queryBuilder); 46 | return new StatusManager($repository); 47 | } 48 | 49 | /** 50 | * @group db-status 51 | * @group db-status-entity-find-one-by-id-not-exists 52 | */ 53 | public function testFindStatusThatDoesNotExist() 54 | { 55 | $entity = new Status(); 56 | $entity->setId(5001); 57 | $manager = $this->getManager(); 58 | 59 | $foundEntity = $manager->findOne($entity->getId()); 60 | $this->assertNull($foundEntity); 61 | 62 | } 63 | 64 | /** 65 | * @group db-status 66 | * @group db-status-entity-find-all-statuses 67 | */ 68 | public function testFindAllStatuses() 69 | { 70 | $entity1 = new Status(); 71 | $entity1->setName('Test 1'); 72 | $entity1->setInternalName('TEST_1'); 73 | 74 | $entity2 = new Status(); 75 | $entity2->setName('Test 2'); 76 | $entity2->setInternalName('TEST_2'); 77 | 78 | $manager = $this->getManager(); 79 | 80 | $manager->save($entity1); 81 | $manager->save($entity2); 82 | 83 | $results = $manager->findAll(); 84 | $this->assertIsArray($results); 85 | $this->assertGreaterThan(1, count($results)); 86 | 87 | $foundEntity1 = $results[0]; 88 | $this->assertInstanceOf(Status::class, $foundEntity1); 89 | 90 | } 91 | 92 | protected function _before() 93 | { 94 | } 95 | 96 | protected function _after() 97 | { 98 | } 99 | } -------------------------------------------------------------------------------- /tests/unit.suite.yml: -------------------------------------------------------------------------------- 1 | # Codeception Test Suite Configuration 2 | # 3 | # Suite for unit or integration tests. 4 | 5 | actor: UnitTester 6 | modules: 7 | enabled: 8 | - Asserts 9 | - \Helper\Unit 10 | step_decorators: ~ -------------------------------------------------------------------------------- /tests/unit/DB/BuilderTest.php: -------------------------------------------------------------------------------- 1 | builder = $builder; 30 | } 31 | 32 | /** 33 | * @group entity 34 | * @group db 35 | * @group db-query-builder 36 | * @group db-query-builder-where 37 | */ 38 | public function testWhere() 39 | { 40 | $where = $this->builder->make(WhereCollection::class); 41 | 42 | $this->assertInstanceOf(WhereCollection::class, $where); 43 | } 44 | 45 | /** 46 | * @group entity 47 | * @group db 48 | * @group db-query-builder 49 | * @group db-query-builder-fields 50 | */ 51 | public function testFields() 52 | { 53 | $where = $this->builder->make(FieldCollection::class); 54 | 55 | $this->assertInstanceOf(FieldCollection::class, $where); 56 | } 57 | 58 | protected function _before() 59 | { 60 | } 61 | 62 | protected function _after() 63 | { 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /tests/unit/DB/ConnectionTest.php: -------------------------------------------------------------------------------- 1 | getCreds(); 31 | 32 | $this->assertSame('db_test', getenv('TEST_MYSQL_HOST')); 33 | $this->assertSame('db_test', $creds['host']); 34 | 35 | 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /tests/unit/DB/FieldCollectionTest.php: -------------------------------------------------------------------------------- 1 | add('id'); 28 | 29 | $this->assertSame('`id`', $fieldCollection->getSQL()); 30 | } 31 | 32 | /** 33 | * @group entity 34 | * @group db 35 | * @group db-field-collection 36 | * @group db-field-collection-add-multiple 37 | */ 38 | public function testAddMultiple() 39 | { 40 | $fieldCollection = new FieldCollection(); 41 | $fieldCollection->add('id'); 42 | $fieldCollection->add('total'); 43 | 44 | $this->assertSame('`id`, `total`', $fieldCollection->getSQL()); 45 | } 46 | 47 | /** 48 | * @group entity 49 | * @group db 50 | * @group db-field-collection 51 | * @group db-field-collection-set 52 | */ 53 | public function testSet() 54 | { 55 | $fieldCollection = new FieldCollection(); 56 | $fieldCollection->set(['id', 'total']); 57 | 58 | $this->assertSame('`id`, `total`', $fieldCollection->getSQL()); 59 | } 60 | 61 | /** 62 | * @group entity 63 | * @group db 64 | * @group db-field-collection 65 | * @group db-field-collection-all 66 | */ 67 | public function testAll() 68 | { 69 | $fieldCollection = new FieldCollection(); 70 | 71 | $this->assertSame('*', $fieldCollection->getSQL()); 72 | } 73 | 74 | protected function _before() 75 | { 76 | } 77 | 78 | protected function _after() 79 | { 80 | } 81 | 82 | } -------------------------------------------------------------------------------- /tests/unit/DB/QueryBuilderTest.php: -------------------------------------------------------------------------------- 1 | builder = $builder; 25 | } 26 | 27 | /** 28 | * @group entity 29 | * @group db 30 | * @group db-query-builder 31 | * @group db-query-builder-select 32 | */ 33 | public function testSelect() 34 | { 35 | $queryBuilder = new QueryBuilder($this->builder); 36 | $queryBuilder->select('invoice'); 37 | 38 | $this->assertSame('SELECT * FROM `invoice`', $queryBuilder->getSQL()); 39 | } 40 | 41 | /** 42 | * @group entity 43 | * @group db 44 | * @group db-query-builder 45 | * @group db-query-builder-select-with-fields 46 | */ 47 | public function testSelectWithFields() 48 | { 49 | $queryBuilder = new QueryBuilder($this->builder); 50 | $queryBuilder->select('invoice', ['id', 'total']); 51 | 52 | $this->assertSame('SELECT `id`, `total` FROM `invoice`', $queryBuilder->getSQL()); 53 | } 54 | 55 | 56 | /** 57 | * @group entity 58 | * @group db 59 | * @group db-query-builder 60 | * @group db-query-builder-and-where 61 | */ 62 | public function testAndWhere() 63 | { 64 | $queryBuilder = new QueryBuilder($this->builder); 65 | $queryBuilder->andWhere('status_id', 4); 66 | 67 | $this->assertSame('WHERE `status_id` =:status_id', $queryBuilder->getSQL()); 68 | 69 | } 70 | 71 | 72 | /** 73 | * @group entity 74 | * @group db 75 | * @group db-query-builder 76 | * @group db-query-builder-insert-invoice 77 | */ 78 | public function testInsertInvoice() 79 | { 80 | $data = [ 81 | 'reference' => 'foo', 82 | 'total' => 1, 83 | 'vat' => 1, 84 | 'status_id' => 4, 85 | 'id' => 5 86 | ]; 87 | $table = 'invoice'; 88 | $sql = QueryBuilder::insert($data, $table); 89 | $expected = "INSERT INTO `invoice` (`reference`, `total`, `vat`, `status_id`, `id`) VALUE (:reference, :total, :vat, :status_id, :id);"; 90 | 91 | $this->assertSame($expected, $sql); 92 | } 93 | 94 | /** 95 | * @group entity 96 | * @group db 97 | * @group db-query-builder 98 | * @group db-query-builder-insert-customer 99 | */ 100 | public function testInsertCustomer() 101 | { 102 | $data = [ 103 | 'first_name' => 'Peter', 104 | 'last_name' => 'Fisher', 105 | 'company_name' => 'How To Code Well', 106 | ]; 107 | $table = 'customer'; 108 | $sql = QueryBuilder::insert($data, $table); 109 | $expected = "INSERT INTO `customer` (`first_name`, `last_name`, `company_name`) VALUE (:first_name, :last_name, :company_name);"; 110 | 111 | $this->assertSame($expected, $sql); 112 | } 113 | 114 | /** 115 | * @group entity 116 | * @group db 117 | * @group db-query-builder 118 | * @group db-query-builder-update 119 | */ 120 | public function testUpdate() 121 | { 122 | $data = [ 123 | 'reference' => 'reference', 124 | 'total' => 'total', 125 | 'vat' => 'vat', 126 | ]; 127 | 128 | $where = [ 129 | 'id' => 'id' 130 | ]; 131 | 132 | $table = 'invoice'; 133 | 134 | $sql = QueryBuilder::update($data, $table, $where); 135 | $expected = "UPDATE `invoice` SET `reference` =:reference, `total` =:total, `vat` =:vat WHERE `id` =:id;"; 136 | 137 | $this->assertSame($expected, $sql); 138 | } 139 | 140 | /** 141 | * @group entity 142 | * @group db 143 | * @group db-query-builder 144 | * @group db-query-builder-insert-or-update-with-no-where-clause 145 | */ 146 | public function testInsertOrUpdateWithNoWhereClause() 147 | { 148 | $data = [ 149 | 'first_name' => 'Peter', 150 | 'last_name' => 'Fisher', 151 | 'company_name' => 'How To Code Well', 152 | ]; 153 | $table = 'customer'; 154 | 155 | $sql = QueryBuilder::insertOrUpdate($data, $table); 156 | $expected = "INSERT INTO `customer` (`first_name`, `last_name`, `company_name`) VALUE (:first_name, :last_name, :company_name);"; 157 | 158 | $this->assertSame($expected, $sql); 159 | } 160 | 161 | /** 162 | * @group entity 163 | * @group db 164 | * @group db-query-builder 165 | * @group db-query-builder-insert-or-update-with-where-clause 166 | */ 167 | public function testInsertOrUpdateWithWhereClause() 168 | { 169 | $data = [ 170 | 'reference' => 'reference', 171 | 'total' => 'total', 172 | 'vat' => 'vat', 173 | ]; 174 | 175 | $where = [ 176 | 'id' => 'id' 177 | ]; 178 | 179 | $table = 'invoice'; 180 | 181 | $sql = QueryBuilder::insertOrUpdate($data, $table, $where); 182 | 183 | $expected = "UPDATE `invoice` SET `reference` =:reference, `total` =:total, `vat` =:vat WHERE `id` =:id;"; 184 | 185 | $this->assertSame($expected, $sql); 186 | } 187 | 188 | /** 189 | * @group entity 190 | * @group db 191 | * @group db-query-builder 192 | * @group db-query-builder-insert-or-update-invoice-with-status 193 | */ 194 | public function testInsertOrUpdateInvoiceWithStatus() 195 | { 196 | $status = new Status(); 197 | $status->setInternalName('test') 198 | ->setName('test') 199 | ->setId(2); 200 | $entity = new Invoice(); 201 | $entity->setReference('foo') 202 | ->setTotal(1) 203 | ->setVAT(1) 204 | ->setStatus($status);; 205 | $data = [ 206 | 'reference' => $entity->getReference(), 207 | 'total' => $entity->getTotal(), 208 | 'vat' => $entity->getVat() 209 | ]; 210 | if ($entity->getStatus() instanceof Status) { 211 | $data['status_id'] = $entity->getStatus()->getId(); 212 | } 213 | 214 | $table = 'invoice'; 215 | 216 | $sql = QueryBuilder::insertOrUpdate($data, $table); 217 | 218 | $expected = "INSERT INTO `invoice` (`reference`, `total`, `vat`, `status_id`) VALUE (:reference, :total, :vat, :status_id);"; 219 | 220 | $this->assertSame($expected, $sql); 221 | } 222 | 223 | /** 224 | * @group entity 225 | * @group db 226 | * @group db-query-builder 227 | * @group db-query-builder-find-one-by-id 228 | */ 229 | public function testFindOneByID() 230 | { 231 | $sql = QueryBuilder::findOneBy('status'); 232 | $expected = "SELECT * FROM `status` WHERE id=:id"; 233 | $this->assertSame($expected, $sql); 234 | } 235 | 236 | /** 237 | * @group entity 238 | * @group db 239 | * @group db-query-builder 240 | * @group db-query-builder-find-all 241 | */ 242 | public function testFindAll() 243 | { 244 | $sql = QueryBuilder::findAll('status'); 245 | $expected = "SELECT * FROM `status`"; 246 | $this->assertSame($expected, $sql); 247 | } 248 | 249 | /** 250 | * @group entity 251 | * @group db 252 | * @group db-query-builder 253 | * @group db-query-builder-find-all-by 254 | */ 255 | public function testFindAllBy() 256 | { 257 | $sql = QueryBuilder::findAllBy('status', [ 258 | 'name' => 'name', 259 | 'internal_name' => 'internal_name' 260 | ]); 261 | $expected = "SELECT * FROM `status` WHERE `name` =:name AND `internal_name` =:internal_name"; 262 | $this->assertSame($expected, $sql); 263 | } 264 | 265 | protected function _before() 266 | { 267 | } 268 | 269 | protected function _after() 270 | { 271 | } 272 | 273 | } -------------------------------------------------------------------------------- /tests/unit/DB/StatusQueryBuilderTest.php: -------------------------------------------------------------------------------- 1 | builder = $builder; 25 | } 26 | 27 | /** 28 | * @group entity 29 | * @group db 30 | * @group db-query-builder-status 31 | * @group db-query-builder-status-select-all 32 | */ 33 | public function testSelectAll() 34 | { 35 | $queryBuilder = new QueryBuilder($this->builder); 36 | $queryBuilder->select('status'); 37 | 38 | $this->assertSame('SELECT * FROM `status`', $queryBuilder->getSQL()); 39 | } 40 | 41 | /** 42 | * @group entity 43 | * @group db 44 | * @group db-query-builder-status 45 | * @group db-query-builder-status-select-by-id 46 | */ 47 | public function testSelectByID() 48 | { 49 | $queryBuilder = new QueryBuilder($this->builder); 50 | $queryBuilder->select('status'); 51 | $queryBuilder->andWhere('id', 4); 52 | 53 | $this->assertSame("SELECT * FROM `status` WHERE `id` =:id", $queryBuilder->getSQL()); 54 | } 55 | 56 | 57 | protected function _before() 58 | { 59 | } 60 | 61 | protected function _after() 62 | { 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /tests/unit/DB/WhereCollectionTest.php: -------------------------------------------------------------------------------- 1 | add('id', 10); 26 | 27 | $this->assertSame('WHERE `id` =:id', $whereCollection->getSQL()); 28 | } 29 | 30 | /** 31 | * @group entity 32 | * @group db 33 | * @group db-where-collection 34 | * @group db-where-collection-add-multiple 35 | */ 36 | public function testAddMultiple() 37 | { 38 | $whereCollection = new WhereCollection(); 39 | $whereCollection->add('id', 10); 40 | $whereCollection->add('total', 15); 41 | 42 | $this->assertSame('WHERE `id` =:id AND `total` =:total', $whereCollection->getSQL()); 43 | } 44 | 45 | /** 46 | * @group entity 47 | * @group db 48 | * @group db-where-collection 49 | * @group db-where-collection-set 50 | */ 51 | public function testSet() 52 | { 53 | $whereCollection = new WhereCollection(); 54 | $whereCollection->set([ 55 | 'id' => 19, 56 | 'total' => 3 57 | ]); 58 | 59 | $this->assertSame('WHERE `id` =:id AND `total` =:total', $whereCollection->getSQL()); 60 | } 61 | 62 | /** 63 | * @group entity 64 | * @group db 65 | * @group db-where-collection 66 | * @group db-where-collection-blank 67 | */ 68 | public function testBlank() 69 | { 70 | $whereCollection = new WhereCollection(); 71 | 72 | $this->assertSame('', $whereCollection->getSQL()); 73 | } 74 | 75 | protected function _before() 76 | { 77 | } 78 | 79 | protected function _after() 80 | { 81 | } 82 | 83 | } -------------------------------------------------------------------------------- /tests/unit/Entity/AddCustomerToInvoiceTest.php: -------------------------------------------------------------------------------- 1 | setCustomer($customer); 31 | $this->assertInstanceOf(Customer::class, $invoice->getCustomer()); 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /tests/unit/Entity/AddInvoiceItemToInvoiceTest.php: -------------------------------------------------------------------------------- 1 | addItem($invoiceItem); 31 | $this->assertInstanceOf(Invoice::class, $invoice); 32 | } 33 | 34 | /** 35 | * @group entity 36 | * @group invoice-add-item 37 | * @group invoice-add-item-set-items 38 | */ 39 | public function testSetItems() 40 | { 41 | $invoiceItem1 = new InvoiceItem(); 42 | $invoiceItem2 = new InvoiceItem(); 43 | $invoice = new Invoice(); 44 | $invoice->setItems([$invoiceItem1]); 45 | $invoice->setItems([$invoiceItem2]); 46 | $this->assertContains($invoiceItem2, $invoice->getItems()); 47 | $this->assertCount(1, $invoice->getItems()); 48 | $this->assertInstanceOf(Invoice::class, $invoice); 49 | } 50 | 51 | /** 52 | * @group entity 53 | * @group invoice-add-item 54 | * @group invoice-add-item-reset-items 55 | */ 56 | public function testResetItems() 57 | { 58 | $invoiceItem = new InvoiceItem(); 59 | $invoice = new Invoice(); 60 | $invoice->setItems([$invoiceItem]); 61 | $invoice->resetItems(); 62 | $this->assertEmpty($invoice->getItems()); 63 | $this->assertInstanceOf(Invoice::class, $invoice); 64 | } 65 | 66 | /** 67 | * @group entity 68 | * @group invoice-add-item 69 | * @group invoice-add-item-does-contain-item 70 | */ 71 | public function testDoesContainItem() 72 | { 73 | $invoiceItem = new InvoiceItem(); 74 | $invoice = new Invoice(); 75 | $invoice->addItem($invoiceItem); 76 | $doesItemsContain = $invoice->doesItemsContain($invoiceItem); 77 | 78 | $this->assertTrue($doesItemsContain); 79 | $this->assertInstanceOf(Invoice::class, $invoice); 80 | } 81 | 82 | /** 83 | * @group entity 84 | * @group invoice-add-item 85 | * @group invoice-add-item-does-not-contain-item 86 | */ 87 | public function testDoesNotContainItem() 88 | { 89 | $invoiceItem = new InvoiceItem(); 90 | $invoice = new Invoice(); 91 | $doesItemsContain = $invoice->doesItemsContain($invoiceItem); 92 | 93 | $this->assertFalse($doesItemsContain); 94 | $this->assertInstanceOf(Invoice::class, $invoice); 95 | } 96 | 97 | /** 98 | * @group entity 99 | * @group invoice-add-item 100 | * @group invoice-add-item-does-not-contain-item 101 | */ 102 | public function testSetTheSameItem() 103 | { 104 | $invoiceItem = new InvoiceItem(); 105 | $invoice = new Invoice(); 106 | $invoice->setItems([$invoiceItem, $invoiceItem]); 107 | $this->assertCount(1, $invoice->getItems()); 108 | $this->assertInstanceOf(Invoice::class, $invoice); 109 | } 110 | } -------------------------------------------------------------------------------- /tests/unit/Entity/CustomerTest.php: -------------------------------------------------------------------------------- 1 | assertEmpty($customer->getCompanyName()); 30 | $this->assertIsString($customer->getCompanyName()); 31 | $this->assertEmpty($customer->getFirstName()); 32 | $this->assertIsString($customer->getFirstName()); 33 | $this->assertEmpty($customer->getLastName()); 34 | $this->assertIsString($customer->getLastName()); 35 | $this->assertEmpty((string) $customer); 36 | } 37 | 38 | /** 39 | * @group entity 40 | * @group customer 41 | * @group customer-set-company-name 42 | */ 43 | public function testSetCompanyName() 44 | { 45 | $customer = new Customer(); 46 | $customer->setCompanyName('How To Code Well'); 47 | $this->assertSame('How To Code Well', $customer->getCompanyName()); 48 | } 49 | 50 | /** 51 | * @group entity 52 | * @group customer 53 | * @group customer-set-first-name 54 | */ 55 | public function testSetFirstName() 56 | { 57 | $customer = new Customer(); 58 | $customer->setFirstName('Peter'); 59 | $this->assertSame('Peter', $customer->getFirstName()); 60 | $this->assertSame('Peter', (string) $customer); 61 | } 62 | 63 | /** 64 | * @group entity 65 | * @group customer 66 | * @group customer-set-last-name 67 | */ 68 | public function testSetLastName() 69 | { 70 | $customer = new Customer(); 71 | $customer->setLastName('Fisher'); 72 | $this->assertSame('Fisher', $customer->getLastName()); 73 | $this->assertSame('Fisher', (string) $customer); 74 | } 75 | 76 | /** 77 | * @group entity 78 | * @group customer 79 | * @group customer-to-string 80 | */ 81 | public function testFullName() 82 | { 83 | $customer = new Customer(); 84 | $customer->setFirstName('Peter'); 85 | $customer->setLastName('Fisher'); 86 | $this->assertSame('Peter Fisher', (string) $customer); 87 | } 88 | 89 | } -------------------------------------------------------------------------------- /tests/unit/Entity/InvoiceItemTest.php: -------------------------------------------------------------------------------- 1 | assertEmpty($invoiceItem->getDescription()); 30 | $this->assertIsString($invoiceItem->getDescription()); 31 | $this->assertIsFloat($invoiceItem->getUnitPrice()); 32 | $this->assertSame(0.0,$invoiceItem->getUnitPrice()); 33 | $this->assertIsInt($invoiceItem->getUnits()); 34 | $this->assertSame(0,$invoiceItem->getUnits()); 35 | $this->assertEmpty($invoiceItem->getReference()); 36 | $this->assertIsString($invoiceItem->getReference()); 37 | $this->assertIsFloat($invoiceItem->getTotal()); 38 | $this->assertSame(0.0,$invoiceItem->getTotal()); 39 | 40 | } 41 | 42 | /** 43 | * @group entity 44 | * @group invoice-item 45 | * @group invoice-item-set-description 46 | */ 47 | public function testDescription() 48 | { 49 | $invoiceItem = new InvoiceItem(); 50 | $item = $invoiceItem->setDescription('Test invoice item'); 51 | 52 | $this->assertInstanceOf(InvoiceItem::class, $item); 53 | $this->assertSame('Test invoice item', $invoiceItem->getDescription()); 54 | } 55 | 56 | /** 57 | * @group entity 58 | * @group invoice-item 59 | * @group invoice-item-set-reference 60 | */ 61 | public function testReference() 62 | { 63 | $invoiceItem = new InvoiceItem(); 64 | $item = $invoiceItem->setReference('Test invoice item reference'); 65 | 66 | $this->assertInstanceOf(InvoiceItem::class, $item); 67 | $this->assertSame('Test invoice item reference', $invoiceItem->getReference()); 68 | } 69 | 70 | 71 | /** 72 | * @group entity 73 | * @group invoice-item 74 | * @group invoice-item-set-units 75 | */ 76 | public function testUnits() 77 | { 78 | $invoiceItem = new InvoiceItem(); 79 | $item = $invoiceItem->setUnits(4); 80 | 81 | $this->assertInstanceOf(InvoiceItem::class, $item); 82 | $this->assertSame(4, $invoiceItem->getUnits()); 83 | } 84 | 85 | /** 86 | * @group entity 87 | * @group invoice-item 88 | * @group invoice-item-set-unit-price 89 | */ 90 | public function testUnitPrice() 91 | { 92 | $invoiceItem = new InvoiceItem(); 93 | $item = $invoiceItem->setUnitPrice(223423.53); 94 | 95 | $this->assertInstanceOf(InvoiceItem::class, $item); 96 | $this->assertSame(223423.53, $invoiceItem->getUnitPrice()); 97 | } 98 | 99 | /** 100 | * @group entity 101 | * @group invoice-item 102 | * @group invoice-item-set-total 103 | */ 104 | public function testTotal() 105 | { 106 | $invoiceItem = new InvoiceItem(); 107 | $item = $invoiceItem->setTotal(124434235.53); 108 | 109 | $this->assertInstanceOf(InvoiceItem::class, $item); 110 | $this->assertSame(124434235.53, $invoiceItem->getTotal()); 111 | } 112 | } -------------------------------------------------------------------------------- /tests/unit/Entity/InvoiceTest.php: -------------------------------------------------------------------------------- 1 | assertNull($invoice->getCustomer()); 30 | $this->assertIsArray($invoice->getItems()); 31 | $this->assertEmpty($invoice->getItems()); 32 | $this->assertIsString($invoice->getReference()); 33 | $this->assertEmpty($invoice->getReference()); 34 | $this->assertIsFloat($invoice->getTotal()); 35 | $this->assertSame(0.0, $invoice->getTotal()); 36 | $this->assertIsFloat($invoice->getVAT()); 37 | $this->assertSame(0.0, $invoice->getVAT()); 38 | $this->assertNull($invoice->getStatus()); 39 | $this->assertNull($invoice->getId()); 40 | $this->assertNull($invoice->getDateCreated()); 41 | $this->assertNull($invoice->getDateUpdated()); 42 | } 43 | 44 | /** 45 | * @group entity 46 | * @group invoice 47 | * @group invoice-set-reference 48 | */ 49 | public function testSetReference() 50 | { 51 | $invoice = new Invoice(); 52 | $invoice->setReference('abc123'); 53 | $this->assertSame('abc123', $invoice->getReference()); 54 | } 55 | 56 | /** 57 | * @group entity 58 | * @group invoice 59 | * @group invoice-set-total 60 | */ 61 | public function testSetTotal() 62 | { 63 | $invoice = new Invoice(); 64 | $invoice->setTotal(100.5); 65 | $this->assertSame( 100.5, $invoice->getTotal()); 66 | } 67 | 68 | /** 69 | * @group entity 70 | * @group invoice 71 | * @group invoice-set-vat 72 | */ 73 | public function testSetVAT() 74 | { 75 | $invoice = new Invoice(); 76 | $invoice->setVAT(123.5); 77 | $this->assertSame( 123.5, $invoice->getVAT()); 78 | } 79 | 80 | 81 | } -------------------------------------------------------------------------------- /tests/unit/Entity/SetStatusToInvoiceTest.php: -------------------------------------------------------------------------------- 1 | setName('draft'); 30 | $invoice = new Invoice(); 31 | $invoice->setStatus($status); 32 | $this->assertInstanceOf(Status::class, $invoice->getStatus()); 33 | $this->assertSame('draft', $invoice->getStatus()->getName()); 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /tests/unit/Entity/StatusTest.php: -------------------------------------------------------------------------------- 1 | assertEmpty($status->getName()); 30 | $this->assertIsString($status->getName()); 31 | $this->assertEmpty($status->getInternalName()); 32 | $this->assertIsString($status->getInternalName()); 33 | } 34 | 35 | /** 36 | * @group entity 37 | * @group status 38 | * @group status-set-name 39 | */ 40 | public function testSetName() 41 | { 42 | $status = new Status(); 43 | $status->setName('draft'); 44 | 45 | $this->assertSame('draft', $status->getName()); 46 | $this->assertSame('DRAFT', $status->getInternalName()); 47 | $this->assertInstanceOf(Status::class, $status); 48 | } 49 | 50 | /** 51 | * @group entity 52 | * @group status 53 | * @group status-set-internal-name 54 | */ 55 | public function testSetInternalName() 56 | { 57 | $status = new Status(); 58 | $status->setInternalName('draft'); 59 | 60 | $this->assertSame('DRAFT', $status->getInternalName()); 61 | $this->assertInstanceOf(Status::class, $status); 62 | } 63 | 64 | /** 65 | * @group entity 66 | * @group status 67 | * @group status-set-internal-name-with-spaces 68 | */ 69 | public function testSetInternalNameWithSpaces() 70 | { 71 | $status = new Status(); 72 | $status->setInternalName('Under Review'); 73 | 74 | $this->assertSame('UNDER_REVIEW', $status->getInternalName()); 75 | $this->assertInstanceOf(Status::class, $status); 76 | } 77 | 78 | 79 | } -------------------------------------------------------------------------------- /tests/unit/Helper/HTTP/Locator/LocatorTest.php: -------------------------------------------------------------------------------- 1 | assertNull($locator->locate()); 34 | 35 | } 36 | 37 | /** 38 | * @group locator 39 | * @group locator-valid-route 40 | */ 41 | public function testInvoiceID() 42 | { 43 | $route = new Route(); 44 | $route->setPattern('/invoice/{id}') 45 | ->setMethods(['GET']) 46 | ->setParameters([ 47 | 'id' => '([0-9]*)' 48 | ]) 49 | ; 50 | $request = new Request('/invoice/123', 'GET'); 51 | $locator = new Locator($request, [$route]); 52 | 53 | $this->assertInstanceOf(Route::class, $locator->locate()); 54 | 55 | } 56 | 57 | /** 58 | * @group locator 59 | * @group locator-valid-route 60 | */ 61 | public function testInvoiceEdit() 62 | { 63 | $route = new Route(); 64 | $route->setPattern('/invoice/{id}/edit') 65 | ->setMethods(['GET']) 66 | ->setParameters([ 67 | 'id' => '([0-9]*)' 68 | ]) 69 | ; 70 | $request = new Request('/invoice/123/edit', 'GET'); 71 | $locator = new Locator($request, [$route]); 72 | 73 | $this->assertInstanceOf(Route::class, $locator->locate()); 74 | 75 | } 76 | 77 | /** 78 | * @group locator 79 | * @group locator-invoice-item-edit 80 | */ 81 | public function testInvoiceItemEdit() 82 | { 83 | $route1 = new Route(); 84 | $route1->setPattern('/invoice/{invoice_id}/item/{item_id}/edit') 85 | ->setMethods(['GET']) 86 | ->setParameters([ 87 | 'invoice_id' => '([0-9]*)', 88 | 'item_id' => '([0-9]*)', 89 | ]) 90 | ; 91 | $route2 = new Route(); 92 | $route2->setPattern('/invoice/{invoice_id}/item/{item_id}/not-valid') 93 | ->setMethods(['GET']) 94 | ->setParameters([ 95 | 'invoice_id' => '([0-9]*)', 96 | 'item_id' => '([0-9]*)', 97 | ]) 98 | ; 99 | $request = new Request('/invoice/123/item/456/edit', 'GET'); 100 | $locator = new Locator($request, [$route1, $route2]); 101 | 102 | $foundRoute = $locator->locate(); 103 | 104 | $this->assertInstanceOf(Route::class, $foundRoute); 105 | $this->assertSame('/invoice/{invoice_id}/item/{item_id}/edit', $foundRoute->getPattern()); 106 | 107 | } 108 | 109 | 110 | } -------------------------------------------------------------------------------- /tests/unit/Helper/HTTP/Request/Factory/Type/ServerFactoryTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf(Request::class, $request); 36 | } 37 | 38 | /** 39 | * @group request 40 | * @group request-server-factory-uri-exception 41 | */ 42 | public function testURIException() 43 | { 44 | $this->tester->expectException(new Exception("REQUEST_URI not found"), function() { 45 | $_SERVER['REQUEST_METHOD'] = 'GET'; 46 | 47 | $factory = new ServerFactory(); 48 | $factory::make(); 49 | }); 50 | 51 | } 52 | 53 | /** 54 | * @group request 55 | * @group request-server-factory-method-exception 56 | */ 57 | public function testMethodException() 58 | { 59 | $this->tester->expectException(new Exception("REQUEST_METHOD not found"), function() { 60 | $_SERVER['REQUEST_URI'] = '/'; 61 | 62 | $factory = new ServerFactory(); 63 | $factory::make(); 64 | }); 65 | 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /tests/unit/Helper/HTTP/Request/RequestTest.php: -------------------------------------------------------------------------------- 1 | assertEmpty($route->getPath()); 30 | $this->assertEmpty($route->getMethod()); 31 | $this->assertEmpty($route->getParameters()); 32 | $this->assertIsArray($route->getParameters()); 33 | } 34 | 35 | /** 36 | * @group request 37 | * @group request-set-URI-in-constructor 38 | */ 39 | public function testSetURIInConstructor() 40 | { 41 | $route = new Request('/'); 42 | 43 | $this->assertSame('/', $route->getPath()); 44 | 45 | } 46 | 47 | /** 48 | * @group request 49 | * @group request-set-URI 50 | */ 51 | public function testSetURI() 52 | { 53 | $route = new Request(); 54 | 55 | $route->setPath('/'); 56 | 57 | $this->assertSame('/', $route->getPath()); 58 | 59 | } 60 | 61 | /** 62 | * @group request 63 | * @group request-set-method-in-constructor 64 | */ 65 | public function testSetMethodInConstructor() 66 | { 67 | $route = new Request('/', 'GET'); 68 | 69 | $this->assertSame('GET', $route->getMethod()); 70 | 71 | } 72 | 73 | /** 74 | * @group request 75 | * @group request-set-method 76 | */ 77 | public function testSetMethod() 78 | { 79 | $route = new Request(); 80 | 81 | $route->setMethod('GET'); 82 | 83 | $this->assertSame('GET', $route->getMethod()); 84 | 85 | } 86 | 87 | /** 88 | * @group request 89 | * @group request-set-method 90 | */ 91 | public function testSetLowerCaseMethod() 92 | { 93 | $route = new Request(); 94 | 95 | $route->setMethod('get'); 96 | 97 | $this->assertSame('GET', $route->getMethod()); 98 | 99 | } 100 | 101 | /** 102 | * @group request 103 | * @group request-add-parameter 104 | */ 105 | public function testAddParameter() 106 | { 107 | $route = new Request(); 108 | 109 | $route->addParameter('id', 123); 110 | 111 | $this->assertSame(123, $route->getParameter('id')); 112 | 113 | } 114 | 115 | /** 116 | * @group request 117 | * @group request-add-parameter 118 | */ 119 | public function testSetParameters() 120 | { 121 | $route = new Request(); 122 | 123 | $route->setParameters([ 124 | 'id' => 123 125 | ]); 126 | 127 | $this->assertArrayHasKey('id', $route->getParameters()); 128 | 129 | } 130 | 131 | /** 132 | * @group request 133 | * @group request-add-parameter 134 | */ 135 | public function testGetDefaultParameter() 136 | { 137 | $route = new Request(); 138 | 139 | $this->assertSame(345, $route->getParameter('id', 345)); 140 | 141 | } 142 | 143 | /** 144 | * @group request 145 | * @group request-add-parameter 146 | */ 147 | public function testGetNullParameter() 148 | { 149 | $route = new Request(); 150 | 151 | $this->assertNull($route->getParameter('id')); 152 | 153 | } 154 | } -------------------------------------------------------------------------------- /tests/unit/Helper/HTTP/Route/FactoryTest.php: -------------------------------------------------------------------------------- 1 | addRoute([ 31 | 'pattern' => '/', 32 | 'controller' => Type\Home::class, 33 | 'method' => ['GET'], 34 | 'action' => 'index' 35 | ]); 36 | 37 | $this->assertInstanceOf(Route::class, $route); 38 | } 39 | 40 | /** 41 | * @group router 42 | * @group router-factory-make-multiple 43 | */ 44 | public function testMakeMultiple() 45 | { 46 | $routes = [ 47 | [ 48 | 'pattern' => '/', 49 | 'controller' => Type\Home::class, 50 | 'method' => ['GET'], 51 | 'action' => 'index' 52 | ], 53 | [ 54 | 'pattern' => '/invoice/([0-9]*)', 55 | 'controller' => Type\Invoice::class, 56 | 'method' => ['GET'], 57 | 'action' => 'index' 58 | ], 59 | [ 60 | 'pattern' => '/invoice/([0-9]*)/edit/([0-9]*)', 61 | 'controller' => Type\Invoice::class, 62 | 'method' => ['GET'], 63 | 'action' => 'index' 64 | ], 65 | ]; 66 | 67 | $factory = new Factory(); 68 | 69 | $results = []; 70 | foreach($routes as $data) { 71 | $results[] = $factory->addRoute($data); 72 | } 73 | 74 | $this->assertEquals(count($routes), count($results)); 75 | } 76 | 77 | /** 78 | * @group router 79 | * @group router-factory-make-routes 80 | */ 81 | public function testMakeRoutes() 82 | { 83 | $routes = [ 84 | [ 85 | 'pattern' => '/', 86 | 'controller' => Type\Home::class, 87 | 'method' => ['GET'], 88 | 'action' => 'index' 89 | ], 90 | [ 91 | 'pattern' => '/invoice/([0-9]*)', 92 | 'controller' => Type\Invoice::class, 93 | 'method' => ['GET'], 94 | 'action' => 'index' 95 | ], 96 | [ 97 | 'pattern' => '/invoice/([0-9]*)/edit/([0-9]*)', 98 | 'controller' => Type\Invoice::class, 99 | 'method' => ['GET'], 100 | 'action' => 'index' 101 | ], 102 | ]; 103 | 104 | $factory = new Factory(); 105 | 106 | $results = $factory->makeRoutes($routes); 107 | $this->assertIsArray($results); 108 | $this->assertEquals(count($routes), count($results)); 109 | } 110 | } -------------------------------------------------------------------------------- /tests/unit/Helper/HTTP/Route/RouteTest.php: -------------------------------------------------------------------------------- 1 | assertSame('', $route->getController()); 31 | $this->assertSame('', $route->getAction()); 32 | $this->assertSame('', $route->getPattern()); 33 | $this->assertSame([], $route->getMethods()); 34 | 35 | } 36 | 37 | /** 38 | * @group route 39 | * @group route-home-page 40 | */ 41 | public function testHomePageIndex() 42 | { 43 | $route = new Route(); 44 | $route->setController(Home::class) 45 | ->setMethods(['GET']) 46 | ->setPattern('/') 47 | ->setAction('index') 48 | ; 49 | 50 | $this->assertSame(Home::class, $route->getController()); 51 | $this->assertSame(['GET'], $route->getMethods()); 52 | $this->assertSame('/', $route->getPattern()); 53 | $this->assertSame('index', $route->getAction()); 54 | 55 | } 56 | 57 | /** 58 | * @group route 59 | * @group route-upper-case-method 60 | */ 61 | public function testUpperCaseMethod() 62 | { 63 | $route = new Route(); 64 | $route->setMethods(['get']); 65 | 66 | $this->assertSame(['GET'], $route->getMethods()); 67 | 68 | } 69 | } -------------------------------------------------------------------------------- /tests/unit/Helper/HTTP/Route/RouterTest.php: -------------------------------------------------------------------------------- 1 | assertIsArray($router->getRoutes()); 31 | $this->assertEquals(0, count($router->getRoutes())); 32 | } 33 | 34 | /** 35 | * @group router 36 | * @group router-routes-array 37 | */ 38 | public function testIsRoutesAnArray() 39 | { 40 | $router = new Router(); 41 | $this->assertIsArray($router->getRoutes()); 42 | } 43 | 44 | /** 45 | * @group router 46 | * @group router-add-route 47 | */ 48 | public function testAddRoute() 49 | { 50 | $route = new Route(); 51 | $route->setController(Home::class) 52 | ->setMethods(['GET']) 53 | ->setPattern('/') 54 | ->setAction('index') 55 | ; 56 | 57 | $router = new Router(); 58 | $router::add($route); 59 | 60 | $this->assertIsArray($router->getRoutes()); 61 | $this->assertEquals(1, count($router->getRoutes())); 62 | } 63 | 64 | /** 65 | * @group router 66 | * @group router-add-duplicate 67 | */ 68 | public function testAddDuplicateRoute() 69 | { 70 | $route = new Route(); 71 | $route->setController(Home::class) 72 | ->setMethods(['GET']) 73 | ->setPattern('/') 74 | ->setAction('index') 75 | ; 76 | 77 | $router = new Router(); 78 | $router::add($route); 79 | $router::add($route); 80 | 81 | $this->assertIsArray($router->getRoutes()); 82 | $this->assertEquals(1, count($router->getRoutes())); 83 | } 84 | } -------------------------------------------------------------------------------- /tests/unit/Helper/HTTP/URI/URIBuilderTest.php: -------------------------------------------------------------------------------- 1 | assertSame('#^$#', $uri); 33 | } 34 | 35 | /** 36 | * @group uri 37 | * @group uri-blank-default-with-array 38 | */ 39 | public function testBlankDefaultWithArray() 40 | { 41 | $uri = URIBuilder::build('',['id' => 123]); 42 | 43 | $this->assertSame('#^$#', $uri); 44 | } 45 | 46 | /** 47 | * @group uri 48 | * @group uri-place-holder 49 | */ 50 | public function testPlaceHolder() 51 | { 52 | $uri = URIBuilder::build('/{foo_bar}', ['foo_bar' => 'abc']); 53 | 54 | $this->assertSame('#^/abc$#', $uri); 55 | } 56 | 57 | /** 58 | * @group uri 59 | * @group uri-broken-place-holder 60 | */ 61 | public function testBrokenPlaceHolder() 62 | { 63 | $uri = URIBuilder::build('/{foo_', ['foo' => 'abc']); 64 | 65 | $this->assertSame('#^/{foo_$#', $uri); 66 | } 67 | } -------------------------------------------------------------------------------- /tests/unit/Helper/HTTP/Validation/Type/ActionValidatorTest.php: -------------------------------------------------------------------------------- 1 | assertTrue($validator->doesExist(Home::class, 'index')); 33 | } 34 | 35 | /** 36 | * @group validation 37 | * @group validation-type 38 | * @group validation-type-action 39 | * @group validation-type-action-does-not-exist 40 | */ 41 | public function testDoesNotActionExist() 42 | { 43 | $validator = new ActionValidator(); 44 | $this->assertFalse($validator->doesExist(Home::class, 'NOT_FOUND')); 45 | } 46 | 47 | /** 48 | * @group validation 49 | * @group validation-type 50 | * @group validation-type-action 51 | * @group validation-type-action-is-in-valid 52 | */ 53 | public function testIsInValid() 54 | { 55 | $route = new Route(); 56 | 57 | $validator = new ActionValidator(); 58 | $validator->setRoute($route); 59 | $this->assertFalse($validator->isValid()); 60 | } 61 | 62 | /** 63 | * @group validation 64 | * @group validation-type 65 | * @group validation-type-action 66 | * @group validation-type-action-is-valid 67 | */ 68 | public function testIsValid() 69 | { 70 | $route = new Route(); 71 | $route->setController(Home::class); 72 | $route->setAction('index'); 73 | 74 | $validator = new ActionValidator(); 75 | $validator->setRoute($route); 76 | $this->assertTrue($validator->isValid()); 77 | } 78 | } -------------------------------------------------------------------------------- /tests/unit/Helper/HTTP/Validation/Type/ControllerValidatorTest.php: -------------------------------------------------------------------------------- 1 | assertTrue($validator->doesExist(Home::class)); 34 | } 35 | 36 | /** 37 | * @group validation 38 | * @group validation-type 39 | * @group validation-type-controller 40 | * @group validation-type-controller-does-not-exist 41 | */ 42 | public function testDoesNotControllerExist() 43 | { 44 | $validator = new ControllerValidator(); 45 | $this->assertFalse($validator->doesExist('NOT_FOUND')); 46 | } 47 | 48 | /** 49 | * @group validation 50 | * @group validation-type 51 | * @group validation-type-controller 52 | * @group validation-type-controller-empty 53 | */ 54 | public function testDoesNotControllerEmpty() 55 | { 56 | $route = new Route(); 57 | 58 | $validator = new ControllerValidator(); 59 | $validator->setRoute($route); 60 | $this->assertFalse($validator->isValid()); 61 | } 62 | 63 | /** 64 | * @group validation 65 | * @group validation-type 66 | * @group validation-type-controller 67 | * @group validation-type-controller-set 68 | */ 69 | public function testDoesNotControllerSet() 70 | { 71 | $route = new Route(); 72 | $route->setController(Home::class); 73 | 74 | $validator = new ControllerValidator(); 75 | $validator->setRoute($route); 76 | $this->assertTrue($validator->isValid()); 77 | } 78 | } -------------------------------------------------------------------------------- /tests/unit/Helper/HTTP/Validation/Type/MethodValidatorTest.php: -------------------------------------------------------------------------------- 1 | setController(Home::class) 35 | ->setMethods(['GET']) 36 | ; 37 | 38 | $validator = new MethodValidator(); 39 | $validator->setRoute($route); 40 | 41 | $this->assertTrue($validator->isValid()); 42 | } 43 | 44 | /** 45 | * @group validation 46 | * @group validation-type 47 | * @group validation-type-method 48 | * @group validation-type-method-is-lowecase 49 | */ 50 | public function testIsLowerCase() 51 | { 52 | $route = new Route(); 53 | $route->setController(Home::class) 54 | ->setMethods(['get']) 55 | ; 56 | 57 | $validator = new MethodValidator(); 58 | $validator->setRoute($route); 59 | 60 | $this->assertTrue($validator->isValid()); 61 | } 62 | 63 | /** 64 | * @group validation 65 | * @group validation-type 66 | * @group validation-type-method 67 | * @group validation-type-method-is-invalid 68 | */ 69 | public function testIsInvalid() 70 | { 71 | $route = new Route(); 72 | $route->setController(Home::class) 73 | ->setMethods(['this-should-not-work']) 74 | ; 75 | 76 | $validator = new MethodValidator(); 77 | $validator->setRoute($route); 78 | 79 | $this->assertFalse($validator->isValid()); 80 | } 81 | 82 | } -------------------------------------------------------------------------------- /tests/unit/Helper/HTTP/Validation/Type/PatternValidatorTest.php: -------------------------------------------------------------------------------- 1 | setRoute($route); 33 | 34 | $this->assertFalse($validator->isValid()); 35 | } 36 | 37 | /** 38 | * @group validation 39 | * @group validation-type 40 | * @group validation-type-pattern 41 | * @group validation-type-pattern-is-valid 42 | */ 43 | public function testIsValid() 44 | { 45 | $route = new Route(); 46 | $route->setPattern('/'); 47 | $validator = new PatternValidator(); 48 | $validator->setRoute($route); 49 | 50 | $this->assertTrue($validator->isValid()); 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /tests/unit/Helper/HTTP/Validation/ValidationTest.php: -------------------------------------------------------------------------------- 1 | addValidator($validator); 34 | 35 | $this->assertTrue($validation->hasValidator(ControllerValidator::class)); 36 | 37 | } 38 | 39 | /** 40 | * @group validation 41 | * @group validation-add-two-validator 42 | */ 43 | public function testValidationAddTwo() 44 | { 45 | $validator1 = new ControllerValidator(); 46 | $validator2 = new MethodValidator(); 47 | 48 | $validation = new Validation(); 49 | $validation->addValidator($validator1); 50 | $validation->addValidator($validator2); 51 | 52 | $this->assertTrue($validation->hasValidator(ControllerValidator::class)); 53 | $this->assertTrue($validation->hasValidator(MethodValidator::class)); 54 | 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /tests/unit/Hydrator/CustomerTest.php: -------------------------------------------------------------------------------- 1 | 1, 31 | 'company_name' => 'Acme Inc', 32 | 'first_name' => 'Peter', 33 | 'last_name' => 'Fisher', 34 | 'date_created' => $date->format(DateTime::ISO8601), 35 | 'date_updated' => $date->format(DateTime::ISO8601) 36 | ]; 37 | $entity = CustomerHydrator::hydrate($data); 38 | 39 | $this->assertInstanceOf(Customer::class, $entity); 40 | $this->assertSame(1, $entity->getId()); 41 | $this->assertSame('Acme Inc', $entity->getCompanyName()); 42 | $this->assertSame('Peter', $entity->getFirstName()); 43 | $this->assertSame('Fisher', $entity->getLastName()); 44 | $this->assertInstanceOf(DateTime::class, $entity->getDateCreated()); 45 | $this->assertInstanceOf(DateTime::class, $entity->getDateUpdated()); 46 | 47 | } 48 | } -------------------------------------------------------------------------------- /tests/unit/Hydrator/InvoiceItemTest.php: -------------------------------------------------------------------------------- 1 | 1, 31 | 'reference' => 'invoice-item-001', 32 | 'description' => 'Development time', 33 | 'unit_price' => 2.85, 34 | 'units' => 7, 35 | 'total' => 350, 36 | 'date_created' => $date->format(DateTime::ISO8601), 37 | 'date_updated' => $date->format(DateTime::ISO8601) 38 | ]; 39 | $entity = InvoiceItemHydrator::hydrate($data); 40 | 41 | $this->assertInstanceOf(InvoiceItem::class, $entity); 42 | $this->assertSame(1, $entity->getId()); 43 | $this->assertSame('invoice-item-001', $entity->getReference()); 44 | $this->assertSame('Development time', $entity->getDescription()); 45 | $this->assertSame(2.85, $entity->getUnitPrice()); 46 | $this->assertSame(7, $entity->getUnits()); 47 | $this->assertSame(350.0, $entity->getTotal()); 48 | $this->assertInstanceOf(DateTime::class, $entity->getDateCreated()); 49 | $this->assertInstanceOf(DateTime::class, $entity->getDateUpdated()); 50 | } 51 | } -------------------------------------------------------------------------------- /tests/unit/Hydrator/InvoiceTest.php: -------------------------------------------------------------------------------- 1 | 1, 32 | 'reference' => 'invoice-001', 33 | 'total' => 2.99, 34 | 'vat' => 1.25, 35 | 'date_created' => $date->format(DateTime::ISO8601), 36 | 'date_updated' => $date->format(DateTime::ISO8601) 37 | ]; 38 | $entity = InvoiceHydrator::hydrate($data); 39 | 40 | $this->assertInstanceOf(Invoice::class, $entity); 41 | $this->assertSame(1, $entity->getId()); 42 | $this->assertSame('invoice-001', $entity->getReference()); 43 | $this->assertSame(2.99, $entity->getTotal()); 44 | $this->assertSame(1.25, $entity->getVAT()); 45 | $this->assertInstanceOf(DateTime::class, $entity->getDateCreated()); 46 | $this->assertInstanceOf(DateTime::class, $entity->getDateUpdated()); 47 | } 48 | } -------------------------------------------------------------------------------- /tests/unit/Hydrator/StatusTest.php: -------------------------------------------------------------------------------- 1 | 1, 31 | 'name' => 'test', 32 | 'internal_name' => 'TEST', 33 | 'date_created' => $date->format(DateTime::ISO8601), 34 | 'date_updated' => $date->format(DateTime::ISO8601) 35 | ]; 36 | $entity = StatusHydrator::hydrate($data); 37 | 38 | $this->assertInstanceOf(Status::class, $entity); 39 | $this->assertSame(1, $entity->getId()); 40 | $this->assertSame('test', $entity->getName()); 41 | $this->assertSame('TEST', $entity->getInternalName()); 42 | $this->assertInstanceOf(DateTime::class, $entity->getDateCreated()); 43 | $this->assertInstanceOf(DateTime::class, $entity->getDateUpdated()); 44 | } 45 | } --------------------------------------------------------------------------------