Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ docs
.vscode
composer.lock
.phpunit.result.cache
clover.xml
clover.xml
config/db.dev.php
12 changes: 5 additions & 7 deletions .scrutinizer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ checks:
duplication: true

build:
image: default-bionic
image: default-jammy
environment:
php: 8.1.12
variables:
XDEBUG_MODE: 'coverage'
php: 8.4.0
nodes:
coverage:
services:
Expand All @@ -26,12 +24,12 @@ build:
- sudo apt install -y ffmpeg exiftool
tests:
override:
- command: ./vendor/bin/phpunit --coverage-clover=build/coverage/clover.xml # Or "./vendor/bin/phpunit --coverage-clover=build/coverage/clover.xml"
- command: mkdir -p build/logs && DIVERGENCE_TEST_DB=tests-mysql phpdbg -qrr ./vendor/bin/phpunit --coverage-clover build/logs/clover.xml
idle_timeout: 300
coverage:
file: 'build/coverage/clover.xml'
file: 'build/logs/clover.xml'
format: 'php-clover'
analysis:
tests:
override:
- php-scrutinizer-run
- php-scrutinizer-run
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
language: php
php:
- '8.1'
- '8.4'

services:
- mysql
Expand Down Expand Up @@ -33,7 +33,7 @@ before_script:
- ls -al

script:
- ./vendor/bin/phpunit --coverage-clover build/logs/clover.xml
- composer test:mysql

