Changing Friendica\App\Mode from static methods to public methods

- Changing from static methods to public methods
- Adding dev-composer-dependency Mockery for static method mocking (f.e. Config, DBA)
- Adding ModeTest with Mocking
- removing bootstrap from phpunit.xml because of double loading tests\bootstrap.php
This commit is contained in:
Philipp Holzer 2018-10-06 16:27:20 +02:00
parent 5014779052
commit 31148e25cf
No known key found for this signature in database
GPG key ID: 517BE60E2CE5C8A5
21 changed files with 498 additions and 106 deletions

View file

@ -54,7 +54,7 @@ require_once "include/dba.php";
$a = new App(dirname(__DIR__)); $a = new App(dirname(__DIR__));
if (App\Mode::isNormal()) { if ($a->getMode()->isNormal()) {
$oAuth = new ExAuth(); $oAuth = new ExAuth();
$oAuth->readStdin(); $oAuth->readStdin();
} }

View file

@ -34,7 +34,7 @@ require_once "include/dba.php";
$a = new App(dirname(__DIR__)); $a = new App(dirname(__DIR__));
if (App\Mode::isInstall()) { if ($a->getMode()->isInstall()) {
die("Friendica isn't properly installed yet.\n"); die("Friendica isn't properly installed yet.\n");
} }

View file

