mirror of
https://github.com/Karaka-Management/Developer-Guide.git
synced 2026-01-16 14:38:41 +00:00
Merge changes
This commit is contained in:
parent
bc772a3b09
commit
a21e5e4512
|
|
@ -40,7 +40,6 @@
|
|||
* [Logging](services/logging.md)
|
||||
* [Localization](services/localization.md)
|
||||
* [Events](services/events.md)
|
||||
* [Action Manager](services/action_manager.md)
|
||||
* [Tasks](services/tasks.md)
|
||||
* [Queues](services/queues.md)
|
||||
* [Collection](services/collection.md)
|
||||
|
|
|
|||
|
|
@ -4,19 +4,7 @@ Requests can be either incoming requests such as http requests on the server sid
|
|||
|
||||
## Http Requests
|
||||
|
||||
Every request accepts a localization for localized responses, optionally the request URI can also be passed during initialization.
|
||||
|
||||
```
|
||||
$request = new Request(new Localization(), new Http());
|
||||
```
|
||||
|
||||
In case no URI is provided the request object initializes the current http request URI. The request object automatically removes all global request variables (e.g. $_GET) in case the current http request gets initialized. All the data will be available through:
|
||||
|
||||
```
|
||||
$request->getData('queryName');
|
||||
```
|
||||
|
||||
During the request initialization the UriBuilder will be set up as well.
|
||||
## Rest Requests
|
||||
|
||||
## Socket Requests
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ $this->router->add('foo/bar', function() {
|
|||
|
||||
## Route Parameters
|
||||
|
||||
coming soon
|
||||
<coming soon>
|
||||
|
||||
## Reference
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ In case the response header is set to JSON the view will automatically get parse
|
|||
|
||||
The base view class contains the request as well as the response objects hence it also contains the request/response localization. One of the most important methods is the `getText()` method. This private method allows for module and theme specific translations of defined language elements.
|
||||
|
||||
In the template you can simply use `$this->getHtml({TEXT_ID})` for localized text. All other localization elements can be accessed in a similar way e.g. `$this->l11n->getTemperature()`
|
||||
In the template you can simply use `$this->getText({TEXT_ID})` for localized text. All other localization elements can be accessed in a similar way e.g. `$this->l11n->getTemperature()`
|
||||
|
||||
## Templates
|
||||
|
||||
|
|
|
|||
|
|
@ -68,9 +68,9 @@ class Installer extends InstallerAbstract
|
|||
{
|
||||
public static function install(string $path, Pool $dbPool, InfoManager $info)
|
||||
{
|
||||
parent::install(__DIR__ . '/..', $dbPool, $info);
|
||||
parent::install($path, $dbPool, $info);
|
||||
|
||||
switch ($dbPool->get()->getType()) {
|
||||
switch ($dbPool->get('core')->getType()) {
|
||||
case DatabaseType::MYSQL:
|
||||
/* Your database setup goes here */
|
||||
break;
|
||||
|
|
|
|||
42
components/packages.md
Normal file
42
components/packages.md
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# Updates
|
||||
|
||||
The following directory structure shows how a update/patch package has to be structured.The purpose of the different files will be
|
||||
covered afterwards.
|
||||
|
||||
* {UniquePackageName.tar.gz}
|
||||
* signature.cert
|
||||
* Files
|
||||
* package.json
|
||||
* {other_files_or_subdirectories}
|
||||
|
||||
## Package Name
|
||||
|
||||
The unique package name is generated by the update server. Usually they are called:
|
||||
|
||||
* Modules: {Module Name}_{New Version}.tar.gz
|
||||
* Framework: {Framework Name}_{New Version}.tar.gz
|
||||
* Resources: {Resource Name}_{New Version}.tar.gz
|
||||
* Other Components: {Component Name}_{New Version}.tar.gz
|
||||
|
||||
By providing unique package names it's possible to define other updates as dependencies and prevent overwriting update packages.
|
||||
|
||||
## signature.cert
|
||||
|
||||
The `signature.cert` contains the signature for the package which will be used to certify the origin of the package.
|
||||
The public key provided with the application is used to decrypt the certificate and compare it to the actual package data.
|
||||
|
||||
## Files
|
||||
|
||||
In the files directory all files are stored.
|
||||
|
||||
### package.json
|
||||
|
||||
The `package.json` file contains information of the package.
|
||||
|
||||
```
|
||||
```
|
||||
|
||||
### Other
|
||||
|
||||
All other files are related to updates, patches, extensions and installation. These files can be simple assets that will be used or
|
||||
replaced in modules, classes in the framework that need to be updated and sql methods for updateing the database schema.
|
||||
BIN
cover.jpg
BIN
cover.jpg
Binary file not shown.
|
Before Width: | Height: | Size: 226 KiB After Width: | Height: | Size: 226 KiB |
|
|
@ -1,8 +1,8 @@
|
|||
# Cache
|
||||
## Cache
|
||||
|
||||
For caching the `CacheManager` provides access to the caching systems in place. Out of the box the CacheManager supports and automatically initializes either Redis or Memcached depending on the client configuration. The caching is not mandatory and therfor shouldn't be missuesed as in-memory database. It is not necessary to check if Redis or Memcached are available the CacheManager automatically handles the caching based on their existence.
|
||||
|
||||
## HTTP Cache
|
||||
### HTTP Cache
|
||||
|
||||
By default only stylesheets, javascript and layout images as well as module images are cached. Everything else is considered volatile and not cached. If a response specific response should be cached feel free to use the response header:
|
||||
|
||||
|
|
@ -18,12 +18,4 @@ Example usage:
|
|||
|
||||
```
|
||||
$head->addAsset(AssetType::JS, $request->getUri()->getBase() . 'Modules/Media/Controller.js?v=' . self::MODULE_VERSION);
|
||||
```
|
||||
|
||||
## FileCache
|
||||
|
||||
The `FileCache` provides file caching of data on a single file basis. Every cache object will be stored in a sperate file on the local file system. The file cache doesn't support remote caching. The `FileCache` serializes and unserializes the data/object by invoking the corresponding serialization and unserialization functions. Scalars and array will be handled by the cache internally.
|
||||
|
||||
### Storage
|
||||
|
||||
The cache key used will be used for the file storage. Invalid path characters used within the cache key will be replaced. The character `/` used inside the key string can be used to generate subdirectories in the cache directory.
|
||||
```
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
# Forecasting
|
||||
|
||||
## Exponential Smoothing
|
||||
|
||||
### Double Exponential Smoothing (Holt)
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# Tests
|
||||
|
||||
The applications goal is to achive 90% code coverage, which applies for the core application as well as all modules. All unit tests are located in a separate repository `Tests`. The frameworks code coverage has to be greater than 75% at all times.
|
||||
The applications goal is to achive 90% code coverage, which applies for the core application as well as all modules. All unit tests are located in a separate repository `Tests`.
|
||||
|
||||
## PHPUnit
|
||||
|
||||
|
|
@ -8,7 +8,7 @@ This application uses PHPUnit as unit testing framework. The PHPUnit directory i
|
|||
|
||||
### Modules
|
||||
|
||||
Every module needs to have a `Admin` directory containing a class called `AdminTest.php` which is used for testing the installation, activation, deactivation, uninstall and remove of the module. Tests that install, update, remove etc. a module need to have a group called `admin`. After running the `AdminTest.php` test the final state of the module should be installed and active, only this way it's possible to further test the controller and models. A code coverage of 75% is mandatory for every module for integration.
|
||||
Every module needs to have a `Admin` directory containing a class called `AdminTest.php` which is used for testing the installation, activation, deactivation, uninstall and remove of the module. Tests that install, update, remove etc. a module need to have a group called `admin`. After running the `AdminTest.php` test the final state of the module should be installed and active, only this way it's possible to further test the controller and models. A code coverage of 80% is mandatory for every module for integration.
|
||||
|
||||
## Jasmine
|
||||
|
||||
|
|
|
|||
|
|
@ -20,11 +20,11 @@ Example usage in a module handling a API request:
|
|||
|
||||
```
|
||||
if($request->getData('CSRF') === null) {
|
||||
$response->setStatusCode(RequestStatusCode::R_403);
|
||||
|
||||
$response->setStatusCode(RequestStatus::R_403);
|
||||
|
||||
/* optional */
|
||||
$response->set($request->__toString(), new Notify('Unknown referrer!', NotifyType::INFO));
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
|
@ -56,13 +56,13 @@ Scripts and frames must be provided by the own server or google. This is importa
|
|||
The default CSP looks like the following:
|
||||
|
||||
```
|
||||
$response->getHeader()->set('content-security-policy', 'script-src \'self\'; child-src \'self\'', true);
|
||||
$response->getHeader()->set('content-security-policy', 'script-src \'self\'; frame-src \'self\'', true);
|
||||
```
|
||||
|
||||
In order to whitelist inline javascript you can use the following logic. This however requires you to know the inline script beforehand `$script`. After setting the CSP header they automatically get locked so that further changes are not possible. This is a security measure in order to prevent any malicious adjustments.
|
||||
In order to whitelist inline javascript you can use the following logic. This however requires you to know the inline script beforehand `$script`. After setting the CSP header they automatically get locked so that further changes are not possible. This is a security measure in order to prevent any malicious adjustments.
|
||||
|
||||
```
|
||||
$response->getHeader()->set('content-security-policy', 'script-src \'self\' \'sha256-' . base64_encode(hash('sha256', $script, true)) . '\'; child-src \'self\'', true);
|
||||
$response->getHeader()->set('content-security-policy', 'script-src \'self\' \'sha256-' . base64_encode(hash('sha256', $script, true)) . '\'; frame-src \'self\'', true);
|
||||
```
|
||||
|
||||
### X-XSS-Protection
|
||||
|
|
@ -105,7 +105,7 @@ In some cases super globals will even be overwritten by values from these classe
|
|||
Input validation be implemented on multiple levels.
|
||||
|
||||
1. Regex validation in html/javascript by using the `pattern=""` attribute
|
||||
2. Type hints for method parameters and method returns wherever possible.
|
||||
2. Type hints for method parameters wherever possible.
|
||||
3. Making use of the `Validation` classes as much as possible
|
||||
4. **Don't** sanitize at all! Accept or dismiss.
|
||||
|
||||
|
|
@ -131,9 +131,9 @@ if(($pathNew = realpath($path)) === false || strpos($pathNew, self::MODULE_PATH)
|
|||
The example throws an exception if the path either doesn't exist or is trying to access a path that doesn't contain the path defined in `self::MODULE_PATH`. Another validation could be:
|
||||
|
||||
```
|
||||
if(($pathNew = realpath($path)) === false || !Validator::startsWith($pathNew, ROOT_PATH)) {
|
||||
if(($pathNew = realpath($path)) === false || !StringUtils::startsWith($pathNew, ROOT_PATH)) {
|
||||
throw new PathException($path);
|
||||
}
|
||||
```
|
||||
|
||||
This example now is not only checking if the path exists and if it contains a path element, it also makes sure that the path is inside the application root path.
|
||||
This example now is not only checking if the path exists and if it contains a path element, it also makes sure that the path is inside the application root path. You could as easily replace `ROOT_PATH` with `self::MODULE_PATH` and this validation would make sure `$path` only directs within a module.
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
# Action Manager
|
||||
|
||||
The action manager is only available for the frontend as its purpose is to execute/trigger events based on UI events. The action manager allows to define procedures for UI events without writing any inline JavaScript and reducing the necessary JavaScript code in general thanks to this modular approach.
|
||||
|
||||
## Binding Action Events
|
||||
|
||||
In order to perform actions on UI events it is necessary to define listeners for elements that need to be observed. Usually these elements are input and button elements. The following action has one `click-listener` executing the defined actions if this listener is triggered.
|
||||
|
||||
```
|
||||
<button data-action='[
|
||||
{
|
||||
"listener": click, "action": [...]
|
||||
}
|
||||
]'>
|
||||
```
|
||||
|
||||
Now we have to define the actions that should be executed when a click-event is performed.
|
||||
|
||||
```
|
||||
<button data-action='[
|
||||
{
|
||||
"listener": "click", "action": [
|
||||
{"key": 1, "type": "dom.popup", "tpl": "some-tpl", "aniIn": "fadeIn"},
|
||||
{"key": 2, "type": "message.request", "uri": "http://api.uri.com/?para=123", , "method": "GET", "request_type": "json"},
|
||||
{"key": 3, "type": "dom.table.append", "id": "some-tpl", "aniIn": "fadeIn", "data": [], "bindings": {"id": "id", "name": "name/0"}, "position": -1}
|
||||
]
|
||||
}
|
||||
]'>
|
||||
```
|
||||
|
||||
Actions can be executed synchronously or asynchronously depending on the actions implementation. Every action needs a `key` which has to be unique locally for this listner. Also every action needs a type; the type is used to identify which code to execute if the action is triggered. The framework comes with a set of pre-defined actions that can be used. All other object properties depend on the action.
|
||||
|
||||
In the example above, if the button is clicked it will look for a template with the id `some-tpl` and insert it into the DOM with a fade-in animation effect. Afterwards a GET request is performed to the API. The resultset of the API is then appended to a table in the previously opened popup. The binding in this example are used to map the API resultset to the table columns.
|
||||
|
||||
The API request URI doesn't have to be static but could be dynamic by using the URI factory which would allow to fetch values from other input fields as parameter value etc.
|
||||
|
||||
### Child Elements
|
||||
|
||||
In some situations it is required to define listeners and actions for all child elements. Writing listeners and action for every list element for example is tedious and confusing. For this purpose the parent element can specify a selector for a listener.
|
||||
|
||||
```
|
||||
<ul id="click-list" data-action='[
|
||||
{
|
||||
"listener": "...", "selector": "#click-list li", "action": [...]
|
||||
}
|
||||
]'>
|
||||
<li>...
|
||||
<li>...
|
||||
</ul>
|
||||
```
|
||||
|
||||
This registers the same listener to all `<li>` elements. Another advantag is that in case a new `<li>` element gets added it will automatically also receive this listener.
|
||||
|
||||
## Defining Actions
|
||||
|
||||
### Definition
|
||||
|
||||
A action event skeleton looks as follows:
|
||||
|
||||
```
|
||||
const uniqueFunctionName = function(action, callback, data)
|
||||
{
|
||||
"use strict";
|
||||
|
||||
// some code here
|
||||
|
||||
callback(newData);
|
||||
};
|
||||
```
|
||||
|
||||
The action parameter contains all the action configuration values, the callback is the next action event that should be triggered afterwards and the data parameter is either data that is passed from a previous action event or data you would like to pass to the next action event.
|
||||
|
||||
### Binding
|
||||
|
||||
A action event can be registered simply by adding it to the action manager:
|
||||
|
||||
```
|
||||
this.uiManager.getActionManager().add('some.new.action', uniqueFunctionName);
|
||||
```
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
# Charting
|
||||
|
||||
## Line Chart
|
||||
|
||||
## Area Chart
|
||||
|
||||
### Stacked
|
||||
|
||||
## Bar Chart
|
||||
|
||||
### Column
|
||||
|
||||
### Stacked
|
||||
|
||||
## Pie Chart
|
||||
|
||||
## Donut Chart
|
||||
|
||||
## Radar Chart
|
||||
|
||||
## Scatter Plot
|
||||
|
||||
## Box Plot
|
||||
|
||||
## Pyramid Chart
|
||||
|
||||
## Bubble Chart
|
||||
|
||||
## High Low Chart
|
||||
|
||||
## Candlestick Chart
|
||||
|
||||
## Gantt Chart
|
||||
|
||||
## Waterfall
|
||||
|
||||
## Tree
|
||||
|
||||
|
|
@ -7,13 +7,13 @@ Events are available in the frontend and the backend. Both implementations provi
|
|||
Every event requires a unique trigger key as well as a `\Closure` which should be called once the event is triggered.
|
||||
|
||||
```
|
||||
$this->eventManager->attach('eventId', function($data) { echo 'Hello World'; });
|
||||
$this->eventManager->attach('eventId', function() { echo 'Hello World'; });
|
||||
```
|
||||
|
||||
If an event should only be able to be triggered once another boolean parameter has to be edded to the `attach()` function call.
|
||||
If a event should only be able to be triggered once another boolean parameter has to be edded to the `attach()` function call.
|
||||
|
||||
```
|
||||
$this->eventManager->attach('eventId', function($data) { echo 'Hello World'; }, true);
|
||||
$this->eventManager->attach('eventId', function() { echo 'Hello World'; }, true);
|
||||
```
|
||||
|
||||
Now the event will be removed from the event manager once executed.
|
||||
|
|
@ -28,23 +28,20 @@ $this->eventManager->trigger('eventId');
|
|||
|
||||
## Multi Condition Events
|
||||
|
||||
In some cases it is required that multiple conditions are met before an event is supposed to be triggered. This can be achived by registering these conditions through the `addGroup()` function.
|
||||
In some cases it is required that multiple conditions are met before an event is supposed to be triggered. This can be achived by registering these conditions through the `addGroup()` function.
|
||||
|
||||
```
|
||||
$this->eventManager->addGroup('eventId', 'conditionName');
|
||||
$this->eventManager->addGroup('eventId', 'conditionName2');
|
||||
```
|
||||
|
||||
Now the event will only be triggered once every registered condition was triggered. If requried it's also possible to pass data to the event closure.
|
||||
Now the event will only be triggered once every registered condition was triggered.
|
||||
|
||||
```
|
||||
$data = [1, 2, new Object()];
|
||||
$this->eventManager->trigger('eventId', 'conditionName', $data); // No output
|
||||
$this->eventManager->trigger('eventId', 'conditionName2', $data); // Hello World
|
||||
$this->eventManager->trigger('eventId', 'conditionName'); // No output
|
||||
$this->eventManager->trigger('eventId', 'conditionName2'); // Hello World
|
||||
$this->eventManager->trigger('eventId'); // Hello World
|
||||
$this->eventManager->trigger('eventId', 'conditionName'); // Hello World
|
||||
```
|
||||
|
||||
The order in which these conditions are triggered doesn't mapper. A multi condition event SHOULD be atteched with the optional boolean parameter `true`. These events can only be executed once and will be removed afterwards. In case the optional boolean parameter was not set to `true` the event will remain in the event manager and will be triggered whenever `trigger('eventId')` is called.
|
||||
|
||||
Another optional boolean parameter can be added at the end if the event should stay active in the event manager but all trigger conditions should be reset after executed once.
|
||||
The order in which these conditions are triggered doesn't mapper. A multi condition event SHOULD be atteched with the optional boolean parameter `true`. These events can only be executed once and will be removed afterwards. In case the optional boolean parameter was not set to `true` the event will remain in the event manager and will be triggered whenever `trigger('eventId')` is called.
|
||||
|
|
@ -20,9 +20,9 @@ The file system provides a simple way to handle operations on the file system. S
|
|||
|
||||
## Custom Implementations
|
||||
|
||||
Custom implementations can be created by extending the StorageAbstract. These implementations must get registered in the file system and can be used afterwards as the pre-defined implementations.
|
||||
Custom implementations can be created by implementing the FileSystemInterface. These implementations must get registered in the file system and can be used afterwards as the pre-defined implementations.
|
||||
|
||||
```
|
||||
Storage::register('custom1', '\implementation\namespace');
|
||||
Storage::env('custom1')->list();
|
||||
FileSystem::register('custom1', '\implementation\namespace');
|
||||
FileSystem::env('custom1')->list();
|
||||
```
|
||||
|
|
@ -7,13 +7,13 @@ Most of the localization is stored inside the localization object which is part
|
|||
Language specific text can be used through the `LocalizationManager`, either by directly calling the `getText()` function of the localization manager
|
||||
|
||||
```
|
||||
$this->l11nManager->getHtml({LANGUAGE}, {MODULE}, {THEME}, {TEXT})
|
||||
$this->l11nManager->getText({LANGUAGE}, {MODULE}, {THEME}, {TEXT})
|
||||
```
|
||||
|
||||
or indirectly by calling the `getText()` in the view context.
|
||||
|
||||
```
|
||||
$this->getHtml({TEXT})
|
||||
$this->getText({TEXT})
|
||||
```
|
||||
|
||||
The language that should be used for a response should always be depending on the requested language and therefore never be hard coded.
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
# Service Worker
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
# Configuration
|
||||
|
||||
## IDE
|
||||
|
||||
### PHPStorm
|
||||
|
||||
For uniform code formatting and guidelines import the PHPStorm configuration located in the `Build` repository. The configuration includes the code formatting standards as well as code inspection standards used for PHP, JavaScript, CSS and HTML. Due to the limitations of the IDE not all guidelines can be implemented but provide a good start for further inspections.
|
||||
|
||||
## Build
|
||||
|
||||
### phpOMS
|
||||
|
||||
### cssOMS
|
||||
|
||||
### jsOMS
|
||||
|
||||
### Modules
|
||||
|
|
@ -1,2 +1 @@
|
|||
# Dev Environment
|
||||
|
||||
# Dev Environment
|
||||
|
|
@ -12,7 +12,7 @@ A file documentation MUST be implemented in the following form:
|
|||
/**
|
||||
* File description
|
||||
*
|
||||
* PHP Version 7.1
|
||||
* PHP Version 7.0
|
||||
*
|
||||
* @category Category name
|
||||
* @package Package name
|
||||
|
|
@ -69,7 +69,7 @@ A function/method documentation MUST be implemented in the following form:
|
|||
* @param variable_type $param1Name Parameter description
|
||||
* @param variable_type $param2Name Parameter description
|
||||
*
|
||||
* @return return_type Return description
|
||||
* @return return_type
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @author Your Author 2 <your.second@email.com>
|
||||
|
|
@ -113,7 +113,7 @@ The scss documentation is based on SassDoc, therefore only valid SassDoc comment
|
|||
// Optional example or more detailed description.
|
||||
//
|
||||
// @since 1.0.0
|
||||
// @author Your Author <your.second@email.com>
|
||||
// @author Your Author 2 <your.second@email.com>
|
||||
////
|
||||
```
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user