after_success:
# Submit coverage report to Coveralls servers, see .coveralls.yml
Expand All @@ -49,4 +49,4 @@ after_success:
cache:
directories:
- vendor
- $HOME/.cache/composer
- $HOME/.cache/composer
7 changes: 6 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@
},
"scripts": {
"fix-code": "php-cs-fixer fix",
"test": "vendor/bin/phpunit --coverage-clover build/logs/clover.xml"
"test": [
"@test:mysql",
"@test:sqlite"
],
"test:mysql": "DIVERGENCE_TEST_DB=tests-mysql vendor/bin/phpunit --coverage-clover build/logs/clover.xml",
"test:sqlite": "DIVERGENCE_TEST_DB=tests-sqlite-memory vendor/bin/phpunit"
},
"support": {
"issues": "https://github.com/Divergence/framework/issues"
Expand Down
29 changes: 29 additions & 0 deletions config/db.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
$devConfig = __DIR__ . '/db.dev.php';

if (file_exists($devConfig)) {
return require $devConfig;
}

return [
/*
* MySQL database configuration
Expand Down Expand Up @@ -52,4 +58,27 @@
'username' => 'root',
'password' => '',
],
/*
* SQLite database configuration
*/
'sqlite' => [
'path' => __DIR__ . '/../var/sqlite/app.sqlite',
'foreign_keys' => true,
'busy_timeout' => 5000,
],
'dev-sqlite' => [
'path' => __DIR__ . '/../var/sqlite/dev.sqlite',
'foreign_keys' => true,
'busy_timeout' => 5000,
],
'tests-sqlite-memory' => [
'path' => ':memory:',
'foreign_keys' => true,
'busy_timeout' => 5000,
],
'tests-sqlite-files' => [
'path' => __DIR__ . '/../var/sqlite/tests.sqlite',
'foreign_keys' => true,
'busy_timeout' => 5000,
],
];
5 changes: 4 additions & 1 deletion phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@
</exclude>
</coverage>
<testsuites>
<testsuite name="all">
<testsuite name="tests-mysql">
<directory>tests/Divergence</directory>
</testsuite>
<!--<testsuite name="tests-sqlite-memory">
<file>tests/DivergenceSQLite/SQLiteSuiteLoader.php</file>
</testsuite>-->
</testsuites>
<listeners>
<listener class="Divergence\Tests\TestListener" file="./tests/Divergence/TestListener.php"/>
Expand Down
60 changes: 53 additions & 7 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,34 @@
---
Divergence is a PHP framework designed for rapid development and modern practices without becoming an over abstracted mess.

**Requires PHP 8.1+**

## [Documentation](https://github.com/Divergence/docs#divergence-framework-documentation)
## [Getting Started](https://github.com/Divergence/docs/blob/release/gettingstarted.md#getting-started)
## [V3 Architecture](docs/v3-architecture.md)

## Minimal Model

```php
<?php

namespace App\Models;

use Divergence\Models\Model;
use Divergence\Models\Mapping\Column;

class Article extends Model
{
public static $tableName = 'articles';

#[Column(type: 'string', notnull: true)]
private string $Title;

#[Column(type: 'clob', notnull: true)]
private string $Body;
}
```

[![asciicast](https://asciinema.org/a/FhE9hATLKDhH7oQfFbeNG5hzs.png)](https://asciinema.org/a/FhE9hATLKDhH7oQfFbeNG5hzs)

## Purpose
This collection of classes contains my favorite building blocks for developing websites with PHP and they have an impressive track record with hundreds of currently active websites using one version or another of the classes in this framework. While they were originally written years ago they are all PSR compatible and support modern practices out of the box.
Expand All @@ -16,17 +40,18 @@ Unit testing the code base and providing code coverage is a primary goal of this
# Main Features
* Models
* Real PHP classes.
* Map fields with array or attributes.
* Declare fields with static arrays or PHP 8 attributes (`#[Column(...)]`).
* Declare relationships with static arrays or PHP 8 attributes (`#[Relation(...)]`).
* Built in support for relationships and object versioning.
* Speed up prototyping and automate new deployments by automatically creates table based on your models when none are found.
* Built in support for MySQL.
* Speed up prototyping and automate new deployments by automatically creating tables based on your models when none are found.
* Built in support for MySQL and SQLite.

* Routing
* Simpler, faster, tree based routing system.
* Built with basic class inheritance in mind.

* Controllers
* Psr7 compatible controllers.
* PSR-7 compatible controllers.
* Pre-made REST API controllers allow you to build APIs rapidly.
* 100% Unit test coverage for filters, sorters, and conditions.
* Build HTTP APIs in minutes by extending `RecordsRequestHandler` and setting the one config variable: the name of your model class.
Expand All @@ -43,6 +68,27 @@ Unit testing the code base and providing code coverage is a primary goal of this
* Manage media remotely with a built in JSON API using the standard permissions interface for all controllers.
* Supports POST and PUT request types for media uploads.

## Installation

```bash
composer require divergence/divergence
```

The [divergence/cli](https://packagist.org/packages/divergence/cli) package is also available to initialize new projects and manage database configurations from the command line.

## Running Tests

```bash
# Run all test suites
composer test

# MySQL suite only
composer test:mysql

# SQLite in-memory suite only
composer test:sqlite
```

### Contributing To Divergence

**All issues and pull requests should be filed on the [Divergence/framework](http://github.com/Divergence/framework) repository.**
Expand All @@ -52,5 +98,5 @@ Unit testing the code base and providing code coverage is a primary goal of this
The Divergence framework is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)

### Credits
- Much of the original code in this framework was published as part of the [PHP framework portion](https://github.com/JarvusInnovations/Emergence-Skeleton) of [Emergence](https://github.com/JarvusInnovations/Emergence) by [Chris Alfano](https://github.com/themightychris).
- This project is maintained by [Henry Paradiz](https://github.com/hparadiz)
- The patterns in this framework are a fork of the [PHP framework portion](https://github.com/JarvusInnovations/Emergence-Skeleton) of [Emergence](https://github.com/JarvusInnovations/Emergence) by [Chris Alfano](https://github.com/themightychris).
- This project is maintained by [Henry Paradiz](https://github.com/hparadiz)
28 changes: 15 additions & 13 deletions src/Controllers/RecordsRequestHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@

use Exception;
use Divergence\Helpers\JSON;
use Divergence\IO\Database\Connections;
use Divergence\Responders\JsonBuilder;
use Divergence\Responders\TwigBuilder;
use Divergence\IO\Database\MySQL as DB;
use Divergence\Responders\JsonpBuilder;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
Expand All @@ -25,7 +25,6 @@
*
* @package Divergence
* @author Henry Paradiz <henry.paradiz@gmail.com>
* @author Chris Alfano <themightychris@gmail.com>
*/
abstract class RecordsRequestHandler extends RequestHandler
{
Expand Down Expand Up @@ -198,14 +197,15 @@ public function handleBrowseRequest($options = [], $conditions = [], $responseID
}

$className = static::$recordClass;
$storageClass = Connections::getConnectionType();

return $this->respond(
isset($responseID) ? $responseID : $this->getTemplateName($className::$pluralNoun),
isset($responseID) ? $responseID : $this->getTemplateName($className::getPluralNoun()),
array_merge($responseData, [
'success' => true,
'data' => $className::getAllByWhere($conditions, $options),
'conditions' => $conditions,
'total' => DB::foundRows(),
'total' => $storageClass::foundRows(),
'limit' => $options['limit'],
'offset' => $options['offset'],
])
Expand All @@ -225,7 +225,7 @@ public function handleRecordRequest(ActiveRecord $Record, $action = false)
{
$className = static::$recordClass;

return $this->respond($this->getTemplateName($className::$singularNoun), [
return $this->respond($this->getTemplateName($className::getSingularNoun()), [
'success' => true,
'data' => $Record,
]);
Expand Down Expand Up @@ -264,7 +264,8 @@ public function getDatumRecord($datum)
$className = static::$recordClass;
$PrimaryKey = $className::getPrimaryKey();
if (empty($datum[$PrimaryKey])) {
$record = new $className::$defaultClass();
$defaultClass = $className::getDefaultClassName();
$record = new $defaultClass();
$this->onRecordCreated($record, $datum);
} else {
if (!$record = $className::getByID($datum[$PrimaryKey])) {
Expand Down Expand Up @@ -344,7 +345,7 @@ public function handleMultiSaveRequest(): ResponseInterface
}


return $this->respond($this->getTemplateName($className::$pluralNoun).'Saved', [
return $this->respond($this->getTemplateName($className::getPluralNoun()).'Saved', [
'success' => count($results) || !count($failed),
'data' => $results,
'failed' => $failed,
Expand Down Expand Up @@ -417,7 +418,7 @@ public function handleMultiDestroyRequest(): ResponseInterface
}
}

return $this->respond($this->getTemplateName($className::$pluralNoun).'Destroyed', [
return $this->respond($this->getTemplateName($className::getPluralNoun()).'Destroyed', [
'success' => count($results) || !count($failed),
'data' => $results,
'failed' => $failed,
Expand All @@ -432,7 +433,8 @@ public function handleCreateRequest(ActiveRecord $Record = null): ResponseInterf

if (!$Record) {
$className = static::$recordClass;
$Record = new $className::$defaultClass();
$defaultClass = $className::getDefaultClassName();
$Record = new $defaultClass();
}

// call template function
Expand Down Expand Up @@ -485,7 +487,7 @@ public function handleEditRequest(ActiveRecord $Record): ResponseInterface
$this->onRecordSaved($Record, $_REQUEST);

// fire created response
$responseID = $this->getTemplateName($className::$singularNoun).'Saved';
$responseID = $this->getTemplateName($className::getSingularNoun()).'Saved';
$responseData = [
'success' => true,
'data' => $Record,
Expand All @@ -496,7 +498,7 @@ public function handleEditRequest(ActiveRecord $Record): ResponseInterface
// fall through back to form if validation failed
}

$responseID = $this->getTemplateName($className::$singularNoun).'Edit';
$responseID = $this->getTemplateName($className::getSingularNoun()).'Edit';
$responseData = [
'success' => false,
'data' => $Record,
Expand All @@ -522,14 +524,14 @@ public function handleDeleteRequest(ActiveRecord $Record): ResponseInterface
$this->onRecordDeleted($Record, $data);

// fire created response
return $this->respond($this->getTemplateName($className::$singularNoun).'Deleted', [
return $this->respond($this->getTemplateName($className::getSingularNoun()).'Deleted', [
'success' => true,
'data' => $Record,
]);
}

return $this->respond('confirm', [
'question' => 'Are you sure you want to delete this '.$className::$singularNoun.'?',
'question' => 'Are you sure you want to delete this '.$className::getSingularNoun().'?',
'data' => $Record,
]);
}
Expand Down
1 change: 0 additions & 1 deletion src/Helpers/JSON.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*
* @package Divergence
* @author Henry Paradiz <henry.paradiz@gmail.com>
* @author Chris Alfano <themightychris@gmail.com>
*/
class JSON
{
Expand Down
Loading