@ -75,7 +75,8 @@
"phpunit/dbunit": "^2.0", "phpunit/dbunit": "^2.0",
"phpdocumentor/reflection-docblock": "^3.0.2", "phpdocumentor/reflection-docblock": "^3.0.2",
"phpunit/php-token-stream": "^1.4.2", "phpunit/php-token-stream": "^1.4.2",
"mikey179/vfsStream": "^1.6" "mikey179/vfsStream": "^1.6",
"mockery/mockery": "^1.2"
}, },
"scripts": { "scripts": {
"test": "phpunit" "test": "phpunit"

203
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "c2306df3b19ec46d53bb16ac2cffa51a", "content-hash": "9f0dbeccbae197460a0ce74a940177cd",
"packages": [ "packages": [
{ {
"name": "asika/simple-console", "name": "asika/simple-console",
@ -818,6 +818,28 @@
"reference": null, "reference": null,
"shasum": "30dc7a7ce872155b23a33bd10ad4c76c0d613f55" "shasum": "30dc7a7ce872155b23a33bd10ad4c76c0d613f55"
}, },
"require-dev": {
"npm-asset/babel-core": ">=6.26.0,<7.0.0",
"npm-asset/babel-plugin-external-helpers": ">=6.22.0,<7.0.0",
"npm-asset/babel-preset-env": ">=1.6.1,<2.0.0",
"npm-asset/cpy-cli": ">=1.0.1,<2.0.0",
"npm-asset/cssnano": ">=3.10.0,<4.0.0",
"npm-asset/del-cli": ">=1.1.0,<2.0.0",
"npm-asset/eslint": ">=4.14.0,<5.0.0",
"npm-asset/eslint-config-airbnb-base": ">=12.1.0,<13.0.0",
"npm-asset/eslint-plugin-import": ">=2.8.0,<3.0.0",
"npm-asset/node-qunit-phantomjs": ">=2.0.0,<3.0.0",
"npm-asset/npm-run-all": ">=4.1.2,<5.0.0",
"npm-asset/postcss-cli": ">=4.1.1,<5.0.0",
"npm-asset/postcss-cssnext": ">=3.0.2,<4.0.0",
"npm-asset/postcss-header": ">=1.0.0,<2.0.0",
"npm-asset/postcss-url": ">=7.3.0,<8.0.0",
"npm-asset/rollup": ">=0.53.3,<0.54.0",
"npm-asset/rollup-plugin-babel": ">=3.0.3,<4.0.0",
"npm-asset/rollup-watch": ">=4.3.1,<5.0.0",
"npm-asset/stylefmt": ">=6.0.0,<7.0.0",
"npm-asset/uglify-js": ">=3.3.4,<4.0.0"
},
"type": "npm-asset-library", "type": "npm-asset-library",
"extra": { "extra": {
"npm-asset-bugs": { "npm-asset-bugs": {
@ -997,6 +1019,22 @@
"require": { "require": {
"npm-asset/ev-emitter": ">=1.0.0,<2.0.0" "npm-asset/ev-emitter": ">=1.0.0,<2.0.0"
}, },
"require-dev": {
"npm-asset/chalk": ">=1.1.1,<2.0.0",
"npm-asset/cheerio": ">=0.19.0,<0.20.0",
"npm-asset/gulp": ">=3.9.0,<4.0.0",
"npm-asset/gulp-jshint": ">=1.11.2,<2.0.0",
"npm-asset/gulp-json-lint": ">=0.1.0,<0.2.0",
"npm-asset/gulp-rename": ">=1.2.2,<2.0.0",
"npm-asset/gulp-replace": ">=0.5.4,<0.6.0",
"npm-asset/gulp-requirejs-optimize": "dev-github:metafizzy/gulp-requirejs-optimize",
"npm-asset/gulp-uglify": ">=1.4.2,<2.0.0",
"npm-asset/gulp-util": ">=3.0.7,<4.0.0",
"npm-asset/highlight.js": ">=8.9.1,<9.0.0",
"npm-asset/marked": ">=0.3.5,<0.4.0",
"npm-asset/minimist": ">=1.2.0,<2.0.0",
"npm-asset/transfob": ">=1.0.0,<2.0.0"
},
"type": "npm-asset-library", "type": "npm-asset-library",
"extra": { "extra": {
"npm-asset-bugs": { "npm-asset-bugs": {
@ -1042,6 +1080,14 @@
"reference": null, "reference": null,
"shasum": "2736e332aaee73ccf0a14a5f0066391a0a13f4a3" "shasum": "2736e332aaee73ccf0a14a5f0066391a0a13f4a3"
}, },
"require-dev": {
"npm-asset/grunt": "~0.4.2",
"npm-asset/grunt-contrib-cssmin": "~0.9.0",
"npm-asset/grunt-contrib-jshint": "~0.6.3",
"npm-asset/grunt-contrib-less": "~0.11.0",
"npm-asset/grunt-contrib-uglify": "~0.4.0",
"npm-asset/grunt-contrib-watch": "~0.6.1"
},
"type": "npm-asset-library", "type": "npm-asset-library",
"extra": { "extra": {
"npm-asset-bugs": { "npm-asset-bugs": {
@ -1075,6 +1121,32 @@
"reference": null, "reference": null,
"shasum": "2c89d6889b5eac522a7eea32c14521559c6cbf02" "shasum": "2c89d6889b5eac522a7eea32c14521559c6cbf02"
}, },
"require-dev": {
"npm-asset/commitplease": "2.0.0",
"npm-asset/core-js": "0.9.17",
"npm-asset/grunt": "0.4.5",
"npm-asset/grunt-babel": "5.0.1",
"npm-asset/grunt-cli": "0.1.13",
"npm-asset/grunt-compare-size": "0.4.0",
"npm-asset/grunt-contrib-jshint": "0.11.2",
"npm-asset/grunt-contrib-uglify": "0.9.2",
"npm-asset/grunt-contrib-watch": "0.6.1",
"npm-asset/grunt-git-authors": "2.0.1",
"npm-asset/grunt-jscs": "2.1.0",
"npm-asset/grunt-jsonlint": "1.0.4",
"npm-asset/grunt-npmcopy": "0.1.0",
"npm-asset/gzip-js": "0.3.2",
"npm-asset/jsdom": "5.6.1",
"npm-asset/load-grunt-tasks": "1.0.0",
"npm-asset/qunit-assert-step": "1.0.3",
"npm-asset/qunitjs": "1.17.1",
"npm-asset/requirejs": "2.1.17",
"npm-asset/sinon": "1.10.3",
"npm-asset/sizzle": "2.2.1",
"npm-asset/strip-json-comments": "1.0.3",
"npm-asset/testswarm": "1.1.0",
"npm-asset/win-spawn": "2.0.0"
},
"type": "npm-asset-library", "type": "npm-asset-library",
"extra": { "extra": {
"npm-asset-bugs": { "npm-asset-bugs": {
@ -1225,6 +1297,12 @@
"reference": null, "reference": null,
"shasum": "06f0335f16e353a695e7206bf50503cb523a6ee5" "shasum": "06f0335f16e353a695e7206bf50503cb523a6ee5"
}, },
"require-dev": {
"npm-asset/grunt": "~0.4.1",
"npm-asset/grunt-contrib-connect": "~0.5.0",
"npm-asset/grunt-contrib-jshint": "~0.7.1",
"npm-asset/grunt-contrib-uglify": "~0.2.7"
},
"type": "npm-asset-library", "type": "npm-asset-library",
"extra": { "extra": {
"npm-asset-bugs": { "npm-asset-bugs": {
@ -1933,6 +2011,54 @@
], ],
"time": "2015-06-14T21:17:01+00:00" "time": "2015-06-14T21:17:01+00:00"
}, },
{
"name": "hamcrest/hamcrest-php",
"version": "v2.0.0",
"source": {
"type": "git",
"url": "https://github.com/hamcrest/hamcrest-php.git",
"reference": "776503d3a8e85d4f9a1148614f95b7a608b046ad"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/776503d3a8e85d4f9a1148614f95b7a608b046ad",
"reference": "776503d3a8e85d4f9a1148614f95b7a608b046ad",
"shasum": ""
},
"require": {
"php": "^5.3|^7.0"
},
"replace": {
"cordoval/hamcrest-php": "*",
"davedevelopment/hamcrest-php": "*",
"kodova/hamcrest-php": "*"
},
"require-dev": {
"phpunit/php-file-iterator": "1.3.3",
"phpunit/phpunit": "~4.0",
"satooshi/php-coveralls": "^1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"hamcrest"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD"
],
"description": "This is the PHP port of Hamcrest Matchers",
"keywords": [
"test"
],
"time": "2016-01-20T08:20:44+00:00"
},
{ {
"name": "mikey179/vfsStream", "name": "mikey179/vfsStream",
"version": "v1.6.5", "version": "v1.6.5",
@ -1979,6 +2105,71 @@
"homepage": "http://vfs.bovigo.org/", "homepage": "http://vfs.bovigo.org/",
"time": "2017-08-01T08:02:14+00:00" "time": "2017-08-01T08:02:14+00:00"
}, },
{
"name": "mockery/mockery",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/mockery/mockery.git",
"reference": "100633629bf76d57430b86b7098cd6beb996a35a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mockery/mockery/zipball/100633629bf76d57430b86b7098cd6beb996a35a",
"reference": "100633629bf76d57430b86b7098cd6beb996a35a",
"shasum": ""
},
"require": {
"hamcrest/hamcrest-php": "~2.0",
"lib-pcre": ">=7.0",
"php": ">=5.6.0"
},
"require-dev": {
"phpunit/phpunit": "~5.7.10|~6.5|~7.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-0": {
"Mockery": "library/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Pádraic Brady",
"email": "padraic.brady@gmail.com",
"homepage": "http://blog.astrumfutura.com"
},
{
"name": "Dave Marshall",
"email": "dave.marshall@atstsolutions.co.uk",
"homepage": "http://davedevelopment.co.uk"
}
],
"description": "Mockery is a simple yet flexible PHP mock object framework",
"homepage": "https://github.com/mockery/mockery",
"keywords": [
"BDD",
"TDD",
"library",
"mock",
"mock objects",
"mockery",
"stub",
"test",
"test double",
"testing"
],
"time": "2018-10-02T21:52:37+00:00"
},
{ {
"name": "myclabs/deep-copy", "name": "myclabs/deep-copy",
"version": "1.7.0", "version": "1.7.0",
@ -2779,7 +2970,7 @@
} }
], ],
"description": "Provides the functionality to compare PHP values for equality", "description": "Provides the functionality to compare PHP values for equality",
"homepage": "http://www.github.com/sebastianbergmann/comparator", "homepage": "https://github.com/sebastianbergmann/comparator",
"keywords": [ "keywords": [
"comparator", "comparator",
"compare", "compare",
@ -2881,7 +3072,7 @@
} }
], ],
"description": "Provides functionality to handle HHVM/PHP environments", "description": "Provides functionality to handle HHVM/PHP environments",
"homepage": "http://www.github.com/sebastianbergmann/environment", "homepage": "https://github.com/sebastianbergmann/environment",
"keywords": [ "keywords": [
"Xdebug", "Xdebug",
"environment", "environment",
@ -2949,7 +3140,7 @@
} }
], ],
"description": "Provides the functionality to export PHP variables for visualization", "description": "Provides the functionality to export PHP variables for visualization",
"homepage": "http://www.github.com/sebastianbergmann/exporter", "homepage": "https://github.com/sebastianbergmann/exporter",
"keywords": [ "keywords": [
"export", "export",
"exporter" "exporter"
@ -3001,7 +3192,7 @@
} }
], ],
"description": "Snapshotting of global state", "description": "Snapshotting of global state",
"homepage": "http://www.github.com/sebastianbergmann/global-state", "homepage": "https://github.com/sebastianbergmann/global-state",
"keywords": [ "keywords": [
"global state" "global state"
], ],
@ -3103,7 +3294,7 @@
} }
], ],
"description": "Provides functionality to recursively process PHP variables", "description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context", "homepage": "https://github.com/sebastianbergmann/recursion-context",
"time": "2016-11-19T07:33:16+00:00" "time": "2016-11-19T07:33:16+00:00"
}, },
{ {

View file

@ -36,7 +36,7 @@ $a->backend = false;
require_once "include/dba.php"; require_once "include/dba.php";
// Missing DB connection: ERROR // Missing DB connection: ERROR
if (App\Mode::has(App\Mode::LOCALCONFIGPRESENT) && !App\Mode::has(App\Mode::DBAVAILABLE)) { if ($a->getMode()->has(App\Mode::LOCALCONFIGPRESENT) && !$a->getMode()->has(App\Mode::DBAVAILABLE)) {
System::httpExit(500, ['title' => 'Error 500 - Internal Server Error', 'description' => 'Apologies but the website is unavailable at the moment.']); System::httpExit(500, ['title' => 'Error 500 - Internal Server Error', 'description' => 'Apologies but the website is unavailable at the moment.']);
} }
@ -48,7 +48,7 @@ if ($a->isMaxProcessesReached() || $a->isMaxLoadReached()) {
System::httpExit(503, ['title' => 'Error 503 - Service Temporarily Unavailable', 'description' => 'System is currently overloaded. Please try again later.']); System::httpExit(503, ['title' => 'Error 503 - Service Temporarily Unavailable', 'description' => 'System is currently overloaded. Please try again later.']);
} }
if (!App\Mode::isInstall()) { if (!$a->getMode()->isInstall()) {
if (Config::get('system', 'force_ssl') && ($a->get_scheme() == "http") if (Config::get('system', 'force_ssl') && ($a->get_scheme() == "http")
&& (intval(Config::get('system', 'ssl_policy')) == SSL_POLICY_FULL) && (intval(Config::get('system', 'ssl_policy')) == SSL_POLICY_FULL)
&& (substr(System::baseUrl(), 0, 8) == "https://") && (substr(System::baseUrl(), 0, 8) == "https://")
@ -107,7 +107,7 @@ if (!empty($_SESSION['language']) && $_SESSION['language'] !== $lang) {
L10n::loadTranslationTable($lang); L10n::loadTranslationTable($lang);
} }
if (!empty($_GET['zrl']) && App\Mode::isNormal()) { if (!empty($_GET['zrl']) && $a->getMode()->isNormal()) {
$a->query_string = Profile::stripZrls($a->query_string); $a->query_string = Profile::stripZrls($a->query_string);
if (!local_user()) { if (!local_user()) {
// Only continue when the given profile link seems valid // Only continue when the given profile link seems valid
@ -130,7 +130,7 @@ if (!empty($_GET['zrl']) && App\Mode::isNormal()) {
} }
} }
if (!empty($_GET['owt']) && App\Mode::isNormal()) { if (!empty($_GET['owt']) && $a->getMode()->isNormal()) {
$token = $_GET['owt']; $token = $_GET['owt'];
$a->query_string = Profile::stripQueryParam($a->query_string, 'owt'); $a->query_string = Profile::stripQueryParam($a->query_string, 'owt');
Profile::openWebAuthInit($token); Profile::openWebAuthInit($token);
@ -165,9 +165,9 @@ $_SESSION['last_updated'] = defaults($_SESSION, 'last_updated', []);
// in install mode, any url loads install module // in install mode, any url loads install module
// but we need "view" module for stylesheet // but we need "view" module for stylesheet
if (App\Mode::isInstall() && $a->module != 'view') { if ($a->getMode()->isInstall() && $a->module != 'view') {
$a->module = 'install'; $a->module = 'install';
} elseif (!App\Mode::has(App\Mode::MAINTENANCEDISABLED) && $a->module != 'view') { } elseif (!$a->getMode()->has(App\Mode::MAINTENANCEDISABLED) && $a->module != 'view') {
$a->module = 'maintenance'; $a->module = 'maintenance';
} else { } else {
check_url($a); check_url($a);
@ -320,7 +320,7 @@ if (file_exists($theme_info_file)) {
/* initialise content region */ /* initialise content region */
if (App\Mode::isNormal()) { if ($a->getMode()->isNormal()) {
Addon::callHooks('page_content_top', $a->page['content']); Addon::callHooks('page_content_top', $a->page['content']);
} }

View file

@ -1,6 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<phpunit <phpunit
bootstrap="tests/bootstrap.php"
verbose="true"> verbose="true">
<testsuites> <testsuites>
<testsuite> <testsuite>

View file

@ -11,6 +11,7 @@ use Friendica\Core\L10n;
use Friendica\Core\PConfig; use Friendica\Core\PConfig;
use Friendica\Core\System; use Friendica\Core\System;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\Network\HTTPException\InternalServerErrorException;
require_once 'boot.php'; require_once 'boot.php';
require_once 'include/dba.php'; require_once 'include/dba.php';
@ -83,6 +84,11 @@ class App
public $stylesheets = []; public $stylesheets = [];
public $footerScripts = []; public $footerScripts = [];
/**
* @var App\Mode The Mode of the Application
*/
private $mode;
/** /**
* Register a stylesheet file path to be included in the <head> tag of every page. * Register a stylesheet file path to be included in the <head> tag of every page.
* Inclusion is done in App->initHead(). * Inclusion is done in App->initHead().
@ -193,6 +199,8 @@ class App
$this->callstack['rendering'] = []; $this->callstack['rendering'] = [];
$this->callstack['parser'] = []; $this->callstack['parser'] = [];
$this->mode = new App\Mode($basepath);
$this->reload(); $this->reload();
set_time_limit(0); set_time_limit(0);
@ -300,6 +308,22 @@ class App
$this->register_template_engine('Friendica\Render\FriendicaSmartyEngine'); $this->register_template_engine('Friendica\Render\FriendicaSmartyEngine');
} }
/**
* Returns the Mode of the Application
*
* @return App\Mode The Application Mode
*
* @throws InternalServerErrorException when the mode isn't created
*/
public function getMode()
{
if (empty($this->mode)) {
throw new InternalServerErrorException('Mode of the Application is not defined');
}
return $this->mode;
}
/** /**
* Reloads the whole app instance * Reloads the whole app instance
*/ */
@ -310,13 +334,13 @@ class App
$this->loadDatabase(); $this->loadDatabase();
App\Mode::determine($this->basepath); $this->getMode()->determine($this->basepath);
$this->determineUrlPath(); $this->determineUrlPath();
Config::load(); Config::load();
if (App\Mode::has(App\Mode::DBAVAILABLE)) { if ($this->getMode()->has(App\Mode::DBAVAILABLE)) {
Core\Addon::loadHooks(); Core\Addon::loadHooks();
$this->loadAddonConfig(); $this->loadAddonConfig();
@ -1402,7 +1426,7 @@ class App
*/ */
public function getCurrentTheme() public function getCurrentTheme()
{ {
if (App\Mode::isInstall()) { if ($this->getMode()->isInstall()) {
return ''; return '';
} }

View file

@ -20,9 +20,19 @@ class Mode
/*** /***
* @var int the mode of this Application * @var int the mode of this Application
* *
* Default is 0 (= not set)
*/ */
private static $mode = 0; private $mode;
/**
* @var string the basepath of the application
*/
private $basepath;
public function __construct($basepath = '')
{
$this->basepath = $basepath;
$this->mode = 0;
}
/** /**
* Sets the App mode * Sets the App mode
@ -34,34 +44,38 @@ class Mode
* @param string $basepath the Basepath of the Application * @param string $basepath the Basepath of the Application
* *
*/ */
public static function determine($basepath) public function determine($basepath = null)
{ {
self::$mode = 0; if (!empty($basepath)) {
$this->basepath = $basepath;
}
if (!file_exists($basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php') $this->mode = 0;
&& !file_exists($basepath . DIRECTORY_SEPARATOR . '.htconfig.php')) {
if (!file_exists($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php')
&& !file_exists($this->basepath . DIRECTORY_SEPARATOR . '.htconfig.php')) {
return; return;
} }
self::$mode |= Mode::LOCALCONFIGPRESENT; $this->mode |= Mode::LOCALCONFIGPRESENT;
if (!DBA::connected()) { if (!DBA::connected()) {
return; return;
} }
self::$mode |= Mode::DBAVAILABLE; $this->mode |= Mode::DBAVAILABLE;
if (DBA::fetchFirst("SHOW TABLES LIKE 'config'") === false) { if (DBA::fetchFirst("SHOW TABLES LIKE 'config'") === false) {
return; return;
} }
self::$mode |= Mode::DBCONFIGAVAILABLE; $this->mode |= Mode::DBCONFIGAVAILABLE;
if (Config::get('system', 'maintenance')) { if (Config::get('system', 'maintenance')) {
return; return;
} }
self::$mode |= Mode::MAINTENANCEDISABLED; $this->mode |= Mode::MAINTENANCEDISABLED;
} }
/** /**
@ -71,9 +85,13 @@ class Mode
* *
* @return bool returns true, if the mode is set * @return bool returns true, if the mode is set
*/ */
public static function has($mode) public function has($mode)
{ {
return self::$mode & $mode; echo "mode: " . $this->mode . " with " . $mode;
echo "value: " . ($this->mode & $mode);
return ($this->mode & $mode) > 0;
} }
@ -82,10 +100,10 @@ class Mode
* *
* @return bool * @return bool
*/ */
public static function isInstall() public function isInstall()
{ {
return !self::has(Mode::LOCALCONFIGPRESENT) || return !$this->has(Mode::LOCALCONFIGPRESENT) ||
!self::has(MODE::DBCONFIGAVAILABLE); !$this->has(MODE::DBCONFIGAVAILABLE);
} }
/** /**
@ -93,11 +111,11 @@ class Mode
* *
* @return bool * @return bool
*/ */
public static function isNormal() public function isNormal()
{ {
return self::has(Mode::LOCALCONFIGPRESENT) && return $this->has(Mode::LOCALCONFIGPRESENT) &&
self::has(Mode::DBAVAILABLE) && $this->has(Mode::DBAVAILABLE) &&
self::has(Mode::DBCONFIGAVAILABLE) && $this->has(Mode::DBCONFIGAVAILABLE) &&
self::has(Mode::MAINTENANCEDISABLED); $this->has(Mode::MAINTENANCEDISABLED);
} }
} }

View file

@ -31,7 +31,7 @@ class Config extends BaseObject
public static function init() public static function init()
{ {
// Database isn't ready or populated yet // Database isn't ready or populated yet
if (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
return; return;
} }
@ -55,7 +55,7 @@ class Config extends BaseObject
public static function load($family = "config") public static function load($family = "config")
{ {
// Database isn't ready or populated yet // Database isn't ready or populated yet
if (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
return; return;
} }
@ -88,7 +88,7 @@ class Config extends BaseObject
public static function get($family, $key, $default_value = null, $refresh = false) public static function get($family, $key, $default_value = null, $refresh = false)
{ {
// Database isn't ready or populated yet, fallback to file config // Database isn't ready or populated yet, fallback to file config
if (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
return self::getApp()->getConfigValue($family, $key, $default_value); return self::getApp()->getConfigValue($family, $key, $default_value);
} }
@ -116,7 +116,7 @@ class Config extends BaseObject
public static function set($family, $key, $value) public static function set($family, $key, $value)
{ {
// Database isn't ready or populated yet // Database isn't ready or populated yet
if (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
return false; return false;
} }
@ -141,7 +141,7 @@ class Config extends BaseObject
public static function delete($family, $key) public static function delete($family, $key)
{ {
// Database isn't ready or populated yet // Database isn't ready or populated yet
if (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
return false; return false;
} }

View file

@ -39,7 +39,7 @@ HELP;
protected function doExecute() protected function doExecute()
{ {
$a = get_app(); $a = \Friendica\BaseObject::getApp();
if ($this->getOption('v')) { if ($this->getOption('v')) {
$this->out('Class: ' . __CLASS__); $this->out('Class: ' . __CLASS__);
@ -56,7 +56,7 @@ HELP;
throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
} }
if (App\Mode::isInstall()) { if ($a->getMode()->isInstall()) {
throw new RuntimeException('Friendica isn\'t properly installed yet.'); throw new RuntimeException('Friendica isn\'t properly installed yet.');
} }

View file

@ -65,7 +65,7 @@ HELP;
$this->out('Options: ' . var_export($this->options, true)); $this->out('Options: ' . var_export($this->options, true));
} }
if (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { if ($a->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
$this->out('Database isn\'t ready or populated yet, database cache won\'t be available'); $this->out('Database isn\'t ready or populated yet, database cache won\'t be available');
} }

View file

@ -84,7 +84,7 @@ HELP;
throw new CommandArgsException('Too many arguments'); throw new CommandArgsException('Too many arguments');
} }
if (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { if (!$a->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
$this->out('Database isn\'t ready or populated yet, showing file config only'); $this->out('Database isn\'t ready or populated yet, showing file config only');
} }
@ -143,7 +143,7 @@ HELP;
if (count($this->args) == 0) { if (count($this->args) == 0) {
Core\Config::load(); Core\Config::load();
if (Core\Config::get('system', 'config_adapter') == 'jit' && App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { if (Core\Config::get('system', 'config_adapter') == 'jit' && $a->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
$this->out('Warning: The JIT (Just In Time) Config adapter doesn\'t support loading the entire configuration, showing file config only'); $this->out('Warning: The JIT (Just In Time) Config adapter doesn\'t support loading the entire configuration, showing file config only');
} }

View file

@ -56,7 +56,7 @@ HELP;
throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
} }
if (App\Mode::isInstall()) { if ($a->getMode()->isInstall()) {
throw new \RuntimeException('Database isn\'t ready or populated yet'); throw new \RuntimeException('Database isn\'t ready or populated yet');
} }

View file

@ -65,7 +65,7 @@ HELP;
throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
} }
if (App\Mode::isInstall()) { if ($a->getMode()->isInstall()) {
throw new RuntimeException('Database isn\'t ready or populated yet'); throw new RuntimeException('Database isn\'t ready or populated yet');
} }

View file

@ -47,7 +47,7 @@ HELP;
protected function doExecute() protected function doExecute()
{ {
$a = get_app(); $a = \Friendica\BaseObject::getApp();
if ($this->getOption('v')) { if ($this->getOption('v')) {
$this->out('Class: ' . __CLASS__); $this->out('Class: ' . __CLASS__);
@ -64,7 +64,7 @@ HELP;
throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
} }
if (App\Mode::isInstall()) { if ($a->getMode()->isInstall()) {
throw new \RuntimeException('Database isn\'t ready or populated yet'); throw new \RuntimeException('Database isn\'t ready or populated yet');
} }

View file

@ -57,7 +57,7 @@ HELP;
throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
} }
if (App\Mode::isInstall()) { if ($a->getMode()->isInstall()) {
throw new RuntimeException('Database isn\'t ready or populated yet'); throw new RuntimeException('Database isn\'t ready or populated yet');
} }

View file

@ -33,7 +33,7 @@ HELP;
protected function doExecute() protected function doExecute()
{ {
$a = get_app(); $a = \Friendica\BaseObject::getApp();
if ($this->getOption($this->helpOptions)) { if ($this->getOption($this->helpOptions)) {
$this->out($this->getHelp()); $this->out($this->getHelp());
@ -50,7 +50,7 @@ HELP;
return 0; return 0;
} }
if (App\Mode::isInstall()) { if ($a->getMode()->isInstall()) {
throw new \RuntimeException('Database isn\'t ready or populated yet'); throw new \RuntimeException('Database isn\'t ready or populated yet');
} }

View file

@ -29,12 +29,14 @@ class PConfig extends BaseObject
public static function init($uid) public static function init($uid)
{ {
$a = self::getApp();
// Database isn't ready or populated yet // Database isn't ready or populated yet
if (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { if (!$a->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
return; return;
} }
if (self::getApp()->getConfigValue('system', 'config_adapter') == 'preload') { if ($a->getConfigValue('system', 'config_adapter') == 'preload') {
self::$adapter = new Config\PreloadPConfigAdapter($uid); self::$adapter = new Config\PreloadPConfigAdapter($uid);
} else { } else {
self::$adapter = new Config\JITPConfigAdapter($uid); self::$adapter = new Config\JITPConfigAdapter($uid);
@ -55,7 +57,7 @@ class PConfig extends BaseObject
public static function load($uid, $family) public static function load($uid, $family)
{ {
// Database isn't ready or populated yet // Database isn't ready or populated yet
if (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
return; return;
} }
@ -84,7 +86,7 @@ class PConfig extends BaseObject
public static function get($uid, $family, $key, $default_value = null, $refresh = false) public static function get($uid, $family, $key, $default_value = null, $refresh = false)
{ {
// Database isn't ready or populated yet // Database isn't ready or populated yet
if (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
return; return;
} }
@ -113,7 +115,7 @@ class PConfig extends BaseObject
public static function set($uid, $family, $key, $value) public static function set($uid, $family, $key, $value)
{ {
// Database isn't ready or populated yet // Database isn't ready or populated yet
if (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
return false; return false;
} }
@ -139,7 +141,7 @@ class PConfig extends BaseObject
public static function delete($uid, $family, $key) public static function delete($uid, $family, $key)
{ {
// Database isn't ready or populated yet // Database isn't ready or populated yet
if (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
return false; return false;
} }

52
tests/Util/VFSTrait.php Normal file
View file

@ -0,0 +1,52 @@
<?php
namespace Friendica\Test\Util;
use org\bovigo\vfs\vfsStream;
use org\bovigo\vfs\vfsStreamDirectory;
trait VFSTrait
{
/**
* @var vfsStreamDirectory The Stream Directory
*/
protected $root;
protected function setUpVfsDir() {
// the used directories inside the App class
$structure = [
'config' => [],
'bin' => []
];
// create a virtual directory and copy all needed files and folders to it
$this->root = vfsStream::setup('friendica', null, $structure);
$this->setConfigFile('config.ini.php');
$this->setConfigFile('settings.ini.php');
$this->setConfigFile('local.ini.php');
$this->setConfigFile('dbstructure.json');
}
protected function setConfigFile($filename)
{
$file = dirname(__DIR__) . DIRECTORY_SEPARATOR .
'..' . DIRECTORY_SEPARATOR .
'config' . DIRECTORY_SEPARATOR .
$filename;
if (file_exists($file)) {
vfsStream::newFile($filename)
->at($this->root->getChild('config'))
->setContent(file_get_contents($file));
}
}
protected function delConfigFile($filename)
{
if ($this->root->hasChild('config/' . $filename)) {
$this->root->removeChild('config/' . $filename);
}
}
}

139
tests/src/App/ModeTest.php Normal file
View file

@ -0,0 +1,139 @@
<?php
namespace Friendica\Test\src\App;
use Friendica\App\Mode;
use Friendica\Test\Util\VFSTrait;
use PHPUnit\Framework\TestCase;
/**
* @runTestsInSeparateProcesses
* @preserveGlobalState disabled
*/
class ModeTest extends TestCase
{
use VFSTrait;
public function setUp()
{
parent::setUp(); // TODO: Change the autogenerated stub
$this->setUpVfsDir();
}
public function testItEmpty()
{
$mode = new Mode($this->root->url());
$this->assertTrue($mode->isInstall());
$this->assertFalse($mode->isNormal());
}
public function testWithoutConfig()
{
$mode = new Mode($this->root->url());
$this->assertTrue($this->root->hasChild('config/local.ini.php'));
$this->delConfigFile('local.ini.php');
$this->assertFalse($this->root->hasChild('config/local.ini.php'));
$mode->determine();
$this->assertTrue($mode->isInstall());
$this->assertFalse($mode->isNormal());
$this->assertFalse($mode->has(Mode::LOCALCONFIGPRESENT));
}
public function testWithoutDatabase()
{
$dba = \Mockery::mock('alias:Friendica\Database\DBA');
$dba
->shouldReceive('connected')
->andReturn(false);
$mode = new Mode($this->root->url());
$mode->determine();
$this->assertFalse($mode->isNormal());
$this->assertTrue($mode->isInstall());
$this->assertTrue($mode->has(Mode::LOCALCONFIGPRESENT));
$this->assertFalse($mode->has(Mode::DBAVAILABLE));
}
public function testWithoutDatabaseSetup()
{
$dba = \Mockery::mock('alias:Friendica\Database\DBA');
$dba
->shouldReceive('connected')
->andReturn(true);
$dba
->shouldReceive('fetchFirst')
->with('SHOW TABLES LIKE \'config\'')
->andReturn(false);
$mode = new Mode($this->root->url());
$mode->determine();
$this->assertFalse($mode->isNormal());
$this->assertTrue($mode->isInstall());
$this->assertTrue($mode->has(Mode::LOCALCONFIGPRESENT));
}
public function testWithMaintenanceMode()
{
$dba = \Mockery::mock('alias:Friendica\Database\DBA');
$dba
->shouldReceive('connected')
->andReturn(true);
$dba
->shouldReceive('fetchFirst')
->with('SHOW TABLES LIKE \'config\'')
->andReturn(true);
$conf = \Mockery::mock('alias:Friendica\Core\Config');
$conf
->shouldReceive('get')
->with('system', 'maintenance')
->andReturn(true);
$mode = new Mode($this->root->url());
$mode->determine();
$this->assertFalse($mode->isNormal());
$this->assertFalse($mode->isInstall());
$this->assertTrue($mode->has(Mode::DBCONFIGAVAILABLE));
$this->assertFalse($mode->has(Mode::MAINTENANCEDISABLED));
}
public function testNormalMode()
{
$dba = \Mockery::mock('alias:Friendica\Database\DBA');
$dba
->shouldReceive('connected')
->andReturn(true);
$dba
->shouldReceive('fetchFirst')
->with('SHOW TABLES LIKE \'config\'')
->andReturn(true);
$conf = \Mockery::mock('alias:Friendica\Core\Config');
$conf
->shouldReceive('get')
->with('system', 'maintenance')
->andReturn(false);
$mode = new Mode($this->root->url());
$mode->determine();
$this->assertTrue($mode->isNormal());
$this->assertFalse($mode->isInstall());
$this->assertTrue($mode->has(Mode::DBCONFIGAVAILABLE));
$this->assertTrue($mode->has(Mode::MAINTENANCEDISABLED));
}
}

View file

@ -6,12 +6,15 @@ use Friendica\App;
use Friendica\BaseObject; use Friendica\BaseObject;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\Test\Util\Intercept; use Friendica\Test\Util\Intercept;
use Friendica\Test\Util\VFSTrait;
use org\bovigo\vfs\vfsStream; use org\bovigo\vfs\vfsStream;
use org\bovigo\vfs\vfsStreamDirectory; use org\bovigo\vfs\vfsStreamDirectory;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
abstract class ConsoleTest extends TestCase abstract class ConsoleTest extends TestCase
{ {
use VFSTrait;
/** /**
* @var MultiUseConsole Extension of the basic Friendica Console for testing purpose * @var MultiUseConsole Extension of the basic Friendica Console for testing purpose
*/ */
@ -21,11 +24,6 @@ abstract class ConsoleTest extends TestCase
*/ */
protected $app; protected $app;
/**
* @var vfsStreamDirectory The Stream Directory
*/
protected $root;
protected $stdout; protected $stdout;
protected function setUp() protected function setUp()
@ -40,6 +38,11 @@ abstract class ConsoleTest extends TestCase
$this->setUpVfsDir(); $this->setUpVfsDir();
// fake console.php for setting an executable
vfsStream::newFile('console.php')
->at($this->root->getChild('bin'))
->setContent('<? php');
// Reusable App object // Reusable App object
$this->app = new App($this->root->url()); $this->app = new App($this->root->url());
BaseObject::setApp($this->app); BaseObject::setApp($this->app);
@ -67,41 +70,4 @@ abstract class ConsoleTest extends TestCase
protected function getExecutablePath() { protected function getExecutablePath() {
return $this->root->getChild('bin' . DIRECTORY_SEPARATOR . 'console.php')->url(); return $this->root->getChild('bin' . DIRECTORY_SEPARATOR . 'console.php')->url();
} }
private function setUpVfsDir() {
// the used directories inside the App class
$structure = [
'config' => [],
'bin' => []
];
// create a virtual directory and copy all needed files and folders to it
$this->root = vfsStream::setup('friendica', null, $structure);
$this->setConfigFile('config.ini.php');
$this->setConfigFile('settings.ini.php');
$this->setConfigFile('local.ini.php');
$this->setConfigFile('dbstructure.json');
// fake console.php for setting an executable
vfsStream::newFile('console.php')
->at($this->root->getChild('bin'))
->setContent('<? php');
}
private function setConfigFile($filename)
{
$file = dirname(__DIR__) . DIRECTORY_SEPARATOR .
'..' . DIRECTORY_SEPARATOR .
'..' . DIRECTORY_SEPARATOR .
'..' . DIRECTORY_SEPARATOR .
'config' . DIRECTORY_SEPARATOR .
$filename;
if (file_exists($file)) {
vfsStream::newFile($filename)
->at($this->root->getChild('config'))
->setContent(file_get_contents($file));
}
}
} }