Framework Skeleton: Models Embedded

These are models already implemented by framework, defined either by Framework Skeleton API (so open for change and extension) or by Framework Engine API (so closed from change, open for extension).

Which models should developers be aware of?

There are two types of models framework comes with:

Following open models are available:

Class Folder Used if
EtagCacheableDriver cacheables you want response to be cacheable by etag headers
DateCacheableDriver cacheables you want response to be cacheable by last modified headers
BasicLoginThrottler throttlers you want form logins to have throttling abilities against brute-force attacks
SqlLoginThrottler throttlers you want a throttler where form logins are checked in an SQL database
NoSqlLoginThrottler throttlers you want a throttler where form logins are checked in an NoSQL database
SQL dao you want to quickly query a SQL database
EmergencyHandler errors an exception was thrown in STDERR phase
Json json you want HTML templating or JSON response
translate internationalization you want response to be adapted to locale

Following closed models are available:

Class Folder Used if
Lucinda\Framework\AbstractLoggerWrapper logging you want logging abilities for your app
Lucinda\Framework\LogReporter error_reporting you want error reporting abilities for your app

EtagCacheableDriver

This class extends Lucinda\Framework\CacheableDriver blueprint to generate an ETAG for current response. This will be picked up by Framework and sent back to caller as an ETag response header. Once that header is received, next time client requests same resource (page), value of ETAG will be sent along with it as If-Match or If-None-Match request header. If it didn't change, framework will respond with a 304 Not Modified header and empty body. Otherwise, framework will respond with 200 OK and full body.

Requires:

Framework binds class automatically on installation!

DateCacheableDriver

This class extends Lucinda\Framework\CacheableDriver blueprint to generate a last modified time for current response. This will be picked up by Framework and sent back to caller as an Last-Modified response header. Once that header is received, next time client requests same resource (page), value of ETAG will be sent along with it as If-Modified-Since or If-Unmodified-Since request header. If it didn't change, framework will respond with a 304 Not Modified header and empty body. Otherwise, framework will respond with 200 OK and full body.

Requires:

Because its results are best effort, it is to be used only if etags aren't supported by your web server (eg: running through CloudFlare)!

BasicLoginThrottler

This abstract class extends Lucinda\Framework\FormLoginThrottler blueprint to implement basic logic of login throttling. Login throttling is a mandatory requirement if your application uses form logins, preventing malicious clients from attempting brute-force username/password guessing attacks against your application. Every time a failed login is performed, user will be banned for 2ATTEMPTS_NUMBER-1 seconds from logging in (so ban gets higher the more consecutive failed attempts are made). Once user enters correct password, all bans for that user are removed!

Requires:

This class remains abstract because it takes no guesses WHERE TO STORE login attempts histories, necessary for logic above to be feasible: in SQL or a NoSQL database

SqlLoginThrottler

This class extends BasicLoginThrottler to store login histories in an SQL table with following structure (MySQL):

CREATE TABLE user_logins ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, ip VARCHAR(45) NOT NULL, username VARCHAR(255) NOT NULL, attempts BIGINT UNSIGNED NOT NULL default 0, penalty_expiration DATETIME DEFAULT NULL, date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY(id), UNIQUE(ip, username) ) Engine=InnoDB;

Requires:

Framework creates table and binds class automatically on installation if you've chosen form logins and sql (but no nosql) database support!

NoSqlLoginThrottler

This class extends BasicLoginThrottler to store login histories as JSON values in NoSQL documents where keys are calculated:

$key = "logins__".sha1(json_encode(array("ip"=>$ipAddress, "username"=>$userName)));

Requires:

Framework binds class automatically on installation if you've chosen form logins and nosql database support!

SQL

This procedural function automates execution of a prepared statement and results retrieval.

Syntax:

function SQL(string $query, array $parameters=[]): Lucinda\SQL\StatementResults

Where:

Usage example:

$resultSet = SQL("SELECT name FROM users WHERE id>:id", [":id"=>12]); while($row = $resultSet->toRow()) { echo $row["name"]."<br/>"; }

Requires:

EmergencyHandler

This class extending Lucinda\MVC\STDERR\Exception performs error handling for bugs found while STDERR MVC API tries to handle an exception. Default handler behavior is dying with error message, but developers are invited to change this class and implement whatever behavior is desired. There must be no bugs in STDERR MVC API, so whatever you find, please contact author immediately!

Requires:

Json

This class encapsulates JSON encoding/decoding on top of PHP's procedural functions, throwing a JsonException if encoding/decoding fail. It thus defines two public methods:

public function encode(mixed $data): string public function decode(string $json, boolean $assoc=true): array|stdClass

Required by:

translate

This procedural function, called inside views (templates or tags), returns a translation of a KEYWORD for detected caller's LOCALE (language) and thus provides internationalization abilities to displayed HTML content. If no translation is found for client's locale, KEYWORD itself is returned instead of throwing an error. This aligns with GETTEXT behavior, the industry standard in the field.

Syntax:

function translate(string $keyword, string $domain="", ...$parameters): string

Where:

  1. $keyword: (mandatory) a string that uniquely identifies text to be translated
  2. $domain: (optional) name of translation file where keyword will be saught. If none, default is used (see below).
  3. $parameters: (optional) varargs of parameter values to replace placeholders in text to be returned.

Translations will be located on disk in file {FOLDER}/{LOCALE}/{DOMAIN}.json, where:

  1. {FOLDER}: (mandatory) value of "folder" attribute of <internationalization> tag @ XML (eg: locale)
  2. {LOCALE}: (mandatory) locale detected by LocalizationListener (eg: fr_CH)
  3. {DOMAIN}: (mandatory) value of domain set in translate function or value of "domain" attribute of <internationalization> tag @ XML (eg: messages)
All translations are saved in JSON format as KEY-VALUE stores where key is translate keyword and value is text that will replace it.

Example:

Requires:

Lucinda\Framework\AbstractLoggerWrapper

This class, located in Framework Engine API, is a prototype that binds information contained by <loggers> stdout.xml tag with Logging API. Because there are endless ways and venues to log, only classes that extend it perform the actual logging. Framework provides you with two loggers: FileLoggerWrapper and SysLoggerWrapper that log to files or syslog. Developers can bind any other logger by extending this class and implementing its required prototype method:

protected function setLogger(SimpleXMLElement $xml): Lucinda\Logging\Logger

where a Lucinda\Logging\Logger instance is generated based on contents of matching <logger> tag, then returned.

Requires:

Lucinda\Framework\LogReporter

This class implementing Lucinda\MVC\STDERR\ErrorReporter, located in Framework Engine API, is a prototype that binds information contained by <reporters> stderr.xml tag with Logging API. Because there are endless ways and venues to log, only classes that extend it perform the actual error logging. Framework provides you with two loggers: FileReporter and SyslogReporter that log to files or syslog. Developers can bind any other logger by extending this class and implementing its required prototype method:

protected function getLogger(SimpleXMLElement $xml): Lucinda\Logging\Logger

where a Lucinda\Logging\Logger instance is generated based on contents of matching <reporter> tag, then returned.

Requires:


Share