README
This commit is contained in:
parent
4ba1809871
commit
72e6b145d6
204
README.md
204
README.md
@ -11,9 +11,207 @@ Web-Base is a php framework which provides basic web functionalities and a moder
|
|||||||
- REST API
|
- REST API
|
||||||
- Account management
|
- Account management
|
||||||
- Supporting MySQL + PostgreSQL
|
- Supporting MySQL + PostgreSQL
|
||||||
- New: Page Routing
|
- Dynamic Page Routing
|
||||||
- New: Admin Dashboard
|
- Admin Dashboard
|
||||||
- New: Account & User functions
|
- Account & User functions
|
||||||
|
- File Sharing Dashboard
|
||||||
|
|
||||||
### Upcoming:
|
### Upcoming:
|
||||||
I actually don't know what i want to implement here. There are quite to many CMS out there with alot of vulnerabilities. There also exist some frameworks already. This project is meant to provide a stable project base to implement what ever a developer wants to: Dynamic Homepages, Webshops, ..
|
I actually don't know what i want to implement here. There are quite to many CMS out there with alot of vulnerabilities. There also exist some frameworks already. This project is meant to provide a stable project base to implement what ever a developer wants to: Dynamic Homepages, Webshops, ..
|
||||||
|
|
||||||
|
## Extending the Base
|
||||||
|
|
||||||
|
### Adding API-Endpoints
|
||||||
|
|
||||||
|
Each API endpoint has usually one overlying category, for example all user and authorization endpoints belong to the [UserAPI](/core/Api/UserAPI.class.php).
|
||||||
|
These endpoints can be accessed by requesting URLs starting with `/api/user`, for example: `/api/user/login`. There are also endpoints, which don't have
|
||||||
|
a category, e.g. [PatchSQL](/core/Api/PatchSQL.class.php). These functions can be called directly, for example with `/api/patchSQL`. Both methods have one thing in common:
|
||||||
|
Each endpoint is represented by a class inheriting the [Request Class](/core/Api/Request.class.php). An example endpoint looks like this:
|
||||||
|
|
||||||
|
```php
|
||||||
|
namespace Api;
|
||||||
|
use Api\Parameter\Parameter;
|
||||||
|
use Objects\User;
|
||||||
|
|
||||||
|
class SingleEndpoint extends Request {
|
||||||
|
|
||||||
|
public function __construct(User $user, bool $externalCall = false) {
|
||||||
|
parent::__construct($user, $externalCall, array(
|
||||||
|
"someParameter" => new Parameter("someParameter", Parameter::TYPE_INT, true, 100)
|
||||||
|
));
|
||||||
|
$this->forbidMethod("POST");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute($values = array()): bool {
|
||||||
|
if (!parent::execute($values)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$this->result['someAttribute'] = $this->getParam("someParameter") * 2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
An endpoint consists of two important functions:
|
||||||
|
1. the constructor defining the expected parameters as well as some restrictions and endpoint configuration.
|
||||||
|
2. the execute function, checking all requirements by calling the parent, and then executing the own method.
|
||||||
|
|
||||||
|
To create an API category containing multiple endpoints, a parent class inheriting from `Request`, e.g. `class MultipleAPI extends Request` is required.
|
||||||
|
All endpoints inside this category then inherit from the `MultipleAPI` class.
|
||||||
|
|
||||||
|
The classes must be present inside the [Api](/core/Api) directory according to the other endpoints.
|
||||||
|
|
||||||
|
### Access Control
|
||||||
|
|
||||||
|
By default, and if not further specified or restricted, all endpoints have the following access rules:
|
||||||
|
1. Allowed methods: GET and POST (`$this->allowedMethods`)
|
||||||
|
2. No login is required (`$this->loginRequired`)
|
||||||
|
3. CSRF-Token is required, if the user is logged in (`$this->csrfTokenRequired`)
|
||||||
|
4. The function can be called from outside (`$this->isPublic`)
|
||||||
|
5. An API-Key can be used to access this method (`$this->apiKeyAllowed`)
|
||||||
|
6. All user groups can access the method (Database, Table: `ApiPermission`)
|
||||||
|
|
||||||
|
The first five restrictions can be modified inside the constructor, while the group permissions are changed using
|
||||||
|
the [Admin Dashboard](/adminPanel). It's default values are set inside the [database script](/core/Configuration/CreateDatabase.class.php).
|
||||||
|
|
||||||
|
### Using the API internally
|
||||||
|
|
||||||
|
Some endpoints are set to private, which means, they can be only accessed inside the backend. These functions, as well as the public ones,
|
||||||
|
can be used by creating the desired request object, and calling the execute function with our parameters like shown below:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$req = new \Api\Mail\Send($user);
|
||||||
|
$success = $req->execute(array(
|
||||||
|
"to" => "mail@example.org",
|
||||||
|
"subject" => "Example Mail",
|
||||||
|
"body" => "This is an example mail"
|
||||||
|
));
|
||||||
|
|
||||||
|
if (!$success) {
|
||||||
|
echo $req->getLastError();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The user object is usually obtained from the api (`$this->user`) or from the frontend document (`$document->getUser()`).
|
||||||
|
If any result is expected from the api call, the `$req->getResult()` method can be used, which returns an array of all field.
|
||||||
|
|
||||||
|
### Modifying the database
|
||||||
|
|
||||||
|
This step is not really required, as and changes made to the database must not be presented inside the code.
|
||||||
|
On the other hand, it is recommended to keep track of any modifications for later use or to deploy the application
|
||||||
|
to other systems. Therefore, either the [default installation script](/core/Configuration/CreateDatabase.class.php) or
|
||||||
|
an additional patch file, which can be executed using the API (`/api/PatchSQL`), can be created. The patch files are usually
|
||||||
|
located in [/core/Configuration/Patch](/core/Configuration/Patch) and have the following structure:
|
||||||
|
|
||||||
|
```php
|
||||||
|
namespace Configuration\Patch;
|
||||||
|
|
||||||
|
use Configuration\DatabaseScript;
|
||||||
|
use Driver\SQL\SQL;
|
||||||
|
|
||||||
|
class example_patch extends DatabaseScript {
|
||||||
|
public static function createQueries(SQL $sql): array {
|
||||||
|
$queries = [];
|
||||||
|
$queries[] = $sql->createTable("ExampleTable")
|
||||||
|
->addSerial("exampleCol")
|
||||||
|
->addString("someString", 32)
|
||||||
|
->primaryKey("exampleCol");
|
||||||
|
return $queries;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Routing
|
||||||
|
|
||||||
|
To access and view any frontend pages, the internal router is used. Available routes can be customized on the admin dashboard. There are four types of routes:
|
||||||
|
|
||||||
|
1. Permanent redirect (http status code: 308)
|
||||||
|
2. Temporary redirect (http status code: 307)
|
||||||
|
3. Static Route
|
||||||
|
4. Dynamic Content
|
||||||
|
|
||||||
|
A static route targets a file, usually located in [/static](/static) and does nothing more, than returning its content. A dynamic route is usually the way to go:
|
||||||
|
It takes two parameters, firstly the target document and secondly, an optional view. For example, take the following routing table:
|
||||||
|
|
||||||
|
| Route | Action | Target | Extra |
|
||||||
|
| ----- | ------ | ------ | ----- |
|
||||||
|
| `/funnyCatImage` | `Serve Static` | `/static/cat.jpg` | |
|
||||||
|
| `/someRoute(/(.*))?` | `Redirect Dynamic` | `\Documents\MyDocument\` | `$2` |
|
||||||
|
|
||||||
|
The first route would return the cat image, if the case-insensitive path `/funnyCatImage` is requested.
|
||||||
|
The second route is more interesting, as it firstly contains regex, which means, any route starting with `/someRoute/` or just `/someRoute` is accepted.
|
||||||
|
Secondly, it passes the second group (`$2`), which is all the text after the last slash (or `null`) to the dynamically loaded document `MyDocument`.
|
||||||
|
|
||||||
|
### Creating and Modifying documents
|
||||||
|
|
||||||
|
A frontend page consists of a document, which again consists of a head and a body. Furthermore, a document can have various views, which have to be implemented
|
||||||
|
programmatically. Usually, all pages inside a document look somehow similar, for example share a common side- or navbar, a header or a footer. If we think of a web-shop,
|
||||||
|
we could have one document, when showing different articles and products, and a view for various pages, e.g. the dashboard with all the products, a single product view and so on.
|
||||||
|
To create a new document, a class inside [/core/Documents](/core/Documents) is created with the following scheme:
|
||||||
|
|
||||||
|
```php
|
||||||
|
namespace Documents {
|
||||||
|
|
||||||
|
use Elements\Document;
|
||||||
|
use Objects\User;
|
||||||
|
use Documents\Example\ExampleHead;
|
||||||
|
use Documents\Example\ExampleBody;
|
||||||
|
|
||||||
|
class ExampleDocument extends Document {
|
||||||
|
public function __construct(User $user, ?string $view = NULL) {
|
||||||
|
parent::__construct($user, ExampleHead::class, ExampleBody::class, $view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Documents\Example {
|
||||||
|
|
||||||
|
use Elements\Head;
|
||||||
|
use Elements\Body;
|
||||||
|
|
||||||
|
class ExampleHead extends Head {
|
||||||
|
|
||||||
|
public function __construct($document) {
|
||||||
|
parent::__construct($document);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function initSources() {
|
||||||
|
$this->loadJQuery();
|
||||||
|
$this->loadBootstrap();
|
||||||
|
$this->loadFontawesome();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function initMetas() : array {
|
||||||
|
return array(
|
||||||
|
array('charset' => 'utf-8'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function initRawFields() : array {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function initTitle() : string {
|
||||||
|
return "Example Document";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExampleBody extends Body {
|
||||||
|
public function __construct($document) {
|
||||||
|
parent::__construct($document);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCode(): string {
|
||||||
|
$view = $this->getDocument()->getView() ?? "<Empty>";
|
||||||
|
return "<b>Requested View:</b> " . htmlspecialchars($view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Of course, the head and body classes can be placed in any file, as the code might get big and complex.
|
||||||
|
|
||||||
|
|
||||||
|
## Anything more?
|
||||||
|
|
||||||
|
Feel free to contact me regarding this project and any other questions.
|
Loading…
Reference in New Issue
Block a user