fix tests

This commit is contained in:
Dennis Eichhorn 2023-09-24 17:57:27 +00:00
parent 093d526457
commit bd921e29f3
34 changed files with 1042 additions and 649 deletions

0
Helper/.bashrc → Config/.bashrc Executable file → Normal file
View File

769
Helper/ModuleTestTrait.php Normal file
View File

@ -0,0 +1,769 @@
<?php
/**
* Jingga
*
* PHP Version 8.1
*
* @package tests
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace Build\Helper;
use Model\CoreSettings;
use Modules\Admin\Models\ModuleStatusUpdateType;
use phpOMS\Account\AccountManager;
use phpOMS\Application\ApplicationAbstract;
use phpOMS\DataStorage\Database\Query\Builder;
use phpOMS\DataStorage\Database\Schema\Builder as SchemaBuilder;
use phpOMS\DataStorage\Session\HttpSession;
use phpOMS\Dispatcher\Dispatcher;
use phpOMS\Event\EventManager;
use phpOMS\Localization\L11nManager;
use phpOMS\Message\Http\HttpRequest;
use phpOMS\Message\Http\HttpResponse;
use phpOMS\Module\ModuleManager;
use phpOMS\Router\WebRouter;
use phpOMS\Uri\HttpUri;
use phpOMS\Utils\ArrayUtils;
use phpOMS\Validation\Base\Json;
use phpOMS\Version\Version;
trait ModuleTestTrait
{
protected ApplicationAbstract $app;
/**
* {@inheritdoc}
*/
protected function setUp() : void
{
if (self::NAME === 'TestModule') {
$this->markTestSkipped(
'The TestModule is not tested'
);
}
$this->app = new class() extends ApplicationAbstract
{
protected string $appName = 'Api';
};
$this->app->dbPool = $GLOBALS['dbpool'];
$this->app->router = new WebRouter();
$this->app->dispatcher = new Dispatcher($this->app);
$this->app->appSettings = new CoreSettings();
$this->app->moduleManager = new ModuleManager($this->app, __DIR__ . '/../../Modules/');
$this->app->sessionManager = new HttpSession(0);
$this->app->accountManager = new AccountManager($this->app->sessionManager);
$this->app->eventManager = new EventManager($this->app->dispatcher);
$this->app->l11nManager = new L11nManager();
}
/**
* @group admin
* @slowThreshold 5000
* @group module
*/
public function testModuleIntegration() : void
{
$iResponse = new HttpResponse();
$iRequest = new HttpRequest(new HttpUri(''));
$iRequest->header->account = 1;
$iRequest->setData('status', ModuleStatusUpdateType::INSTALL);
$iRequest->setData('module', self::NAME);
$this->app->moduleManager->get('Admin')->apiModuleStatusUpdate($iRequest, $iResponse);
$iRequest->setData('status', ModuleStatusUpdateType::DEACTIVATE, true);
$this->app->moduleManager->get('Admin')->apiModuleStatusUpdate($iRequest, $iResponse);
self::assertFalse($this->app->moduleManager->isActive(self::NAME), 'Module "' . self::NAME . '" is not active.');
$iRequest->setData('status', ModuleStatusUpdateType::ACTIVATE, true);
$this->app->moduleManager->get('Admin')->apiModuleStatusUpdate($iRequest, $iResponse);
self::assertTrue($this->app->moduleManager->isActive(self::NAME), 'Module "' . self::NAME . '" is not active.');
}
/**
* @group module
* @coversNothing
*/
public function testMembers() : void
{
$module = $this->app->moduleManager->get(self::NAME);
if ($module::ID === 0) {
return;
}
self::assertEquals(self::NAME, $module::NAME);
self::assertEquals(\realpath(__DIR__ . '/../../Modules/' . self::NAME), \realpath($module::PATH));
self::assertGreaterThanOrEqual(0, Version::compare($module::VERSION, '1.0.0'));
}
/**
* @group module
* @coversNothing
*/
public function testValidMapper() : void
{
$mappers = \glob(__DIR__ . '/../../Modules/' . self::NAME . '/Models/*Mapper.php');
foreach ($mappers as $mapper) {
$class = $this->getMapperFromPath($mapper);
$columns = $class::COLUMNS;
foreach ($columns as $cName => $column) {
if (!\in_array($column['type'], ['int', 'string', 'compress', 'DateTime', 'DateTimeImmutable', 'Json', 'Serializable', 'bool', 'float'])) {
self::assertTrue(false, 'Mapper "' . $class . '" column "' . $cName . '" has invalid type');
}
if ($cName !== ($column['name'] ?? false)) {
self::assertTrue(false);
}
}
}
self::assertTrue(true);
}
/**
* Get mapper from file path
*
* @param string $mapper Mapper path
*
* @return string
*/
private function getMapperFromPath(string $mapper) : string
{
$name = \substr($mapper, \strlen(__DIR__ . '/../../Modules/' . self::NAME . '/Models/'), -4);
return '\\Modules\\' . self::NAME . '\\Models\\' . $name;
}
/**
* @group module
* @coversNothing
*/
public function testMapperAgainstModel() : void
{
$mappers = \glob(__DIR__ . '/../../Modules/' . self::NAME . '/Models/*Mapper.php');
foreach ($mappers as $mapper) {
$class = $this->getMapperFromPath($mapper);
if ($class === '\Modules\Admin\Models\ModuleMapper'
|| !Autoloader::exists(\substr($class, 0, -6))
) {
continue;
}
$columns = $class::COLUMNS;
$ownsOne = $class::OWNS_ONE;
$classReflection = new \ReflectionClass(\substr($class, 0, -6));
$defaultProperties = $classReflection->getDefaultProperties();
$invalidAcessors = [];
foreach ($columns as $cName => $column) {
$isArray = false;
// testing existence of member variable in model
if (\stripos($column['internal'], '/') !== false) {
$column['internal'] = \explode('/', $column['internal'])[0];
$isArray = true;
}
if (!$classReflection->hasProperty($column['internal'])) {
self::assertTrue(false, 'Mapper "' . $class . '" column "' . $cName . '" has missing/invalid internal/member');
}
$property = $classReflection->getProperty($column['internal']) ?? null;
if ($property === null || (!$property->isPublic() && (!isset($column['private']) || !$column['private']))) {
$invalidAcessors[] = $column['internal'];
}
// testing correct mapper/model variable type definition
$property = $defaultProperties[$column['internal']] ?? null;
if (!($property === null /* not every value is allowed to be null but this just has to be correctly implemented in the mapper, no additional checks for this case! */
|| (\is_string($property) && ($column['type'] === 'string' || $column['type'] === 'compress'))
|| (\is_int($property) && $column['type'] === 'int')
|| (\is_array($property) && ($column['type'] === 'Json' || $column['type'] === 'Serializable' || $isArray))
|| (\is_bool($property) && $column['type'] === 'bool')
|| (\is_float($property) && $column['type'] === 'float')
|| ($property instanceof \DateTime && $column['type'] === 'DateTime')
|| ($property instanceof \DateTimeImmutable && $column['type'] === 'DateTimeImmutable')
|| (isset($ownsOne[$column['internal']]) && $column['type'] === 'int') // if it is in ownsOne it can be a different type because it is a reference!
)) {
self::assertTrue(false, 'Mapper "' . $class . '" column "' . $cName . '" has invalid type compared to model definition');
}
}
if (!empty($invalidAcessors)) {
self::assertTrue(false, 'Mapper "' . $class . '" must define private for "' . \implode(',', $invalidAcessors) . '" or make them public (recommended) in the model');
}
// test hasMany variable exists in model
$rel = $class::HAS_MANY;
foreach ($rel as $pName => $def) {
$property = $classReflection->getProperty($pName) ?? null;
if (!\array_key_exists($pName, $defaultProperties) && $property === null) {
self::assertTrue(false, 'Mapper "' . $class . '" property "' . $pName . '" doesn\'t exist in model');
}
}
}
self::assertTrue(true);
}
/**
* @group module
* @coversNothing
*/
public function testValidDbSchema() : void
{
$schemaPath = __DIR__ . '/../../Modules/' . self::NAME . '/Admin/Install/db.json';
if (!\is_file($schemaPath)) {
self::assertTrue(true);
return;
}
$db = \json_decode(\file_get_contents($schemaPath), true);
foreach ($db as $name => $table) {
if ($name !== ($table['name'] ?? false)) {
self::assertTrue(false, 'Schema "' . $schemaPath . '" name "' . $name . '" is invalid');
}
foreach ($table['fields'] as $cName => $column) {
if ($cName !== ($column['name'] ?? false)) {
self::assertTrue(false, 'Schema "' . $schemaPath . '" name "' . $cName . '" is invalid');
}
if (!(\stripos($column['type'] ?? '', 'TINYINT') === 0
|| \stripos($column['type'] ?? '', 'SMALLINT') === 0
|| \stripos($column['type'] ?? '', 'INT') === 0
|| \stripos($column['type'] ?? '', 'BIGINT') === 0
|| \stripos($column['type'] ?? '', 'VARCHAR') === 0
|| \stripos($column['type'] ?? '', 'VARBINARY') === 0
|| \stripos($column['type'] ?? '', 'TEXT') === 0
|| \stripos($column['type'] ?? '', 'LONGTEXT') === 0
|| \stripos($column['type'] ?? '', 'BLOB') === 0
|| \stripos($column['type'] ?? '', 'DATETIME') === 0
|| \stripos($column['type'] ?? '', 'DECIMAL') === 0
)) {
self::assertTrue(false, 'Schema "' . $schemaPath . '" type "' . ($column['type'] ?? '') . '" is a missing/invalid type');
}
}
}
$dbTemplate = \json_decode(\file_get_contents(__DIR__ . '/../../phpOMS/DataStorage/Database/tableDefinition.json'), true);
self::assertTrue(Json::validateTemplate($dbTemplate, $db), 'Invalid db template for ' . self::NAME);
}
/**
* @group module
* @coversNothing
*/
public function testDbSchemaAgainstDb() : void
{
$builder = new SchemaBuilder($this->app->dbPool->get());
$tables = $builder->selectTables()->execute()->fetchAll(\PDO::FETCH_COLUMN);
$schemaPath = __DIR__ . '/../../Modules/' . self::NAME . '/Admin/Install/db.json';
if (!\is_file($schemaPath)) {
self::assertTrue(true);
return;
}
$db = \json_decode(\file_get_contents($schemaPath), true);
foreach ($db as $name => $table) {
if (!\in_array($name, $tables)) {
self::assertTrue(false, 'Table ' . $name . ' doesn\'t exist in the database.');
}
$field = new SchemaBuilder($this->app->dbPool->get());
$fields = $field->selectFields($name)->execute()->fetchAll();
foreach ($table['fields'] as $cName => $column) {
if (!ArrayUtils::inArrayRecursive($cName, $fields)) {
self::assertTrue(false, 'Couldn\'t find "' . $cName . '" in "' . $name . '"');
}
}
}
self::assertTrue(true);
}
/**
* @group module
* @coversNothing
*/
public function testMapperAgainstDbSchema() : void
{
$schemaPath = __DIR__ . '/../../Modules/' . self::NAME . '/Admin/Install/db.json';
$mappers = \glob(__DIR__ . '/../../Modules/' . self::NAME . '/Models/*Mapper.php');
if (!\is_file($schemaPath)) {
self::assertTrue(true);
return;
}
$db = \json_decode(\file_get_contents($schemaPath), true);
foreach ($mappers as $mapper) {
$class = $this->getMapperFromPath($mapper);
if (\defined('self::MAPPER_TO_IGNORE') && \in_array(\ltrim($class, '\\'), self::MAPPER_TO_IGNORE)
|| empty($class::COLUMNS)
|| $class === '\Modules\Admin\Models\ModuleMapper'
) {
continue;
}
$table = $class::TABLE;
$columns = $class::COLUMNS;
foreach ($columns as $cName => $column) {
// testing existence of field name in schema
if (!isset($db[$table]['fields'][$cName])) {
self::assertTrue(false, 'Mapper "' . $class . '" column "' . $cName . '" doesn\'t match schema');
}
// testing schema/mapper same column data type
if (!(($column['type'] === 'string'
&& (\stripos($db[$table]['fields'][$cName]['type'], 'VARCHAR') === 0
|| \stripos($db[$table]['fields'][$cName]['type'], 'VARBINARY') === 0
|| \stripos($db[$table]['fields'][$cName]['type'], 'BLOB') === 0
|| \stripos($db[$table]['fields'][$cName]['type'], 'TEXT') === 0
|| \stripos($db[$table]['fields'][$cName]['type'], 'LONGTEXT') === 0))
|| ($column['type'] === 'int'
&& (\stripos($db[$table]['fields'][$cName]['type'], 'TINYINT') === 0
|| \stripos($db[$table]['fields'][$cName]['type'], 'SMALLINT') === 0
|| \stripos($db[$table]['fields'][$cName]['type'], 'INT') === 0
|| \stripos($db[$table]['fields'][$cName]['type'], 'BIGINT') === 0))
|| ($column['type'] === 'Json'
&& (\stripos($db[$table]['fields'][$cName]['type'], 'VARCHAR') === 0
|| \stripos($db[$table]['fields'][$cName]['type'], 'LONGTEXT') === 0
|| \stripos($db[$table]['fields'][$cName]['type'], 'TEXT') === 0))
|| ($column['type'] === 'compress'
&& (\stripos($db[$table]['fields'][$cName]['type'], 'BLOB') === 0))
|| ($column['type'] === 'Serializable')
|| ($column['type'] === 'bool' && \stripos($db[$table]['fields'][$cName]['type'], 'TINYINT') === 0)
|| ($column['type'] === 'float' && \stripos($db[$table]['fields'][$cName]['type'], 'DECIMAL') === 0)
|| ($column['type'] === 'DateTime' && \stripos($db[$table]['fields'][$cName]['type'], 'DATETIME') === 0)
|| ($column['type'] === 'DateTimeImmutable' && \stripos($db[$table]['fields'][$cName]['type'], 'DATETIME') === 0)
)) {
self::assertTrue(false, 'Schema "' . $schemaPath . '" type "' . ($column['type'] ?? '') . '" is incompatible with mapper "' . $class . '" definition "' . $db[$table]['fields'][$cName]['type'] . '" for field "' . $cName . '"');
}
}
// testing schema/mapper same primary key definition
$primary = $class::PRIMARYFIELD;
if (!($db[$table]['fields'][$primary]['primary'] ?? false)) {
self::assertTrue(false, 'Field "' . $primary . '" from mapper "' . $class . '" is not defined as primary key in table "' . $table . '"');
}
}
self::assertTrue(true);
}
/**
* @group module
* @coversNothing
*/
public function testJson() : void
{
$sampleInfo = \json_decode(\file_get_contents(__DIR__ . '/../TestModule/info.json'), true);
$infoTemplate = \json_decode(\file_get_contents(__DIR__ . '/../../phpOMS/Module/infoLayout.json'), true);
$module = $this->app->moduleManager->get(self::NAME);
if ($module::ID === 0) {
return;
}
// validate info.json
$info = \json_decode(\file_get_contents($module::PATH . '/info.json'), true);
self::assertTrue($this->infoJsonTest($info, $sampleInfo), 'Info assert failed for '. self::NAME);
self::assertTrue(Json::validateTemplate($infoTemplate, $info), 'Invalid info template for ' . self::NAME);
}
/**
* @group module
* @coversNothing
*/
public function testDependency() : void
{
$module = $this->app->moduleManager->get(self::NAME);
if ($module::ID === 0) {
return;
}
// validate dependency installation
$info = \json_decode(\file_get_contents($module::PATH . '/info.json'), true);
self::assertTrue($this->dependencyTest($info, $this->app->moduleManager->getInstalledModules(false)), 'Invalid dependency configuration in ' . self::NAME);
}
/**
* @group module
* @coversNothing
*/
public function testRoutes() : void
{
$this->app->moduleManager = new ModuleManager($this->app, __DIR__ . '/../../Modules/');
$totalBackendRoutes = \is_file(__DIR__ . '/../../Web/Backend/Routes.php') ? include __DIR__ . '/../../Web/Backend/Routes.php' : [];
$totalApiRoutes = \is_file(__DIR__ . '/../../Web/Api/Routes.php') ? include __DIR__ . '/../../Web/Api/Routes.php' : [];
$module = $this->app->moduleManager->get(self::NAME);
if ($module::ID === 0) {
return;
}
// test routes
if (\is_file($module::PATH . '/Admin/Routes/Web/Backend.php')) {
$moduleRoutes = include $module::PATH . '/Admin/Routes/Web/Backend.php';
self::assertEquals(1, $this->routesTest($moduleRoutes, $totalBackendRoutes), 'Backend route assert failed for '. self::NAME);
}
// test routes
if (\is_file($module::PATH . '/Admin/Routes/Web/Api.php')) {
$moduleRoutes = include $module::PATH . '/Admin/Routes/Web/Api.php';
self::assertEquals(1, $this->routesTest($moduleRoutes, $totalApiRoutes), 'Api route assert failed for '. self::NAME);
}
}
/**
* @group module
* @coversNothing
*/
public function testHooks() : void
{
$this->app->moduleManager = new ModuleManager($this->app, __DIR__ . '/../../Modules/');
$totalBackendHooks = \is_file(__DIR__ . '/../../Web/Backend/Hooks.php') ? include __DIR__ . '/../../Web/Backend/Hooks.php' : [];
$totalApiHooks = \is_file(__DIR__ . '/../../Web/Api/Hooks.php') ? include __DIR__ . '/../../Web/Api/Hooks.php' : [];
$module = $this->app->moduleManager->get(self::NAME);
if ($module::ID === 0) {
return;
}
// test hooks
if (\is_file($module::PATH . '/Admin/Hooks/Web/Backend.php')) {
$moduleHooks = include $module::PATH . '/Admin/Hooks/Web/Backend.php';
self::assertEquals(1, $this->hooksTest($moduleHooks, $totalBackendHooks), 'Backend hook assert failed for '. self::NAME);
}
// test hooks
if (\is_file($module::PATH . '/Admin/Hooks/Web/Api.php')) {
$moduleHooks = include $module::PATH . '/Admin/Hooks/Web/Api.php';
self::assertEquals(1, $this->hooksTest($moduleHooks, $totalApiHooks), 'Api hook assert failed for '. self::NAME);
}
}
/**
* @group final
* @group module
* @coversNothing
*/
public function testNavigation() : void
{
$module = $this->app->moduleManager->get(self::NAME);
if ($module::ID === 0
|| $this->app->moduleManager->get('Navigation')::ID === 0
|| !\is_file($module::PATH . '/Admin/Install/Navigation.install.json')
) {
return;
}
// test if navigation db entries match json files
self::assertTrue(
$this->navLinksTest(
$this->app->dbPool->get(),
\json_decode(
\file_get_contents($module::PATH . '/Admin/Install/Navigation.install.json'),
true
),
self::NAME
)
);
}
/**
* Test if all navigation links are in the database
*
* @param mixed $db Database connection
* @param array $links Navigation links from install file
* @param string $module Module name
*
* @return bool
*/
private function navLinksTest($db, array $links, string $module) : bool
{
$query = new Builder($db);
$query->select('nav_id')->from('nav')->where('nav_from', '=', $module);
$result = $query->execute()->fetchAll(\PDO::FETCH_COLUMN);
$it = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($links));
foreach ($it as $link) {
if (\is_array($link)
&& !\in_array($link['id'], $result)
) {
return false;
}
}
return true;
}
/**
* Test if all dependencies got installed
*
* @param array $info Module info array/file
* @param array $modules Installed modules
*
* @return bool
*/
private function dependencyTest(array $info, array $modules) : bool
{
foreach ($info['dependencies'] as $module => $version) {
if (!isset($modules[$module])) {
return false;
}
}
return true;
}
/**
* Test if route destinations exist (in the *Controller and global application route file)
*
* @param array $module Routes of the module from the respective app and module route file
* @param array $total Routing file of the respective application which contains all app routes
*
* @return int
*/
private function routesTest(array $module, array $total) : int
{
foreach ($module as $route => $dests) {
// test route existence after installation
if (!isset($total[$route])) {
return -1;
}
// test route class
foreach ($dests as $verb) {
$parts = \explode(':', $verb['dest']);
$path = __DIR__ . '/../../' . \ltrim(\strtr($parts[0], '\\', '/'), '/') . '.php';
if (!\is_file($path)) {
return -2;
}
// test route method
$content = \file_get_contents($path);
if (\stripos($content, 'function ' . $parts[\count($parts) - 1]) === false
&& \strpos($parts[\count($parts) - 1], 'Trait') === false
) {
return -3;
}
}
}
return 1;
}
/**
* Test if hook destinations exist (in the *Controller and global application hook file)
*
* @param array $module Hooks of the module from the respective app and module hook file
* @param array $total Routing file of the respective application which contains all app routes
*
* @return int
*/
private function hooksTest(array $module, array $total) : int
{
foreach ($module as $route => $dests) {
if (!isset($total[$route])) {
return -1;
}
// test route class
foreach ($dests['callback'] as $callback) {
$parts = \explode(':', $callback);
$path = __DIR__ . '/../../' . \ltrim(\strtr($parts[0], '\\', '/'), '/') . '.php';
if (!\is_file($path)) {
return -2;
}
// test route method
$content = \file_get_contents($path);
if (\stripos($content, 'function ' . $parts[\count($parts) - 1]) === false) {
return -3;
}
}
}
return 1;
}
/**
* Test if the module info file has the correct types
*
* @param array $module Module info file
* @param array $samle Sample info file (as basis for checking the data types)
*
* @return bool
*/
private function infoJsonTest(array $module, array $sample) : bool
{
try {
if (\gettype($module['name']['id']) === \gettype($sample['name']['id'])
&& \gettype($module['name']['internal']) === \gettype($sample['name']['internal'])
&& \gettype($module['name']['external']) === \gettype($sample['name']['external'])
&& \gettype($module['category']) === \gettype($sample['category'])
&& \gettype($module['version']) === \gettype($sample['version'])
&& \gettype($module['requirements']) === \gettype($sample['requirements'])
&& \gettype($module['creator']) === \gettype($sample['creator'])
&& \gettype($module['creator']['name']) === \gettype($sample['creator']['name'])
&& \gettype($module['description']) === \gettype($sample['description'])
&& \gettype($module['directory']) === \gettype($sample['directory'])
&& \gettype($module['dependencies']) === \gettype($sample['dependencies'])
&& \gettype($module['providing']) === \gettype($sample['providing'])
&& \gettype($module['load']) === \gettype($sample['load'])
) {
return true;
}
} catch (\Throwable $_) {
return false;
}
return false;
}
/**
* @group module
* @coversNothing
*/
public function testRequestLoads() : void
{
if (!\defined('self::URI_LOAD') || empty(self::URI_LOAD)) {
return;
}
$request = new HttpRequest(new HttpUri(self::URI_LOAD));
$request->createRequestHashs(2);
$loaded = $this->app->moduleManager->getUriLoad($request);
$found = false;
foreach ($loaded[4] as $module) {
if ($module['module_load_file'] === self::NAME) {
$found = true;
break;
}
}
self::assertTrue($found, 'Module ' . self::NAME . ' is not loaded at ' . self::URI_LOAD . '. The module info.json file ("load" section for type: 4 loads) and the routing files paths should match.');
self::assertGreaterThan(0, \count($this->app->moduleManager->getLanguageFiles($request)));
self::assertTrue(\in_array(self::NAME, $this->app->moduleManager->getRoutedModules($request)));
$this->app->moduleManager->initRequestModules($request);
self::assertTrue($this->app->moduleManager->isRunning(self::NAME));
}
/**
* @group module
* @coversNothing
*/
public function testLanguage() : void
{
$module = $this->app->moduleManager->get(self::NAME);
if ($module::ID === 0) {
return;
}
$required = ['en', 'de'];
if (!\is_dir($module::PATH . '/Theme')) {
return;
}
$themes = \scandir($module::PATH . '/Theme');
if ($themes === false) {
return;
}
foreach ($themes as $theme) {
if ($theme === '.' || $theme === '..' || !\is_dir($module::PATH . '/Theme/' . $theme . '/Lang')) {
continue;
}
$langKeys = [];
$langFiles = \scandir($module::PATH . '/Theme/' . $theme . '/Lang');
foreach ($langFiles as $file) {
if ($file === '.' || $file === '..' || \stripos($file, '.lang.') === false) {
continue;
}
$parts = \explode('.', $file);
$type = '';
$type = \strlen($parts[0]) === 2 ? '' : $parts[0];
if (!isset($langKeys[$type])) {
$langKeys[$type] = [
'required' => null,
'keys' => [],
];
}
// check if required lanugages files exist IFF any language file of a specific type exists
if ($langKeys[$type]['required'] === null) {
$langKeys[$type]['required'] = true;
$missingLanguages = [];
foreach ($required as $lang) {
if (!\in_array(($type !== '' ? $type . '.' : '') . $lang . '.lang.php', $langFiles)) {
$langKeys[$type]['required'] = false;
$missingLanguages[] = $lang;
}
}
if (!empty($missingLanguages)) {
self::assertTrue(false, 'The language files "' . \implode(', ', $missingLanguages) . '" are missing with type "' . $type . '".');
}
}
// compare key equality
// every key in the key list must be present in all other language files of the same type and vice versa
$langArray = include $module::PATH . '/Theme/' . $theme . '/Lang/' . $file;
$langArray = \reset($langArray);
$keys = \array_keys($langArray);
if (empty($langKeys[$type]['keys'])) {
$langKeys[$type]['keys'] = $keys;
} elseif (!empty($diff1 = \array_diff($langKeys[$type]['keys'], $keys))
|| !empty($diff2 = \array_diff($keys, $langKeys[$type]['keys']))) {
self::assertTrue(false, $file . ': The language keys "' . \implode(', ', \array_merge($diff1, $diff2)) . '" are different.');
}
}
}
self::assertTrue(true);
}
}

