Skip to content
Draft
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
12 changes: 8 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,19 @@
"minimum-stability": "dev",
"prefer-stable": true,
"require": {
"php": "^8.0",
"doctrine/dbal": "^3.1.4",
"php": "^8.3",
"guzzlehttp/guzzle": "^7.8",
"symfony/yaml": "^6.0",
"laravel/helpers": "^1.8",
"symfony/yaml": "^6.0|^7.0",
"tymon/jwt-auth": "^2.1.0",
"dreamfactory/df-system": "~0.6.2"
},
"require-dev": {
"phpunit/phpunit": "@stable"
"laravel/framework": "^13.7",
"mockery/mockery": "^1.6",
"nunomaduro/collision": "^8.6",
"orchestra/testbench": "^11.0",
"phpunit/phpunit": "^11.5.3"
},
"autoload": {
"files": [
Expand Down
2 changes: 1 addition & 1 deletion src/Database/Connectors/SQLiteConnector.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class SQLiteConnector extends \Illuminate\Database\Connectors\SQLiteConnector
* @param array $config
* @return \PDO
*/
public function connect(array $config)
public function connect(array $config): \PDO
{
$options = $this->getOptions($config);

Expand Down
3 changes: 1 addition & 2 deletions src/Http/Controllers/Controller.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
<?php namespace DreamFactory\Core\Http\Controllers;

use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;

class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
use AuthorizesRequests, ValidatesRequests;
}
26 changes: 15 additions & 11 deletions src/LaravelServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,8 @@ public function boot()

$this->registerOtherProviders();

// add routes
/** @noinspection PhpUndefinedMethodInspection */
if (!$this->app->routesAreCached()) {
include __DIR__ . '/../routes/routes.php';
}
// add routes (loadRoutesFrom handles the route-cache check internally)
$this->loadRoutesFrom(__DIR__ . '/../routes/routes.php');

// add commands, https://laravel.com/docs/5.4/packages#commands
$this->addCommands();
Expand All @@ -83,8 +80,10 @@ public function boot()
*/
public function register()
{
// Register MongoDB provider first
$this->app->register(MongoDBServiceProvider::class);
// Register MongoDB provider first (gated — package is optional)
if (class_exists(MongoDBServiceProvider::class)) {
$this->app->register(MongoDBServiceProvider::class);
}

// merge in df config, https://laravel.com/docs/5.4/packages#resources
$this->mergeConfigFrom(__DIR__ . '/../config/df.php', 'df');
Expand Down Expand Up @@ -117,8 +116,10 @@ protected function addMiddleware()
Route::aliasMiddleware('df.access_check', AccessCheck::class);
Route::aliasMiddleware('df.verb_override', VerbOverrides::class);

/** Add the first user check to the web group */
Route::prependMiddlewareToGroup('web', FirstUserCheck::class);
/** Add the first user check to the web group (gated — `web` may not be defined in API-only apps) */
if (Route::hasMiddlewareGroup('web')) {
Route::prependMiddlewareToGroup('web', FirstUserCheck::class);
}

$middleware = [
'df.verb_override',
Expand Down Expand Up @@ -183,7 +184,10 @@ protected function registerExtensions()

protected function registerOtherProviders()
{
// use CORS
$this->app->register(CorsServiceProvider::class);
// use CORS (gated — Laravel HandleCors middleware ships in framework so the
// provider class is always available, but keep the gate symmetric/defensive)
if (class_exists(CorsServiceProvider::class)) {
$this->app->register(CorsServiceProvider::class);
}
}
}
16 changes: 13 additions & 3 deletions src/Models/NoDbModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,25 @@ public function getCasts()
return $casts;
}

// not sure why Laravel has these are in the HasAttributes trait instead of the model, but they need simplification
// The HasAttributes trait calls $this->getDates() and $this->getDateFormat() internally
// during attributesToArray(). The trait's own getDates() implementation depends on
// usesTimestamps() / $dates, neither of which NoDbModel inherits (it doesn't extend
// Model and doesn't use HasTimestamps). We provide stub overrides that short-circuit
// the date handling so attributesToArray() works for this Model-less use case.
//
// Historical note: Eloquent's Model::getDates() was removed in Laravel 10, but the
// method still lives in HasAttributes and is invoked from inside the trait, so the
// override remains necessary as long as NoDbModel uses HasAttributes directly.
public function getDates()
{
return $this->dates;
return property_exists($this, 'dates') ? (array) $this->dates : [];
}

protected function getDateFormat()
{
return $this->dateFormat;
return property_exists($this, 'dateFormat') && $this->dateFormat
? $this->dateFormat
: 'Y-m-d H:i:s';
}

/**
Expand Down
4 changes: 1 addition & 3 deletions src/Providers/CorsServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use Fruitcake\Cors\CorsService;
use Illuminate\Http\Middleware\HandleCors;
use Illuminate\Database\QueryException;
use Illuminate\Contracts\Http\Kernel;
use Illuminate\Http\Request;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
Expand All @@ -31,10 +30,9 @@ public function register()
* Add the Cors middleware to the router.
*
* @param Request $request
* @param Kernel $kernel
* @throws \Exception
*/
public function boot(Request $request, Kernel $kernel)
public function boot(Request $request)
{
$api_prefix = config('df.api_route_prefix', 'api');
config(['cors.paths' => [$api_prefix . '/*']]);
Expand Down
58 changes: 55 additions & 3 deletions src/Testing/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class TestCase extends LaravelTestCase
/**
* Runs before every test class.
*/
public static function setupBeforeClass(): void
public static function setUpBeforeClass(): void
{
echo "\n------------------------------------------------------------------------------\n";
echo "Running test: " . get_called_class() . "\n";
Expand Down Expand Up @@ -110,17 +110,69 @@ public function stage()
/**
* Creates the application.
*
* Consuming applications should override this if the Laravel-style
* bootstrap path differs from the conventional `bootstrap/app.php`
* relative to the host project root. The base path is resolved from
* the consumer's working tree (parent of the running phpunit binary)
* rather than the current working directory, so tests can be invoked
* from any cwd.
*
* @return \Illuminate\Foundation\Application
*/
public function createApplication()
{
$app = require './bootstrap/app.php';
$bootstrap = $this->resolveBootstrapPath();

/** @var \Illuminate\Foundation\Application $app */
$app = require $bootstrap;

$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
$app->make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap();

return $app;
}

/**
* Resolve the path to the Laravel application bootstrap file.
*
* Order of resolution:
* 1. DF_TEST_BOOTSTRAP env var (explicit override)
* 2. df-core's own ./bootstrap/app.php (when df-core has its own)
* 3. Walk up from this file looking for a vendor/.. host project root
*
* @return string
*/
protected function resolveBootstrapPath(): string
{
if ($override = getenv('DF_TEST_BOOTSTRAP')) {
return $override;
}

// df-core itself: __DIR__ = src/Testing, so root is two levels up.
$localCandidate = dirname(__DIR__, 2) . '/bootstrap/app.php';
if (file_exists($localCandidate)) {
return $localCandidate;
}

// Installed under a host project's vendor/dreamfactory/df-core/src/Testing
// → walk up to the host project root (parent of vendor/).
$dir = __DIR__;
for ($i = 0; $i < 10; $i++) {
$candidate = $dir . '/bootstrap/app.php';
if (file_exists($candidate) && is_file($dir . '/artisan')) {
return $candidate;
}
$parent = dirname($dir);
if ($parent === $dir) {
break;
}
$dir = $parent;
}

throw new \RuntimeException(
'Unable to locate bootstrap/app.php. Set DF_TEST_BOOTSTRAP env var to its absolute path.'
);
}

/**
* @param $verb
* @param $url
Expand Down
10 changes: 6 additions & 4 deletions src/helpers.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

use Illuminate\Support\Arr;

if (!function_exists('to_bool')) {
/**
* Convert any value to boolean value.
Expand Down Expand Up @@ -44,7 +46,7 @@ function to_bool($value)
*/
function array_get_bool($array, $key, $default = false)
{
return to_bool(array_get($array, $key, $default));
return to_bool(Arr::get($array, $key, $default));
}
}

Expand All @@ -65,9 +67,9 @@ function array_by_key_value($array, $key, $value, $returnKey = null)
{
if (is_array($array)) {
foreach ($array as $item) {
if ($value === array_get($item, $key)) {
if ($value === Arr::get($item, $key)) {
if ($returnKey) {
return array_get($item, $returnKey);
return Arr::get($item, $returnKey);
} else {
return $item;
}
Expand Down Expand Up @@ -140,7 +142,7 @@ function array_get_or(array $data, array $keys, $default = null)
{
$out = null;
foreach ($keys as $key) {
$out = array_get($data, $key);
$out = Arr::get($data, $key);
if ($out !== null) {
break;
}
Expand Down