<!-- DO NOT EDIT. This file generated from template by Code Scrawl https://tluf.me/php/code-scrawl/ -->
# Liaison
A PHP Framework and a set of components for developing webapps and websites. The software is fairly robust, but the documentation is horrible. The code is also messy & needs a lot of refactoring that may or may not happen.
# Lia\Simple
Lia\Simple extends \Lia and simplifies a lot of server setup. Simple is also pretty messy & confusing.
Much more documentation is needed
## Server Setup
This is basically all thoe code you need to setup a Liaison server.
```php
<?php
require(__DIR__.'/vendor/autoload.php');
$site = __DIR__.'/site/';
$apps = __DIR__.'/apps/';
$lia = new \Lia\Simple();
$lia->debug = !$lia->is_production();
$lia->generic_error_page = __DIR__.'/cache/generic-error-page.html';
$lia->root_dir = __DIR__;
// very simple path-based delivery of static files
$lia->deliver_files("$site/public-archive/");
// by default it will auto-load `$lia->root_dir.'/RSettings.json'`
R()->load("$site/RSettings.json");
// load Liaison apps.
$lia->load_apps("$site", "$apps/Files", "$apps/Blog", "$apps/Forms");
// initialize the apps. See Lifecycle below
$lia->setup();
// retrieve phad instance from a liaison app & configure it.
$files_phad = $lia->phad_from_dir("$apps/Files/");
$files_phad->dir_upload = __DIR__.'/backup/files-upload/';
// sends a response, redirect, or whatever
$lia->respond();
```
## Lifecycle of Lia\Simple
`Lia\Simple::__construct` initializes the default `\Lia\Package\Server` instance, which loads the built-in package & addons like the Router, Seo, View, and others.
`Lia\Simple::load_apps($dir1, $dir2, ...)` will initialize the given app directories, creating instances of `\Lia\Package\Server` for each. Simple does not allow a custom Package class when using `load_apps()` or `load_app`
`Lia\Package\Server::__construct` - called for each app when `load_apps()` is called.
1. Set configs from `"$app_dir/config.json"`, if file exists.
2. Set up routes, views, cache dir, default settings like `$lia->base_url` & cache dir
3. Initialize addons found within the app dir
4. Call `$addon->init_lia($package)` on each addon
5. Call `$package->ready()`, which calls `$addon->onPackageReady()` for each addon in the package.
`Lia\Simple::setup()` - This is bad feature because `Lia\Package\Server` already calls `$package->ready()` during its `__construct`
1. Loop over all packages (each app has a `Lia\Package` class instance)
2. Call each `$package->ready()`
3. `$package` loops over each of its `$package->addons` and calls `$addon->onPackageReady($package)`
4. Override `onPackageReady()` in your `Lia\Addon` for any app to do further setup. The base Addon class doesn't do anything with `onPackageReady()`.
`Lia\Simple::respond()` - calls `$lia->deliver()`, but wraps it in error handling.
Notes:
- Will try to deliver a generic error page. if an exception is thrown. Worst case scenario, just prints that there was an error & a generic link to the home page.
- If `$_SERVER['DO_NOT_RESPOND'] == true`, then simply returns and does nothing.
- If `$lia->debug == true` AND the request is to `/debug/`, call `$lia->debug()` and `exit;`.
- If `$lia->debug == true`, will throw errors instead of showing generic error page. `respond()` DOES NOT change php error display/reporting settings.
- Generic error page must be absolute path set at `$lia->cache->dir.'/generic-error-page.html'` OR `$lia->generic_error_page`.
Lifecycle `Lia::deliver()` - called by `Simple::respond()`, and actually calls `Lia\Addon\Server::deliver()` (*Apr 13, 2023*)
1. Call hooks `ServerStart`, `PreAllPackagesReady`, and `AllPackagesReady` with no params
2. Initialize `Lia\Obj\Request` and `Lia\Obj\Response`
3. Call hook `RequestStarted` with params `$request, $response`.
4. Call `$lia->route($request)`, which calls `Lia\Addon\Router::route($request);`. Gets a list of matching routes from the routeMap. ALTERNATIVELY, if `$router->routers` contains an array of callables & one of those callables returns something truthy (supposed to be an array of routes), then return that.
5. Call hook `RoutesFound` with param `$routeList`
6. Foreach route, call hook `FilterRoute` with param `$route`. If ANY of the hook handlers returns strict (`===`) `false`, remove `$route` from the list.
7. Filter remaining `$routeList` down to one route using an oversimplified and bad algorithm.
8. if route is null, then `try_redirect_to_corrected_url()`, which is a url normalizer & redirecter that `exit`s. If it does not `exit`, throw an excpetion that no routes were found.
9. Call `RoutesFiltered` hook with param `\Lia\Obj\Route $route`
10. Set `$response->useTheme = true`
11. Call `$server->process_route($route, $response);` - executes callable, `require`s php file, or loads static file. Considers cache for static file. Theme is disabled for static file. Enabled for callable or php file. Sets `$response->content` instead of outputting content.
12. If `$_GET['theme']=='json'`, then sets `$server->theme = 'json'` and compiles resource files (js & css files)
13. Call hook `RouteResolved` with params `$route, $response`.
14. Apply Theme. if EITHER `$response->useTheme` OR `$server->useTheme` are falsy, do nothing. if `$server->theme=='json'`, build array with keys `content`, `scripts`, and `stylesheets`, json_encode that array, and set `$response->content` to that json string. Otherwise, load the view with name `$server->themeName` and pass keys `response` and `content` to that view. Then call hook `ThemeLoaded` with param `\Lia\Obj\View $themeView`. Then set `$response->content` to stringified `$themeView`.
15. Call hook `ResponseReady` with param `$response`
16. send `$response->headers`, then `$response->content`
17. Call hooks `ResponseSent` then `RequestFinished`, both with one param `$response`
# Old Documentation (prior to Apr 13, 2023)
These docs below are probably accurate for the most part ... but they are not in reference to Lia\Simple, and they need reviewed.
## Next Version (release TBD)
This version is planned for the future & as of Apr 12, 2022 development has not begun. Just notes. See Status.md
`v0.6` will be the next version & will come with major internal changes but likely will not have any significant changes to the API. The current version has Package & Addon as sub-classes of Lia. Also, there are MANY properties by-reference. These complexities are slow & confusing. In the new version, Packages & Addons will likely not extend from Liaison any further. And by-reference properties will be removed.
## Beta Version (April 5, 2021)
`v0.5` marks the official beta. Software-wise, it's basically ready to go. Documentation wise, it's pretty poor. There are some weird things in here that will make it hard for you to use to it's full ability until I finish writing proper documentation. There's also some minor code issues in Liaison that I do need to fix.
**My advice:** Admire what it could be, keep an eye on it, and use it when it is a little more mature.
## Quick Start
1. Write a deliver script, such as `deliver.php`. Comment out the `require add-route.php` line
```php
<?php
require_once(dirname(__DIR__,2).'/vendor/autoload.php');
$lia = new \Lia();
$main = \Lia\Package\Server::main($lia);
$site = new \Lia\Package\Server($lia, 'site', __DIR__);
//comment this line out in step 1
require(__DIR__.'/add-route.php');
$lia->deliver();
```
2. Write a home page.
Create a file `public/index.php`
```html
<h1>Index Page</h1>
<p>Any file in the `public` dir will be routed to automatically. Any public/*.php files are routed with NO file extension.</p>
```
3. Start the server: `php -S localhost:3000 deliver.php`. Visit `http://localhost:3000/` in your browser
Ideally, write tests to ensure your site works as expected. See [test/run/ServerMinimal.php](/test/run/ServerMinimal.php) for simple examples. I use [php/tester](https://tluf.me/php/tester), but [Php Unit](https://phpunit.de/) is the popular go-to for php testing
4. Write a view file at `view/ArticlePreview.php`
```php
<div class="ArticlePreview" >
<h1><?=$title?></h1>
<p><?=$description?></p>
</div>
```
5. Write a stylesheet at `view/ArticlePreview.css`
You can also write `view/ArticlePreview.js` and `view/ArticlePreview/*.css|*.js` files to add more styling and scripting
```php
.ArticlePreview {
border:1px solid black;
}
```
5. Write a route in your `deliver.php` file. Alternatively, make a public file `public/{slug}.php` and `echo $view` instead of `$response->content = $view`;
```php
<?php
// in production, you might use a database & have some error handling
$articles = [
'cat'=>[
'title'=>'Cats are great',
'description'=>'I\'ve always loved cats. I had two when I was a little kid. As a teen I had a dog & a cat. Loved them both dearly. I love dogs too.'
],
'dog'=>[
'title'=>'fill me in',
'description'=>'fill me in'
],
];
$lia->addRoute('/{article}/',
function($route, $response) use ($lia, $articles){
$slug = $route->param('article');
$view = $lia->view('ArticlePreview', $articles[$slug]);
$response->content = $view;
}
);
```
6. Write a theme at `view/theme.php`:
Call `$lia->setTheme('theme/name')` to change the theme.
```php
<!DOCTYPE html>
<html>
<head>
<?=$this->getHeadHtml()?>
</head>
<body>
<?=$content?>
</body>
</html>
```
## Lia\Simple
A class for more easily setting up a Liaison instance with several integrations.
Notes:
- Sets `user_has_role` handler on phad to a function that returns `$this->user->has_role($role)` or `true` if `$this->user` is not set.
## Older Documentation
I believe the remaining docs are still accurate, but I have not reviewed them recently for accuracy or clarity.
### Structure
- `Lia` manages methods, addons, and properties
- `Lia\Package` is a base class for packaging addons together
- `Lia\Addon` is a base class for writing addons
- `Lia\Package\Server` helps deliver websites by tying together main addons (public files, views, cache, autoloading, and more)
- dir `code/class/Object/*` are objects used by built-in components
- dir `code/class/Utility/*` are Utility classes
- dir `view/theme` provides a default theme
- dir `file/mime_type_map.php` is just that
### Components
Addons create all the features. `Lia\Package` calls upon several of these components
- Autoloader: loads classes within given directories
- Cache: cache key/value pairs & files
- Error: Report errors to users
- Hook: register & call hooks (very generic form of extensibility)
- Redirect: Redirect requests
- Resources:
- Add css & js files, urls, and/or code blocks to a request
- Sorting api to set order of resource files in compiled output
- Routes to compiled resource files
- Manages seo information (this should go in a new component)
- Outputs headHtml (must be called)
- Passes compiled files to cache component
- ResourceSorter: A wrapper around the `Resources` sorting api, to make it easier
- Router: Set pattern & static routes. Parse paramaters from urls. Process url for route target (package, callable, file)
- Server: Handles request delivery
- Helps all the addons work together to respond to a url
- delivers static non-php files
- View: Display re-usable scripts/templates
### Directory Structure
The `Package` decides the structure, so this can be changed. Default is:
```
App/
- config.json <- Package settings
- public/ <- Public files to be routed to. Ex: `public/contact.php` routes to `/contact/`
- view/ <- Views
- addon/ <- Addons (generally extending from \Lia\Addon)
- class/ <- Classes to autoload, PSR4 style. Will be converted to classmap style later
- cache/ <- Dir to store cache files. Only one cache dir is used (each app does not get its own)
```
### Other Stuff
- Environment-dependent features are not built-in, but I recommend my [php/env](https://tluf.me/php/env)
- set `$_SERVER['DO_NOT_RESPOND'] = true;` to stop `Simple->respond()` from doing anything.
- `\Lia\Simple->get_all_sitemap_routes()` is a useful method to know
- send `$_GET['theme'] = 'json'` to return a response as json with keys `content`, `scripts`, and `stylesheets`.