View File

@ -14,17 +14,17 @@ declare(strict_types=1);
// Find modules where the Module/tests/Admin/AdminTest.php is missing
$modules = \scandir(__DIR__ . '/../../Modules');
$modules = \scandir(__DIR__ . '/../../../Modules');
foreach ($modules as $module) {
if ($module === '..' || $module === '.'
|| !\is_dir(__DIR__ . '/../../Modules/' . $module)
|| !\is_file(__DIR__ . '/../../Modules/' . $module . '/info.json'))
|| !\is_dir(__DIR__ . '/../../../Modules/' . $module)
|| !\is_file(__DIR__ . '/../../../Modules/' . $module . '/info.json'))
{
continue;
}
if (!\is_file(__DIR__ . '/../../Modules/' . $module . '/tests/Admin/AdminTest.php')) {
if (!\is_file(__DIR__ . '/../../../Modules/' . $module . '/tests/Admin/AdminTest.php')) {
echo $module . "\n";
}
}

View File

@ -14,7 +14,7 @@ declare(strict_types=1);
// Create missing api functions
$modules = \scandir(__DIR__ . '/../../Modules');
$modules = \scandir(__DIR__ . '/../../../Modules');
$allowed = ['Organization'];
@ -241,22 +241,22 @@ function deleteFunction($module, $modelName)
foreach ($modules as $module) {
if ($module === '..' || $module === '.'
|| !\is_dir(__DIR__ . '/../../Modules/' . $module)
|| !\is_dir(__DIR__ . '/../../Modules/' . $module . '/Controller')
|| !\is_file(__DIR__ . '/../../Modules/' . $module . '/info.json')
|| !\is_dir(__DIR__ . '/../../../Modules/' . $module)
|| !\is_dir(__DIR__ . '/../../../Modules/' . $module . '/Controller')
|| !\is_file(__DIR__ . '/../../../Modules/' . $module . '/info.json')
|| (!empty($allowed) && !\in_array($module, $allowed))
) {
continue;
}
$controllers = \scandir(__DIR__ . '/../../Modules/' . $module . '/Controller');
$controllers = \scandir(__DIR__ . '/../../../Modules/' . $module . '/Controller');
foreach ($controllers as $controller) {
if (\stripos($controller, 'Api') === false) {
continue;
}
$content = \file_get_contents(__DIR__ . '/../../Modules/' . $module . '/Controller/' . $controller);
$content = \file_get_contents(__DIR__ . '/../../../Modules/' . $module . '/Controller/' . $controller);
$matches = [];
\preg_match_all('/(public function )(.*?)(\()/', $content, $matches);
@ -375,7 +375,7 @@ foreach ($modules as $module) {
echo "\nMissing functions \"" . $module . "\": \n";
$newContent = \rtrim($content, " }\n") . "\n }\n" . $newContent . "}\n";
\file_put_contents(__DIR__ . '/../../Modules/' . $module . '/Controller/' . $controller, $newContent);
\file_put_contents(__DIR__ . '/../../../Modules/' . $module . '/Controller/' . $controller, $newContent);
}
foreach ($missing as $m) {

View File

@ -14,18 +14,18 @@ declare(strict_types=1);
// Find null models with no null model test and creates the tests
$modules = \scandir(__DIR__ . '/../../Modules');
$modules = \scandir(__DIR__ . '/../../../Modules');
foreach ($modules as $module) {
if ($module === '..' || $module === '.'
|| !\is_dir(__DIR__ . '/../../Modules/' . $module)
|| !\is_dir(__DIR__ . '/../../Modules/' . $module . '/Models')
|| !\is_file(__DIR__ . '/../../Modules/' . $module . '/info.json'))
|| !\is_dir(__DIR__ . '/../../../Modules/' . $module)
|| !\is_dir(__DIR__ . '/../../../Modules/' . $module . '/Models')
|| !\is_file(__DIR__ . '/../../../Modules/' . $module . '/info.json'))
{
continue;
}
$models = \scandir(__DIR__ . '/../../Modules/' . $module . '/Models');
$models = \scandir(__DIR__ . '/../../../Modules/' . $module . '/Models');
foreach ($models as $model) {
if ($model === '..' || $model === '.'
@ -44,15 +44,15 @@ foreach ($modules as $module) {
throw new Exception('invalid substr');
}
if (!\is_file(__DIR__ . '/../../Modules/' . $module . '/tests/Models/Null' . $model . 'Test.php')) {
if (!\is_file(__DIR__ . '/../../../Modules/' . $module . '/tests/Models/Null' . $model . 'Test.php')) {
echo $module . ': Null' . $model . "\n";
if (!\is_dir(__DIR__ . '/../../Modules/' . $module . '/tests')) {
\mkdir(__DIR__ . '/../../Modules/' . $module . '/tests');
if (!\is_dir(__DIR__ . '/../../../Modules/' . $module . '/tests')) {
\mkdir(__DIR__ . '/../../../Modules/' . $module . '/tests');
}
if (!\is_dir(__DIR__ . '/../../Modules/' . $module . '/tests/Models')) {
\mkdir(__DIR__ . '/../../Modules/' . $module . '/tests/Models');
if (!\is_dir(__DIR__ . '/../../../Modules/' . $module . '/tests/Models')) {
\mkdir(__DIR__ . '/../../../Modules/' . $module . '/tests/Models');
}
$test = '<?php' . "\n"
@ -98,7 +98,7 @@ foreach ($modules as $module) {
. ' }' . "\n"
. '}' . "\n";
\file_put_contents(__DIR__ . '/../../Modules/' . $module . '/tests/Models/Null' . $model . 'Test.php', $test);
\file_put_contents(__DIR__ . '/../../../Modules/' . $module . '/tests/Models/Null' . $model . 'Test.php', $test);
}
}
}

View File

View File

@ -14,7 +14,7 @@ declare(strict_types=1);
// Find missing tests + test report bugs
$report = include __DIR__ . '/../../Build/Config/reportLang.php';
$report = include __DIR__ . '/../../../Build/Config/reportLang.php';
$noTestFile = [];
$noTestFunction = [];
@ -40,7 +40,7 @@ foreach ($report as $key => $line) {
$file = \reset($parts);
$function = \end($parts);
$file = __DIR__ . '/../../' . \strtr($file, '\\', '/') . '.php';
$file = __DIR__ . '/../../../' . \strtr($file, '\\', '/') . '.php';
if (!\is_file($file)) {
$noTestFile[] = $key;
@ -80,8 +80,8 @@ foreach ($invalidDescription as $function) {
}
$directories = [
__DIR__ . '/../../phpOMS/tests/**/*Test.php',
__DIR__ . '/../../Modules/**/tests/**/*Test.php'
__DIR__ . '/../../../phpOMS/tests/**/*Test.php',
__DIR__ . '/../../../Modules/**/tests/**/*Test.php'
];
foreach ($directories as $directory) {
@ -103,7 +103,7 @@ foreach ($directories as $directory) {
$end = \strpos($line, '(');
$function = \substr($line, 20, $end - 20);
$name = \substr(\realpath($file), \strlen(\realpath(__DIR__ . '/../../')) + 1, -4);
$name = \substr(\realpath($file), \strlen(\realpath(__DIR__ . '/../../../')) + 1, -4);
$name = \strtr($name, '/', '\\');
$reportKey = $name . ':' . $function;

View File

0
Helper/install.sh → Helper/Scripts/install.sh Executable file → Normal file
View File

View File

View File

View File

View File

@ -1,24 +0,0 @@
#!/bin/bash
mkdir -p Build/test
# php cs + phpstan + eslint file generation
./vendor/bin/phpcs --severity=1 ./ --standard="Build/Config/phpcs.xml" -s --report-junit=Build/test/junit_phpcs.xml
./vendor/bin/phpstan analyse -l 9 -c Build/Config/phpstan.neon --error-format=prettyJson ./ > Build/test/phpstan.json
npx eslint jsOMS/ -c Build/Config/.eslintrc.json -o Build/test/junit_eslint.xml -f junit
# Remove empty lines and lines with warnings which corrupt the json format
sed -i '/^$/d' Build/test/phpstan.json
sed -i '/^Warning: /d' Build/test/phpstan.json
# Create report
php ./Tools/TestReportGenerator/src/index.php \
-b /var/www/html/Karaka \
-l /var/www/html/Karaka/Build/Config/reportLang.php \
-c /var/www/html/Karaka/tests/coverage.xml \
-s /var/www/html/Karaka/Build/test/junit_phpcs.xml \
-sj /var/www/html/Karaka/Build/test/junit_eslint.xml \
-a /var/www/html/Karaka/Build/test/phpstan.json \
-u /var/www/html/Karaka/Build/test/junit_php.xml \
-d /var/www/html/Karaka/Build/test/ReportExternal \
--version 1.0.0

View File

@ -1,18 +0,0 @@
#!/bin/bash
DIRECTORY_TO_OBSERVE="cssOMS jsOMS"
function watcher {
inotifywait -r -e modify,move,create,delete \
--exclude ".*(\.css|\.php|\.json|\.md|\.sh|\.txt|\.log|\.min\.js)" \
${DIRECTORY_TO_OBSERVE}
}
BUILD_SCRIPT=build_frontend.sh
function build {
bash ${BUILD_SCRIPT}
}
build
while watcher; do
build
done

View File

@ -0,0 +1,10 @@
#!/bin/bash
. config.sh
echo "#################################################"
echo "Start static text inspection"
echo "#################################################"
grep -rlnP '(title|alt|aria\-label)(=\")((?!\<\?).)*(>)' --include \*.tpl.php Modules >> ${INSPECTION_PATH}/Modules/html/static_text.log
grep -rlnP '(\<td\>|\<th\>|\<caption\>|\<label.*?(\"|l)\>)[0-9a-zA-Z\.\?]+' --include \*.tpl.php Modules >> ${INSPECTION_PATH}/Modules/html/static_text.log

33
Inspection/Html/syntax.sh Normal file
View File

@ -0,0 +1,33 @@
#!/bin/bash
. config.sh
echo "#################################################"
echo "Start html syntax inspection"
echo "#################################################"
#
echo "Image alt missing:" > ${INSPECTION_PATH}/Modules/html_syntax.log
grep -rlnP '(\<img)((?!.*?alt=).)*(>)' --include \*.tpl.php Modules >> ${INSPECTION_PATH}/Modules/html_syntax.log
echo "Input type missing:" >> ${INSPECTION_PATH}/Modules/html_syntax.log
grep -rlnP '(<input)((?!.*?type=).)*(>)' --include \*.tpl.php Modules >> ${INSPECTION_PATH}/Modules/html_syntax.log
echo "Input name missing:" >> ${INSPECTION_PATH}/Modules/html_syntax.log
grep -rlnP '(<input|<select|<textarea)((?!.*?name=).)*(>)' --include \*.tpl.php Modules >> ${INSPECTION_PATH}/Modules/html_syntax.log
echo "Form id missing:" >> ${INSPECTION_PATH}/Modules/html_syntax.log
grep -rlnP '(\<form)((?!.*?(name|id)=).)*(>)' --include \*.tpl.php Modules >> ${INSPECTION_PATH}/Modules/html_syntax.log
#
echo "Image alt missing:" > ${INSPECTION_PATH}/Web/html_syntax.log
grep -rlnP '(\<img)((?!.*?alt=).)*(>)' --include \*.tpl.php Web >> ${INSPECTION_PATH}/Web/html_syntax.log
echo "Input type missing:" >> ${INSPECTION_PATH}/Web/html_syntax.log
grep -rlnP '(<input)((?!.*?type=).)*(>)' --include \*.tpl.php Web >> ${INSPECTION_PATH}/Web/html_syntax.log
echo "Input name missing:" >> ${INSPECTION_PATH}/Web/html_syntax.log
grep -rlnP '(<input|<select|<textarea)((?!.*?name=).)*(>)' --include \*.tpl.php Web >> ${INSPECTION_PATH}/Web/html_syntax.log
echo "Form id missing:" >> ${INSPECTION_PATH}/Web/html_syntax.log
grep -rlnP '(\<form)((?!.*?(name|id)=).)*(>)' --include \*.tpl.php Web >> ${INSPECTION_PATH}/Web/html_syntax.log

View File

@ -29,6 +29,6 @@ TAG[18]="<embed.*\/>"
for i in "${TAG[@]}"
do
grep -rln "$i" --include \*.tpl.php ${ROOT_PATH}/phpOMS >> ${INSPECTION_PATH}/Framework/html/tags.log
grep -rln "$i" --include \*.tpl.php ${ROOT_PATH}/Modules >> ${INSPECTION_PATH}/Modules/html/tags.log
grep -rln "$i" --include \*.tpl.php ${ROOT_PATH}/phpOMS >> ${INSPECTION_PATH}/Framework/html_tags.log
grep -rln "$i" --include \*.tpl.php ${ROOT_PATH}/Modules >> ${INSPECTION_PATH}/Modules/html_tags.log
done

View File

@ -7,12 +7,15 @@ echo "Start php linting inspection"
echo "#################################################"
find ${ROOT_PATH}/phpOMS -name "*.php" | xargs -L1 php -l > ${INSPECTION_PATH}/logs/temp.log
sed '/^No syntax.*/ d' < ${INSPECTION_PATH}/logs/temp.log > ${INSPECTION_PATH}/Framework/linting/linting_php.log
sed '/^No syntax.*/ d' < ${INSPECTION_PATH}/logs/temp.log > ${INSPECTION_PATH}/Framework/linting_php.log
find ${ROOT_PATH}/Web -name "*.php" | xargs -L1 php -l > ${INSPECTION_PATH}/logs/temp.log
sed '/^No syntax.*/ d' < ${INSPECTION_PATH}/logs/temp.log > ${INSPECTION_PATH}/Framework/linting/linting_php.log
sed '/^No syntax.*/ d' < ${INSPECTION_PATH}/logs/temp.log > ${INSPECTION_PATH}/Framework/linting_php.log
find ${ROOT_PATH}/Modules -name "*.php" | xargs -L1 php -l > ${INSPECTION_PATH}/logs/temp.log
sed '/^No syntax.*/ d' < ${INSPECTION_PATH}/logs/temp.log > ${INSPECTION_PATH}/Modules/linting/linting_php.log
sed '/^No syntax.*/ d' < ${INSPECTION_PATH}/logs/temp.log > ${INSPECTION_PATH}/Modules/linting_php.log
find ${ROOT_PATH}/Model -name "*.php" | xargs -L1 php -l > ${INSPECTION_PATH}/logs/temp.log
sed '/^No syntax.*/ d' < ${INSPECTION_PATH}/logs/temp.log > ${INSPECTION_PATH}/Model/linting_php.log
rm ${INSPECTION_PATH}/logs/temp.log

View File

@ -10,6 +10,7 @@ echo "#################################################"
php ${ROOT_PATH}/vendor/bin/phploc ${ROOT_PATH}/phpOMS/ > ${INSPECTION_PATH}/Framework/phploc.log
php ${ROOT_PATH}/vendor/bin/phploc ${ROOT_PATH}/Web/ > ${INSPECTION_PATH}/Web/phploc.log
php ${ROOT_PATH}/vendor/bin/phploc ${ROOT_PATH}/Modules/ > ${INSPECTION_PATH}/Modules/phploc.log
php ${ROOT_PATH}/vendor/bin/phploc ${ROOT_PATH}/Model/ > ${INSPECTION_PATH}/Model/phploc.log
#
php ${ROOT_PATH}/vendor/bin/phpmetrics --report-html=${INSPECTION_PATH}/Framework/metrics/metrics.html ${ROOT_PATH}/phpOMS/ >> ${INSPECTION_PATH}/Framework/build.log

View File

@ -7,11 +7,11 @@ echo "Start php style inspection"
echo "#################################################"
php ${ROOT_PATH}/vendor/bin/phpcs ${ROOT_PATH}/phpOMS --standard="${BUILD_PATH}/Config/phpcs.xml" -s --report-full=${INSPECTION_PATH}/Framework/phpcs.log --report-junit=${INSPECTION_PATH}/Framework/phpcs.xml
php ${ROOT_PATH}/vendor/bin/phpcs ${ROOT_PATH}/Web --standard="${BUILD_PATH}/Config/phpcs.xml" -s --report-full=${INSPECTION_PATH}/Modules/phpcs.log --report-junit=${INSPECTION_PATH}/Modules/phpcs.xml
php ${ROOT_PATH}/vendor/bin/phpcs ${ROOT_PATH}/Web --standard="${BUILD_PATH}/Config/phpcs.xml" -s --report-full=${INSPECTION_PATH}/Web/phpcs.log --report-junit=${INSPECTION_PATH}/Web/phpcs.xml
php ${ROOT_PATH}/vendor/bin/phpcs ${ROOT_PATH}/Modules --standard="${BUILD_PATH}/Config/phpcs.xml" -s --report-full=${INSPECTION_PATH}/Modules/phpcs.log --report-junit=${INSPECTION_PATH}/Modules/phpcs.xml
php ${ROOT_PATH}/vendor/bin/phpcs ${ROOT_PATH} --standard="${BUILD_PATH}/Config/phpcs.xml" -s --report-full=${INSPECTION_PATH}/Test/Php/phpcs.log --report-junit=${INSPECTION_PATH}/Test/Php/junit_phpcs.xml
php ${ROOT_PATH}/vendor/bin/phpcs ${ROOT_PATH}/Model --standard="${BUILD_PATH}/Config/phpcs.xml" -s --report-full=${INSPECTION_PATH}/Model/phpcs.log --report-junit=${INSPECTION_PATH}/Model/phpcs.xml
php ${ROOT_PATH}/vendor/bin/rector --dry-run --config ${BUILD_PATH}/Config/rector.php process ${ROOT_PATH}/phpOMS > ${INSPECTION_PATH}/Framework/rector.log
php ${ROOT_PATH}/vendor/bin/rector --dry-run --config ${BUILD_PATH}/Config/rector.php process ${ROOT_PATH}/Web > ${INSPECTION_PATH}/Modules/rector.log
php ${ROOT_PATH}/vendor/bin/rector --dry-run --config ${BUILD_PATH}/Config/rector.php process ${ROOT_PATH}/Modules > ${INSPECTION_PATH}/Modules/rector.log
php ${ROOT_PATH}/vendor/bin/rector --dry-run --config ${BUILD_PATH}/Config/rector.php process ${ROOT_PATH} > ${INSPECTION_PATH}/Test/Php/rector.log
php ${ROOT_PATH}/vendor/bin/rector --dry-run --config ${BUILD_PATH}/Config/rector.php process ${ROOT_PATH}/Web > ${INSPECTION_PATH}/Web/rector.log

View File

@ -17,7 +17,5 @@ php -d memory_limit=4G ${ROOT_PATH}/vendor/bin/phpstan analyse --autoload-file=$
php -d memory_limit=4G ${ROOT_PATH}/vendor/bin/phpstan analyse --autoload-file=${ROOT_PATH}/phpOMS/Autoloader.php -l 9 -c ${BUILD_PATH}/Config/phpstan.neon ${ROOT_PATH}/Model > ${INSPECTION_PATH}/Model/phpstan.log
php -d memory_limit=4G ${ROOT_PATH}/vendor/bin/phpstan analyse --autoload-file=${ROOT_PATH}/phpOMS/Autoloader.php -l 9 -c ${BUILD_PATH}/Config/phpstan.neon ${ROOT_PATH}/Web > ${INSPECTION_PATH}/Web/phpstan.log
php -d memory_limit=4G ${ROOT_PATH}/vendor/bin/phpstan analyse --autoload-file=${ROOT_PATH}/phpOMS/Autoloader.php -l 9 -c ${BUILD_PATH}/Config/phpstan.neon --error-format=json ${ROOT_PATH}/phpOMS > ${INSPECTION_PATH}/Test/Php/phpstan.json
# Cli debugging
# php -dzend_extension=xdebug.so -dxdebug.mode=debug -dxdebug.profiler_enable=1

View File

@ -51,6 +51,8 @@ echo "#################################################"
echo "Custom html inspection"
echo "#################################################"
. ${BUILD_PATH}/Inspection/Html/tags.sh
. ${BUILD_PATH}/Inspection/Html/syntax.sh
. ${BUILD_PATH}/Inspection/Html/static_text.sh
# Custom php inspections
echo "#################################################"
@ -64,6 +66,110 @@ echo "Custom js inspection"
echo "#################################################"
. ${BUILD_PATH}/Inspection/Js/security.sh
# Build internal test report
echo "#################################################"
echo "Internal test report"
echo "#################################################"
echo -e "Internal test report" > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "\n\n#################################################" > ${INSPECTION_PATH}/internal_test_report.txt
echo "Unit test" > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "#################################################\n\n" > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Test/Php/phpunit.log > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "\n\n#################################################" > ${INSPECTION_PATH}/internal_test_report.txt
echo "Static test" > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "#################################################\n\n" > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Framework/phpstan.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Modules/phpstan.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Model/phpstan.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Web/phpstan.log > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "\n\n#################################################" > ${INSPECTION_PATH}/internal_test_report.txt
echo "PHP style test" > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "#################################################\n\n" > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Framework/phpcs.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Modules/phpcs.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Model/phpcs.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Web/phpcs.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Framework/rector.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Modules/rector.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Model/rector.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Web/rector.log > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "\n\n#################################################" > ${INSPECTION_PATH}/internal_test_report.txt
echo "JS style test" > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "#################################################\n\n" > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Framework/eslint.txt > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "\n\n#################################################" > ${INSPECTION_PATH}/internal_test_report.txt
echo "Stats" > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "#################################################\n\n" > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Framework/phploc.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Modules/phploc.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Model/phploc.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Web/phploc.log > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "\n\n#################################################" > ${INSPECTION_PATH}/internal_test_report.txt
echo "PHP security tests" > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "#################################################\n\n" > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Framework/critical_php.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Modules/critical_php.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Model/critical_php.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Web/critical_php.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Framework/strict_missing_php.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Modules/strict_missing_php.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Model/strict_missing_php.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Web/strict_missing_php.log > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "\n\n#################################################" > ${INSPECTION_PATH}/internal_test_report.txt
echo "JS security tests" > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "#################################################\n\n" > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Framework/critical_js.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Modules/critical_js.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Web/critical_js.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Framework/strict_missing_js.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Modules/strict_missing_js.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Model/strict_missing_js.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Web/strict_missing_js.log > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "\n\n#################################################" > ${INSPECTION_PATH}/internal_test_report.txt
echo "Linting tests" > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "#################################################\n\n" > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Framework/linting_php.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Modules/linting_php.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Model/linting_php.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Web/linting_php.log > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "\n\n#################################################" > ${INSPECTION_PATH}/internal_test_report.txt
echo "DB queries" > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "#################################################\n\n" > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Sql/slow_queries.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Sql/locked_queries.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Sql/query_details.log > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "\n\n#################################################" > ${INSPECTION_PATH}/internal_test_report.txt
echo "Html tags" > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "#################################################\n\n" > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Framework/html_tags.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Modules/html_tags.log > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "\n\n#################################################" > ${INSPECTION_PATH}/internal_test_report.txt
echo "Html syntax" > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "#################################################\n\n" > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Modules/html_syntax.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Web/html_syntax.log > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "\n\n#################################################" > ${INSPECTION_PATH}/internal_test_report.txt
echo "Static text" > ${INSPECTION_PATH}/internal_test_report.txt
echo -e "#################################################\n\n" > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Modules/static_text.log > ${INSPECTION_PATH}/internal_test_report.txt
cat ${INSPECTION_PATH}/Web/static_text.log > ${INSPECTION_PATH}/internal_test_report.txt
# Build external test report
echo "#################################################"
echo "Test report"

View File

@ -1,146 +0,0 @@
<?php
namespace Build\Tools\AutoGpt;
use phpOMS\Message\Http\HttpRequest;
use phpOMS\Message\Http\Rest;
use phpOMS\Uri\HttpUri;
class GptHelper
{
private const ENDPOINT = 'https://api.openai.com/v1/chat/completions';
private const APIKEY = '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';
private const MODEL = 'gpt-3.5-turbo';
private const TEMPERATUR = 0.9;
private const MAX_TOKENS = 1700;
private const MAX_STRLEN = 1300;
private const LIMIT_REQUEST_PER_MINUTE = 3;
private const LIMIT_TOKENS_PER_MINUTE = 40000;
private static $lastRun = 0;
public static function defaultFileReader($in, $filename)
{
return \fgets($in);
}
public static function aiRequest(string $behavior, string $content) : string
{
if (\trim($content) === '') {
return '';
}
$requestBody = [
'model' => self::MODEL,
'max_tokens' => self::MAX_TOKENS,
'temperature' => self::TEMPERATUR,
'messages' => [
[
'role' => 'system',
'content' => $behavior,
],
[
'role' => 'user',
'content' => $content,
]
]
];
$request = new HttpRequest(new HttpUri(self::ENDPOINT));
$request->header->set('Authorization', 'Bearer ' . self::APIKEY);
$request->header->set('Content-Type', 'application/json');
$request->setMethod('POST');
$request->data = $requestBody;
do {
$time = \time();
if ($time - self::$lastRun <= (int) (61 / self::LIMIT_REQUEST_PER_MINUTE)) {
\sleep((int) (61 / self::LIMIT_REQUEST_PER_MINUTE - ($time - self::$lastRun)) + 1);
}
$response = Rest::request($request);
self::$lastRun = \time();
} while (\stripos($response->getBody(), '"code":502') !== false
|| \stripos($response->getBody(), '"code": 502') !== false
|| \stripos($response->getBody(), '503 Service') !== false
);
return $response->getBody();
}
public static function handleFile(string $inPath, string $outPath, string $behavior, Callable $fileReader, bool $bulk = true) : string
{
$response = '';
$in = \fopen($inPath, 'r');
$out = \fopen($outPath . ($inPath === $outPath ? '.out' : ''), 'w');
$lines = '';
while (($line = $fileReader($in, $inPath)) !== false) {
$line = \str_replace(' ', "\t", $line);
if (\strlen($line) > self::MAX_STRLEN) {
continue;
}
if (!$bulk) {
$lines = $line;
}
if (!$bulk || \strlen($lines) + \strlen($line) > self::MAX_STRLEN) {
$response = self::aiRequest($behavior, $lines);
if ($response === '' || $response === false) {
continue;
}
if(\stripos($outPath, '.php') !== false) {
$response = \str_replace('```', '', $response);
}
$json = \json_decode($response, true);
\fwrite($out, $json[5][0]['message']['content']);
\fwrite($out, "\n");
$lines = '';
}
if ($bulk) {
$lines .= $line . "\n";
}
}
if (\trim($lines) !== '' && \strlen($lines) <= self::MAX_STRLEN) {
$response = self::aiRequest($behavior, $lines);
if ($response !== '' && $response !== false) {
if(\stripos($outPath, '.php') !== false) {
$response = \str_replace('```', '', $response);
}
$json = \json_decode($response, true);
\fwrite($out, $json[5][0]['message']['content']);
\fwrite($out, "\n");
}
}
if ($outPath === 'php://memory') {
\rewind($out);
$response = \stream_get_contents($out);
}
if ($inPath === $outPath) {
if (\ftell($in) === 0 || \ftell($out) / \ftell($in) < 0.9) {
\unlink($outPath . '.out');
} else {
\unlink($outPath);
\rename($outPath . '.out', $outPath);
}
}
\fclose($in);
\fclose($out);
return $response;
}
}

View File

@ -1,60 +0,0 @@
<?php
use Build\Tools\AutoGpt\GptHelper;
include __DIR__ . '/../../../phpOMS/Autoloader.php';
// fix docblocks
$globs = [
__DIR__ . '/../../../phpOMS/**/*.php',
__DIR__ . '/../../../Modules/*/Models/*.php',
__DIR__ . '/../../../Modules/*/Controller/*.php',
];
$behaviour = <<<BEHAVIOUR
You are a developer, create a developer documentation for the following code using markdown.
BEHAVIOUR;
$fileReader = function ($in, $filename)
{
if (\filesize($filename) > 1300) {
return false;
}
$lines = '';
$isFirstLine = true;
while (($line = \fgets($in)) !== false) {
$isFirstLine = false;
$lines .= $line;
}
if ($isFirstLine && empty($lines)) {
return false;
}
return $lines;
};
$output = __DIR__ . '/../../../doc.md';
$md = \fopen($output, 'w');
foreach ($globs as $glob) {
$files = \glob($glob);
foreach ($files as $file) {
if (\stripos($file, 'Test.php')) {
continue;
}
$response = GptHelper::handleFile($file, 'php://memory', $behaviour, $fileReader);
if (\trim($response) !== '') {
\fwrite($md, $file . ":\n");
\fwrite($md, $response);
\fwrite($md, "\n\n");
}
}
}
\fclose($md);

View File

@ -1,67 +0,0 @@
<?php
use Build\Tools\AutoGpt\GptHelper;
include __DIR__ . '/../../../phpOMS/Autoloader.php';
// fix docblocks
$globs = [
__DIR__ . '/../../../phpOMS/**/*.php',
__DIR__ . '/../../../Modules/*/Models/*.php',
__DIR__ . '/../../../Modules/*/Controller/*.php',
];
$behaviour = <<<BEHAVIOUR
You are a developer and want to improve the docblocks of member variables and functions.
This is a docblock for class member variables:
/**
* Default delivery address.
*
* @var null|Address
* @since 1.0.0
*/
This is a docblock for functions:
/**
* Order contact elements
*
* @param ContactElement \$ele Element
* @param bool \$isRequired Is required
*
* @return int
*
* @since 1.0.0
*/
BEHAVIOUR;
$fileReader = function ($in, $filename)
{
if (\filesize($filename) > 1300) {
return false;
}
$lines = '';
$isFirstLine = true;
while (($line = \fgets($in)) !== false) {
$isFirstLine = false;
$lines .= $line;
}
if ($isFirstLine && empty($lines)) {
return false;
}
return $lines;
};
foreach ($globs as $glob) {
$files = \glob($glob);
foreach ($files as $file) {
if (\stripos($file, 'Test.php')) {
continue;
}
GptHelper::handleFile($file, $file, $behaviour, $fileReader);
}
}

View File

@ -1,76 +0,0 @@
<?php
use Build\Tools\AutoGpt\GptHelper;
include __DIR__ . '/../../../phpOMS/Autoloader.php';
// fix docblocks
$globs = [
__DIR__ . '/../../../phpOMS/**/*.php',
__DIR__ . '/../../../Modules/*/Models/*.php',
__DIR__ . '/../../../Modules/*/Controller/*.php',
];
$behaviour = <<<BEHAVIOUR
You are a developer.
BEHAVIOUR;
$fileReader = function ($in, $filename): bool|string
{
$lines = '';
$scopeStart = false;
$scopeCounter = 0;
$isFirstLine = true;
while (($line = \fgets($in)) !== false && ($isFirstLine || $scopeStart)) {
if (\stripos($line, ' function ') !== false) {
$scopeStart = true;
}
// Not in a function / not relevant
if (!$scopeStart) {
continue;
}
$isFirstLine = false;
$scopeChange = \substr_count($line, '{') - \substr_count($line, '}');
if ($scopeCounter !== 0 && $scopeCounter + $scopeChange === 0) {
$scopeStart = false;
}
$scopeCounter += $scopeChange;
$lines .= $line;
}
// No content or too short
if (($isFirstLine && empty(\trim($lines))) || \strlen($lines) < 550) {
return false;
}
return "Improve the performance and security of the following function without chaning the behaviour. Don't give me any explanations:\n" . $lines;
};
$output = __DIR__ . '/../../../improvements.log';
$log = \fopen($output, 'w');
foreach ($globs as $glob) {
$files = \glob($glob);
foreach ($files as $file) {
if (\stripos($file, 'Test.php')) {
continue;
}
$response = GptHelper::handleFile($file, 'php://memory', $behaviour, $fileReader, false);
if (\trim($response) !== '') {
\fwrite($log, $file . ":\n");
\fwrite($log, $response);
\fwrite($log, "\n\n");
}
}
}
\fclose($log);

View File

@ -1,108 +0,0 @@
<?php
use Build\Tools\AutoGpt\GptHelper;
include __DIR__ . '/../../../phpOMS/Autoloader.php';
// fix docblocks
$globs = [
__DIR__ . '/../../../phpOMS/**/*.php',
__DIR__ . '/../../../Modules/*/Models/*.php',
__DIR__ . '/../../../Modules/*/Controller/*.php',
];
$behaviour = <<<BEHAVIOUR
You are a developer.
BEHAVIOUR;
$fileReader = function ($in, $filename): bool|string
{
$lines = '';
$scopeStart = false;
$scopeCounter = 0;
$isFirstLine = true;
while (($line = \fgets($in)) !== false && ($isFirstLine || $scopeStart)) {
if (\stripos($line, ' public function ') !== false
|| \stripos($line, ' public static function ') !== false
) {
$testFile = \str_replace('.php', 'Test.php', $filename);
$testFile = \str_replace('/phpOMS/', '/phpOMS/tests/', $filename);
if (\stripos($testFile, '../Modules/') !== false) {
$subdirectory = "tests/";
$position = strrpos($testFile, "/../");
if ($position !== false) {
$position = \stripos($testFile, '/', $position + 4) + 1;
$position = \stripos($testFile, '/', $position) + 1;
$testFile = \substr_replace($testFile, $subdirectory, $position, 0);
}
}
if (\file_exists($testFile)) {
$scopeStart = true;
$testContent = \file_get_contents($testFile);
// Parse functio name
$pattern = '/\bfunction\b\s+(\w+)\s*\(/';
\preg_match($pattern, $line, $matches);
if (\stripos($testContent, $matches[1] ?? '~~~') !== false) {
// Test already exists
continue;
}
}
$scopeStart = true;
}
// Not in a function / not relevant
if (!$scopeStart) {
continue;
}
$isFirstLine = false;
$scopeChange = \substr_count($line, '{') - \substr_count($line, '}');
if ($scopeCounter !== 0 && $scopeCounter + $scopeChange === 0) {
$scopeStart = false;
}
$scopeCounter += $scopeChange;
$lines .= $line;
}
// No content or too short
if (($isFirstLine && empty(\trim($lines))) || \strlen($lines) < 550) {
return false;
}
return "Implement a PHPUnit test function for the following function:\n" . $lines;
};
$output = __DIR__ . '/../../../improvements.log';
$log = \fopen($output, 'w');
foreach ($globs as $glob) {
$files = \glob($glob);
foreach ($files as $file) {
if (\stripos($file, 'Test.php')) {
continue;
}
$response = GptHelper::handleFile($file, 'php://memory', $behaviour, $fileReader, false);
if (\trim($response) !== '') {
\fwrite($log, $file . ":\n");
\fwrite($log, $response);
\fwrite($log, "\n\n");
}
}
}
\fclose($log);

View File

@ -4,7 +4,90 @@
. config.sh
# Clean setup
. setup.sh
echo "#################################################"
echo "Remove old setup"
echo "#################################################"
# Previous cleanup
rm -r -f ${ROOT_PATH}
rm -r -f ${BASE_PATH}/phpOMS
rm -r -f ${BASE_PATH}/jsOMS
rm -r -f ${BASE_PATH}/cssOMS
rm -r -f ${TOOLS_PATH}
rm -r -f ${INSPECTION_PATH}
mkdir -p ${INSPECTION_PATH}
cd ${BASE_PATH}
echo "#################################################"
echo "Setup repositories"
echo "#################################################"
# Create git repositories
for i in "${GITHUB_URL[@]}"
do
git clone -b ${GIT_BRANCH} $i >/dev/null
done
cd ${ROOT_PATH}
git submodule update --init --recursive >/dev/null
git submodule foreach git checkout develop >/dev/null
echo "#################################################"
echo "Setup build output"
echo "#################################################"
# Creating directories for inspection
mkdir -p ${INSPECTION_PATH}/logs
mkdir -p ${INSPECTION_PATH}/Framework/logs
mkdir -p ${INSPECTION_PATH}/Framework/metrics
#mkdir -p ${INSPECTION_PATH}/Framework/pdepend
mkdir -p ${INSPECTION_PATH}/Framework/phpcs
mkdir -p ${INSPECTION_PATH}/Framework/phpcpd
mkdir -p ${INSPECTION_PATH}/Framework/linting
mkdir -p ${INSPECTION_PATH}/Framework/html
mkdir -p ${INSPECTION_PATH}/Modules/logs
mkdir -p ${INSPECTION_PATH}/Modules/metrics
#mkdir -p ${INSPECTION_PATH}/Modules/pdepend
mkdir -p ${INSPECTION_PATH}/Modules/phpcs
mkdir -p ${INSPECTION_PATH}/Modules/phpcpd
mkdir -p ${INSPECTION_PATH}/Modules/linting
mkdir -p ${INSPECTION_PATH}/Modules/html
mkdir -p ${INSPECTION_PATH}/Web/logs
mkdir -p ${INSPECTION_PATH}/Web/metrics
#mkdir -p ${INSPECTION_PATH}/Web/pdepend
mkdir -p ${INSPECTION_PATH}/Web/phpcs
mkdir -p ${INSPECTION_PATH}/Web/phpcpd
mkdir -p ${INSPECTION_PATH}/Web/linting
mkdir -p ${INSPECTION_PATH}/Web/html
mkdir -p ${INSPECTION_PATH}/Framework
mkdir -p ${INSPECTION_PATH}/Web
mkdir -p ${INSPECTION_PATH}/Model
mkdir -p ${INSPECTION_PATH}/Modules
mkdir -p ${INSPECTION_PATH}/Test/Php
mkdir -p ${INSPECTION_PATH}/Test/Js
mkdir -p ${INSPECTION_PATH}/Test/sitespeed
mkdir -p ${INSPECTION_PATH}/Sql
# Permission handling
chmod -R 777 ${ROOT_PATH}
# Setup tools for inspection
mkdir -p ${TOOLS_PATH}
echo "#################################################"
echo "Setup tools"
echo "#################################################"
cd ${ROOT_PATH}
composer install
npm install
cd ${BUILD_PATH}

View File

@ -10,7 +10,7 @@ RELEASE_PATH="/var/www/html/Release"
INSPECTION_PATH="/var/www/html/Inspection"
# Web
WEB_URL="http://karaka.de"
WEB_URL="http://jingga.app"
MAIL_ADDR=""
# Authentications
@ -19,7 +19,6 @@ DB_PASSWORD="root"
# Git variables
GITHUB_URL[0]="https://github.com/Karaka-Management/Karaka.git"
GITHUB_URL[1]="https://github.com/Karaka-Management/Website.git"
GIT_BRANCH="develop"

110
setup.sh
View File

@ -1,110 +0,0 @@
#!/bin/bash
. config.sh
echo "#################################################"
echo "Remove old setup"
echo "#################################################"
# Previous cleanup
rm -r -f ${ROOT_PATH}
rm -r -f ${BASE_PATH}/Website
rm -r -f ${BASE_PATH}/phpOMS
rm -r -f ${BASE_PATH}/jsOMS
rm -r -f ${BASE_PATH}/cssOMS
rm -r -f ${TOOLS_PATH}
rm -r -f ${INSPECTION_PATH}
mkdir -p ${INSPECTION_PATH}
cd ${BASE_PATH}
echo "#################################################"
echo "Setup repositories"
echo "#################################################"
# Create git repositories
for i in "${GITHUB_URL[@]}"
do
git clone -b ${GIT_BRANCH} $i >/dev/null
done
cd ${BASE_PATH}/Website
git submodule update --init --recursive >/dev/null
git submodule foreach git checkout develop >/dev/null
cd ${ROOT_PATH}
git submodule update --init --recursive >/dev/null
git submodule foreach git checkout develop >/dev/null
echo "#################################################"
echo "Setup hooks"
echo "#################################################"
# Setup hooks
cp ${ROOT_PATH}/Build/Hooks/default.sh ${ROOT_PATH}/.git/hooks/pre-commit
cp ${ROOT_PATH}/Build/Hooks/default.sh ${ROOT_PATH}/.git/modules/Build/hooks/pre-commit
cp ${ROOT_PATH}/Build/Hooks/default.sh ${ROOT_PATH}/.git/modules/phpOMS/hooks/pre-commit
cp ${ROOT_PATH}/Build/Hooks/default.sh ${ROOT_PATH}/.git/modules/jsOMS/hooks/pre-commit
cp ${ROOT_PATH}/Build/Hooks/default.sh ${ROOT_PATH}/.git/modules/cssOMS/hooks/pre-commit
chmod +x ${ROOT_PATH}/.git/hooks/pre-commit
chmod +x ${ROOT_PATH}/.git/modules/Build/hooks/pre-commit
chmod +x ${ROOT_PATH}/.git/modules/phpOMS/hooks/pre-commit
chmod +x ${ROOT_PATH}/.git/modules/jsOMS/hooks/pre-commit
chmod +x ${ROOT_PATH}/.git/modules/cssOMS/hooks/pre-commit
echo "#################################################"
echo "Setup build output"
echo "#################################################"
# Creating directories for inspection
mkdir -p ${INSPECTION_PATH}/logs
mkdir -p ${INSPECTION_PATH}/Framework/logs
mkdir -p ${INSPECTION_PATH}/Framework/metrics
#mkdir -p ${INSPECTION_PATH}/Framework/pdepend
mkdir -p ${INSPECTION_PATH}/Framework/phpcs
mkdir -p ${INSPECTION_PATH}/Framework/phpcpd
mkdir -p ${INSPECTION_PATH}/Framework/linting
mkdir -p ${INSPECTION_PATH}/Framework/html
mkdir -p ${INSPECTION_PATH}/Modules/logs
mkdir -p ${INSPECTION_PATH}/Modules/metrics
#mkdir -p ${INSPECTION_PATH}/Modules/pdepend
mkdir -p ${INSPECTION_PATH}/Modules/phpcs
mkdir -p ${INSPECTION_PATH}/Modules/phpcpd
mkdir -p ${INSPECTION_PATH}/Modules/linting
mkdir -p ${INSPECTION_PATH}/Modules/html
mkdir -p ${INSPECTION_PATH}/Web/logs
mkdir -p ${INSPECTION_PATH}/Web/metrics
#mkdir -p ${INSPECTION_PATH}/Web/pdepend
mkdir -p ${INSPECTION_PATH}/Web/phpcs
mkdir -p ${INSPECTION_PATH}/Web/phpcpd
mkdir -p ${INSPECTION_PATH}/Web/linting
mkdir -p ${INSPECTION_PATH}/Web/html
mkdir -p ${INSPECTION_PATH}/Framework
mkdir -p ${INSPECTION_PATH}/Web
mkdir -p ${INSPECTION_PATH}/Model
mkdir -p ${INSPECTION_PATH}/Modules
mkdir -p ${INSPECTION_PATH}/Test/Php
mkdir -p ${INSPECTION_PATH}/Test/Js
mkdir -p ${INSPECTION_PATH}/Test/sitespeed
mkdir -p ${INSPECTION_PATH}/Sql
# Permission handling
chmod -R 777 ${ROOT_PATH}
# Setup tools for inspection
mkdir -p ${TOOLS_PATH}
echo "#################################################"
echo "Setup tools"
echo "#################################################"
cd ${ROOT_PATH}
composer install
npm install