-
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
<?php defined('BLUDIT') or die('Bludit CMS.');
|
||||
|
||||
class dbJSON {
|
||||
|
||||
public $db;
|
||||
public $dbBackup;
|
||||
public $file;
|
||||
public $firstLine;
|
||||
|
||||
// $file, the JSON file.
|
||||
// $firstLine, TRUE if you want to remove the first line, FALSE otherwise
|
||||
function __construct($file, $firstLine=true)
|
||||
{
|
||||
$this->file = $file;
|
||||
$this->db = array();
|
||||
$this->dbBackup = array();
|
||||
$this->firstLine = $firstLine;
|
||||
|
||||
if (file_exists($file)) {
|
||||
// Read JSON file
|
||||
$lines = file($file);
|
||||
|
||||
// Remove the first line, the first line is for security reasons
|
||||
if ($firstLine) {
|
||||
unset($lines[0]);
|
||||
}
|
||||
|
||||
// Regenerate the JSON file
|
||||
$implode = implode('', $lines);
|
||||
|
||||
// Unserialize, JSON to Array
|
||||
$array = $this->unserialize($implode);
|
||||
if (empty($array)) {
|
||||
$this->db = array();
|
||||
$this->dbBackup = array();
|
||||
} else {
|
||||
$this->db = $array;
|
||||
$this->dbBackup = $array;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function restoreDB()
|
||||
{
|
||||
$this->db = $this->dbBackup;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns the number of rows in the database
|
||||
public function count()
|
||||
{
|
||||
return count($this->db);
|
||||
}
|
||||
|
||||
// Returns the value from the field
|
||||
public function getField($field)
|
||||
{
|
||||
if (isset($this->db[$field])) {
|
||||
return $this->db[$field];
|
||||
}
|
||||
if (isset($this->dbFields[$field])) {
|
||||
return $this->dbFields[$field];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Save the JSON file
|
||||
public function save()
|
||||
{
|
||||
$data = '';
|
||||
if ($this->firstLine) {
|
||||
$data = "<?php defined('BLUDIT') or die('Bludit CMS.'); ?>".PHP_EOL;
|
||||
}
|
||||
|
||||
// Serialize database
|
||||
$data .= $this->serialize($this->db);
|
||||
|
||||
// Backup the new database.
|
||||
$this->dbBackup = $this->db;
|
||||
|
||||
// LOCK_EX flag to prevent anyone else writing to the file at the same time.
|
||||
if (file_put_contents($this->file, $data, LOCK_EX)) {
|
||||
return true;
|
||||
} else {
|
||||
Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to save the database file.', LOG_TYPE_ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a JSON encoded string on success or FALSE on failure
|
||||
private function serialize($data)
|
||||
{
|
||||
if (DEBUG_MODE) {
|
||||
return json_encode($data, JSON_PRETTY_PRINT);
|
||||
}
|
||||
return json_encode($data);
|
||||
}
|
||||
|
||||
// Returns the value encoded in json in appropriate PHP type
|
||||
private function unserialize($data)
|
||||
{
|
||||
// NULL is returned if the json cannot be decoded
|
||||
$decode = json_decode($data, true);
|
||||
if ($decode===NULL) {
|
||||
Log::set(__METHOD__.LOG_SEP.'Error trying to read the JSON file: '.$this->file, LOG_TYPE_ERROR);
|
||||
return false;
|
||||
}
|
||||
return $decode;
|
||||
}
|
||||
|
||||
public function getDB()
|
||||
{
|
||||
return $this->db;
|
||||
}
|
||||
|
||||
// Truncate all the rows
|
||||
public function truncate()
|
||||
{
|
||||
$this->db = array();
|
||||
return $this->save();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
<?php defined('BLUDIT') or die('Bludit CMS.');
|
||||
|
||||
/*
|
||||
Database structure
|
||||
|
||||
{
|
||||
"videos": {
|
||||
"name": "Videos",
|
||||
"template: "",
|
||||
"description: "",
|
||||
"list": [ "my-page", "second-page" ]
|
||||
},
|
||||
"pets": {
|
||||
"name": "Pets",
|
||||
"template: "",
|
||||
"description: "",
|
||||
"list": [ "cats-and-dogs" ]
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
class dbList extends dbJSON
|
||||
{
|
||||
public $db = array();
|
||||
|
||||
function __construct($file)
|
||||
{
|
||||
parent::__construct($file);
|
||||
}
|
||||
|
||||
public function keys()
|
||||
{
|
||||
return array_keys($this->db);
|
||||
}
|
||||
|
||||
// Returns the list of keys filter by pageNumber
|
||||
// $pageNumber start in 1
|
||||
public function getList($key, $pageNumber, $numberOfItems)
|
||||
{
|
||||
if (!isset($this->db[$key])) {
|
||||
Log::set(__METHOD__.LOG_SEP.'Error key does not exist '.$key);
|
||||
return false;
|
||||
}
|
||||
|
||||
// List of keys
|
||||
$list = $this->db[$key]['list'];
|
||||
|
||||
// Returns all the items from the list
|
||||
if ($numberOfItems==-1) {
|
||||
return $list;
|
||||
}
|
||||
|
||||
// The first page number is 1, so the real is 0
|
||||
$realPageNumber = $pageNumber - 1;
|
||||
$chunks = array_chunk($list, $numberOfItems);
|
||||
if (isset($chunks[$realPageNumber])) {
|
||||
return $chunks[$realPageNumber];
|
||||
}
|
||||
|
||||
// Out of index,returns FALSE
|
||||
return false;
|
||||
}
|
||||
|
||||
public function generateKey($name)
|
||||
{
|
||||
global $L;
|
||||
|
||||
$key = Text::cleanUrl($name);
|
||||
if (Text::isEmpty($key)) {
|
||||
$key = $L->g('empty');
|
||||
}
|
||||
while (isset($this->db[$key])) {
|
||||
$key++;
|
||||
}
|
||||
return $key;
|
||||
}
|
||||
|
||||
// Add a new item to the dblist
|
||||
// $args => 'name', 'template', 'description', 'list'
|
||||
public function add($args)
|
||||
{
|
||||
$key = $this->generateKey($args['name']);
|
||||
|
||||
$this->db[$key]['name'] = Sanitize::removeTags($args['name']);
|
||||
$this->db[$key]['template'] = isset($args['template'])?Sanitize::removeTags($args['template']):'';
|
||||
$this->db[$key]['description'] = isset($args['description'])?Sanitize::removeTags($args['description']):'';
|
||||
$this->db[$key]['list'] = isset($args['list'])?$args['list']:array();
|
||||
|
||||
$this->sortAlphanumeric();
|
||||
$this->save();
|
||||
return $key;
|
||||
}
|
||||
|
||||
public function remove($key)
|
||||
{
|
||||
if (!isset($this->db[$key])) {
|
||||
Log::set(__METHOD__.LOG_SEP.'The key does not exist, key: '.$key);
|
||||
return false;
|
||||
}
|
||||
|
||||
unset($this->db[$key]);
|
||||
return $this->save();
|
||||
}
|
||||
|
||||
// Edit an item to the dblist
|
||||
// $args => 'name', 'oldkey', 'newKey', 'template', 'description'
|
||||
public function edit($args)
|
||||
{
|
||||
if ( isset($this->db[$args['newKey']]) && ($args['newKey']!==$args['oldKey']) ) {
|
||||
Log::set(__METHOD__.LOG_SEP.'The new key already exists. Key: '.$args['newKey'], LOG_TYPE_WARN);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->db[$args['newKey']]['name'] = Sanitize::removeTags($args['name']);
|
||||
$this->db[$args['newKey']]['template'] = isset($args['template'])?Sanitize::removeTags($args['template']):'';
|
||||
$this->db[$args['newKey']]['description'] = isset($args['description'])?Sanitize::removeTags($args['description']):'';
|
||||
$this->db[$args['newKey']]['list'] = $this->db[$args['oldKey']]['list'];
|
||||
|
||||
// Remove the old category
|
||||
if ($args['oldKey'] !== $args['newKey']) {
|
||||
unset( $this->db[$args['oldKey']] );
|
||||
}
|
||||
|
||||
$this->sortAlphanumeric();
|
||||
$this->save();
|
||||
return $args['newKey'];
|
||||
}
|
||||
|
||||
// Sort the categories by "Natural order"
|
||||
public function sortAlphanumeric()
|
||||
{
|
||||
// Sort key alphanumeric strings, a01, a10, b10, c02
|
||||
return ksort($this->db);
|
||||
}
|
||||
|
||||
// Returns the name associated to the key, FALSE if the key doesn't exist
|
||||
public function getName($key)
|
||||
{
|
||||
if (isset($this->db[$key])) {
|
||||
return $this->db[$key]['name'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns an array with key=>name of the list
|
||||
public function getKeyNameArray()
|
||||
{
|
||||
$tmp = array();
|
||||
foreach($this->db as $key=>$fields) {
|
||||
$tmp[$key] = $fields['name'];
|
||||
}
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
// Returns the number of items in the list
|
||||
public function countItems($key)
|
||||
{
|
||||
if (isset($this->db[$key])) {
|
||||
return count($this->db[$key]['list']);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function exists($key)
|
||||
{
|
||||
return isset( $this->db[$key] );
|
||||
}
|
||||
|
||||
public function existsName($name)
|
||||
{
|
||||
foreach ($this->db as $key=>$fields) {
|
||||
if ($name==$fields['name']) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns an array with a portion of the database filtered by key
|
||||
// Returns array( 'key'=>'', 'name'=>'', 'template'=>'', 'description'=>'', list'=>array() )
|
||||
public function getMap($key)
|
||||
{
|
||||
if (isset($this->db[$key])) {
|
||||
$tmp = $this->db[$key];
|
||||
$tmp['key'] = $key;
|
||||
return $tmp;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,354 @@
|
||||
<?php defined('BLUDIT') or die('Bludit CMS.');
|
||||
|
||||
class Plugin
|
||||
{
|
||||
|
||||
// (string) directory name, just the name
|
||||
// Ex: sitemap
|
||||
public $directoryName;
|
||||
|
||||
// (string) Absolute database filename and path
|
||||
// Ex: /www/bludit/bl-content/plugins/sitemap/db.php
|
||||
public $filenameDb;
|
||||
|
||||
// (string) Absolute metadata filename and path
|
||||
// Ex: /www/bludit/bl-plugins/sitemap/metadata.json
|
||||
public $filenameMetadata;
|
||||
|
||||
// (array) Plugin metadata
|
||||
// Ex: array('author'=>'',...., 'notes'=>'')
|
||||
public $metadata;
|
||||
|
||||
// (string) Class name
|
||||
// Ex: pluginSitemap
|
||||
public $className;
|
||||
|
||||
// (array) Database unserialized
|
||||
public $db;
|
||||
|
||||
// (array) Database fields, only for initialize
|
||||
public $dbFields;
|
||||
|
||||
// (boolean) Enable or disable default Save and Cancel button on plugin settings
|
||||
public $formButtons;
|
||||
|
||||
// (array) List of custom hooks
|
||||
public $customHooks;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
$this->dbFields = array();
|
||||
$this->customHooks = array();
|
||||
|
||||
$reflector = new ReflectionClass(get_class($this));
|
||||
|
||||
// Directory name
|
||||
$this->directoryName = basename(dirname($reflector->getFileName()));
|
||||
|
||||
// Class Name
|
||||
$this->className = $reflector->getName();
|
||||
|
||||
$this->formButtons = true;
|
||||
|
||||
// Call the method init() from the children
|
||||
$this->init();
|
||||
|
||||
// Init empty database with default values
|
||||
$this->db = $this->dbFields;
|
||||
|
||||
$this->filenameDb = PATH_PLUGINS_DATABASES . $this->directoryName . DS . 'db.php';
|
||||
|
||||
// --- Metadata ---
|
||||
$this->filenameMetadata = PATH_PLUGINS . $this->directoryName() . DS . 'metadata.json';
|
||||
$metadataString = file_get_contents($this->filenameMetadata);
|
||||
$this->metadata = json_decode($metadataString, true);
|
||||
|
||||
// If the plugin is installed then get the database
|
||||
if ($this->installed()) {
|
||||
$Tmp = new dbJSON($this->filenameDb);
|
||||
$this->db = $Tmp->db;
|
||||
$this->prepare();
|
||||
}
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$tmp = new dbJSON($this->filenameDb);
|
||||
$tmp->db = $this->db;
|
||||
return $tmp->save();
|
||||
}
|
||||
|
||||
public function includeCSS($filename)
|
||||
{
|
||||
return '<link rel="stylesheet" type="text/css" href="' . $this->domainPath() . 'css/' . $filename . '?version=' . BLUDIT_VERSION . '">' . PHP_EOL;
|
||||
}
|
||||
|
||||
public function includeJS($filename)
|
||||
{
|
||||
return '<script charset="utf-8" src="' . $this->domainPath() . 'js/' . $filename . '?version=' . BLUDIT_VERSION . '"></script>' . PHP_EOL;
|
||||
}
|
||||
|
||||
// Returns absolute URL and path of the plugin directory
|
||||
// This function helps to include CSS or Javascript files with absolute URL
|
||||
public function domainPath()
|
||||
{
|
||||
return DOMAIN_PLUGINS . $this->directoryName . '/';
|
||||
}
|
||||
|
||||
// Returns relative path of the plugin directory
|
||||
// This function helps to include CSS or Javascript files with relative URL
|
||||
public function htmlPath()
|
||||
{
|
||||
return HTML_PATH_PLUGINS . $this->directoryName . '/';
|
||||
}
|
||||
|
||||
// Returns absolute path of the plugin directory
|
||||
// This function helps to include PHP libraries or some file at server level
|
||||
public function phpPath()
|
||||
{
|
||||
return PATH_PLUGINS . $this->directoryName . DS;
|
||||
}
|
||||
|
||||
public function phpPathDB()
|
||||
{
|
||||
return PATH_PLUGINS_DATABASES . $this->directoryName . DS;
|
||||
}
|
||||
|
||||
// Returns the value of the key from the metadata of the plugin, FALSE if the key doesn't exist
|
||||
public function getMetadata($key)
|
||||
{
|
||||
if (isset($this->metadata[$key])) {
|
||||
return $this->metadata[$key];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set a key / value on the metadata of the plugin
|
||||
public function setMetadata($key, $value)
|
||||
{
|
||||
$this->metadata[$key] = $value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns the value of the field from the database
|
||||
// (string) $field
|
||||
// (boolean) $html, TRUE returns the value sanitized, FALSE unsanitized
|
||||
public function getValue($field, $html = true)
|
||||
{
|
||||
if (isset($this->db[$field])) {
|
||||
if ($html) {
|
||||
return $this->db[$field];
|
||||
} else {
|
||||
return Sanitize::htmlDecode($this->db[$field]);
|
||||
}
|
||||
}
|
||||
return $this->dbFields[$field];
|
||||
}
|
||||
|
||||
public function label()
|
||||
{
|
||||
return $this->getMetadata('label');
|
||||
}
|
||||
|
||||
public function name()
|
||||
{
|
||||
return $this->getMetadata('name');
|
||||
}
|
||||
|
||||
public function description()
|
||||
{
|
||||
return $this->getMetadata('description');
|
||||
}
|
||||
|
||||
public function author()
|
||||
{
|
||||
return $this->getMetadata('author');
|
||||
}
|
||||
|
||||
public function email()
|
||||
{
|
||||
return $this->getMetadata('email');
|
||||
}
|
||||
|
||||
public function website()
|
||||
{
|
||||
return $this->getMetadata('website');
|
||||
}
|
||||
|
||||
public function position()
|
||||
{
|
||||
return $this->getValue('position');
|
||||
}
|
||||
|
||||
public function version()
|
||||
{
|
||||
return $this->getMetadata('version');
|
||||
}
|
||||
|
||||
public function releaseDate()
|
||||
{
|
||||
return $this->getMetadata('releaseDate');
|
||||
}
|
||||
|
||||
public function className()
|
||||
{
|
||||
return $this->className;
|
||||
}
|
||||
|
||||
public function formButtons()
|
||||
{
|
||||
return $this->formButtons;
|
||||
}
|
||||
|
||||
public function isCompatible()
|
||||
{
|
||||
$bluditRoot = explode('.', BLUDIT_VERSION);
|
||||
$compatible = explode(',', $this->getMetadata('compatible'));
|
||||
foreach ($compatible as $version) {
|
||||
$root = explode('.', $version);
|
||||
if ($root[0] == $bluditRoot[0] && $root[1] == $bluditRoot[1]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function directoryName()
|
||||
{
|
||||
return $this->directoryName;
|
||||
}
|
||||
|
||||
// Return TRUE if the installation success, otherwise FALSE.
|
||||
public function install($position = 1)
|
||||
{
|
||||
if ($this->installed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create workspace
|
||||
$workspace = $this->workspace();
|
||||
mkdir($workspace, DIR_PERMISSIONS, true);
|
||||
|
||||
// Create plugin directory for the database
|
||||
mkdir(PATH_PLUGINS_DATABASES . $this->directoryName, DIR_PERMISSIONS, true);
|
||||
|
||||
$this->dbFields['position'] = $position;
|
||||
// Sanitize default values to store in the file
|
||||
foreach ($this->dbFields as $key => $value) {
|
||||
$value = Sanitize::html($value);
|
||||
settype($value, gettype($this->dbFields[$key]));
|
||||
$this->db[$key] = $value;
|
||||
}
|
||||
|
||||
// Create the database
|
||||
return $this->save();
|
||||
}
|
||||
|
||||
public function uninstall()
|
||||
{
|
||||
// Delete database
|
||||
$path = PATH_PLUGINS_DATABASES . $this->directoryName;
|
||||
Filesystem::deleteRecursive($path);
|
||||
|
||||
// Delete workspace
|
||||
$workspace = $this->workspace();
|
||||
Filesystem::deleteRecursive($workspace);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns TRUE if the plugin is installed
|
||||
// This function just check if the database of the plugin is created
|
||||
public function installed()
|
||||
{
|
||||
return file_exists($this->filenameDb);
|
||||
}
|
||||
|
||||
public function workspace()
|
||||
{
|
||||
return PATH_WORKSPACES . $this->directoryName . DS;
|
||||
}
|
||||
|
||||
public function init()
|
||||
{
|
||||
// This method is used on children classes
|
||||
// The user can define his own field of the database
|
||||
}
|
||||
|
||||
public function prepare()
|
||||
{
|
||||
// This method is used on children classes
|
||||
// The user can prepare the plugin, when it is installed
|
||||
}
|
||||
|
||||
public function post()
|
||||
{
|
||||
$args = $_POST;
|
||||
foreach ($this->dbFields as $field => $value) {
|
||||
if (isset($args[$field])) {
|
||||
$finalValue = Sanitize::html($args[$field]);
|
||||
if ($finalValue === 'false') {
|
||||
$finalValue = false;
|
||||
} elseif ($finalValue === 'true') {
|
||||
$finalValue = true;
|
||||
}
|
||||
settype($finalValue, gettype($value));
|
||||
$this->db[$field] = $finalValue;
|
||||
}
|
||||
}
|
||||
return $this->save();
|
||||
}
|
||||
|
||||
public function type()
|
||||
{
|
||||
return $this->getMetadata('type');
|
||||
}
|
||||
|
||||
public function setField($field, $value)
|
||||
{
|
||||
$this->db[$field] = Sanitize::html($value);
|
||||
return $this->save();
|
||||
}
|
||||
|
||||
public function setPosition($position)
|
||||
{
|
||||
return $this->setField('position', $position);
|
||||
}
|
||||
|
||||
// Returns the parameters after the URI, FALSE if the URI doesn't match with the webhook
|
||||
// Example: https://www.mybludit.com/api/foo/bar
|
||||
public function webhook($URI = false, $returnsAfterURI = false, $fixed = true)
|
||||
{
|
||||
global $url;
|
||||
|
||||
if (empty($URI)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check URI start with the webhook
|
||||
$startString = HTML_PATH_ROOT . $URI;
|
||||
$URI = $url->uri();
|
||||
$length = mb_strlen($startString, CHARSET);
|
||||
if (mb_substr($URI, 0, $length) != $startString) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$afterURI = mb_substr($URI, $length);
|
||||
if (!empty($afterURI)) {
|
||||
if ($fixed) {
|
||||
return false;
|
||||
}
|
||||
if ($afterURI[0] != '/') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($returnsAfterURI) {
|
||||
return $afterURI;
|
||||
}
|
||||
|
||||
Log::set(__METHOD__ . LOG_SEP . 'Webhook requested.');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user