mirror of
https://github.com/cosmocode/dokuwiki-plugin-struct.git
synced 2025-07-25 16:01:54 +00:00
213 lines
6.8 KiB
PHP
213 lines
6.8 KiB
PHP
<?php
|
|
|
|
/**
|
|
* DokuWiki Plugin struct (Helper Component)
|
|
*
|
|
* @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
|
|
* @author Andreas Gohr, Michael Große <dokuwiki@cosmocode.de>
|
|
*/
|
|
|
|
use dokuwiki\Extension\Plugin;
|
|
use dokuwiki\plugin\struct\meta\AccessDataValidator;
|
|
use dokuwiki\plugin\struct\meta\AccessTable;
|
|
use dokuwiki\plugin\struct\meta\Assignments;
|
|
use dokuwiki\plugin\struct\meta\Schema;
|
|
use dokuwiki\plugin\struct\meta\StructException;
|
|
|
|
/**
|
|
* The public interface for the struct plugin
|
|
*
|
|
* 3rd party developers should always interact with struct data through this
|
|
* helper plugin only. If additional interface functionality is needed,
|
|
* it should be added here.
|
|
*
|
|
* All functions will throw StructExceptions when something goes wrong.
|
|
*
|
|
* Remember to check permissions yourself!
|
|
*/
|
|
class helper_plugin_struct extends Plugin
|
|
{
|
|
/**
|
|
* Class names of renderers which should NOT render struct data.
|
|
* All descendants are also blacklisted.
|
|
*/
|
|
public const BLACKLIST_RENDERER = [
|
|
'Doku_Renderer_metadata',
|
|
'\renderer_plugin_qc'
|
|
];
|
|
|
|
/**
|
|
* Get the structured data of a given page
|
|
*
|
|
* @param string $page The page to get data for
|
|
* @param string|null $schema The schema to use null for all
|
|
* @param int $time A timestamp if you want historic data
|
|
* @return array ('schema' => ( 'fieldlabel' => 'value', ...))
|
|
* @throws StructException
|
|
*/
|
|
public function getData($page, $schema = null, $time = 0)
|
|
{
|
|
$page = cleanID($page);
|
|
if (!$time) {
|
|
$time = time();
|
|
}
|
|
|
|
if (is_null($schema)) {
|
|
$assignments = Assignments::getInstance();
|
|
$schemas = $assignments->getPageAssignments($page, false);
|
|
} else {
|
|
$schemas = [$schema];
|
|
}
|
|
|
|
$result = [];
|
|
foreach ($schemas as $schema) {
|
|
$schemaData = AccessTable::getPageAccess($schema, $page, $time);
|
|
$result[$schema] = $schemaData->getDataArray();
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Saves data for a given page (creates a new revision)
|
|
*
|
|
* If this call succeeds you can assume your data has either been saved or it was
|
|
* not necessary to save it because the data already existed in the wanted form or
|
|
* the given schemas are no longer assigned to that page.
|
|
*
|
|
* Important: You have to check write permissions for the given page before calling
|
|
* this function yourself!
|
|
*
|
|
* this duplicates a bit of code from entry.php - we could also fake post data and let
|
|
* entry handle it, but that would be rather unclean and might be problematic when multiple
|
|
* calls are done within the same request.
|
|
*
|
|
* @param string $page
|
|
* @param array $data ('schema' => ( 'fieldlabel' => 'value', ...))
|
|
* @param string $summary
|
|
* @param string $summary
|
|
* @throws StructException
|
|
* @todo should this try to lock the page?
|
|
*
|
|
*
|
|
*/
|
|
public function saveData($page, $data, $summary = '', $minor = false)
|
|
{
|
|
$page = cleanID($page);
|
|
$summary = trim($summary);
|
|
if (!$summary) $summary = $this->getLang('summary');
|
|
|
|
if (!page_exists($page)) throw new StructException("Page does not exist. You can not attach struct data");
|
|
|
|
// validate and see if anything changes
|
|
$valid = AccessDataValidator::validateDataForPage($data, $page, $errors);
|
|
if ($valid === false) {
|
|
throw new StructException("Validation failed:\n%s", implode("\n", $errors));
|
|
}
|
|
if (!$valid) return; // empty array when no changes were detected
|
|
|
|
$newrevision = self::createPageRevision($page, $summary, $minor);
|
|
|
|
// save the provided data
|
|
$assignments = Assignments::getInstance();
|
|
foreach ($valid as $v) {
|
|
$v->saveData($newrevision);
|
|
// make sure this schema is assigned
|
|
$assignments->assignPageSchema($page, $v->getAccessTable()->getSchema()->getTable());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Save lookup data row
|
|
*
|
|
* @param AccessTable $access the table into which to save the data
|
|
* @param array $data data to be saved in the form of [columnName => 'data']
|
|
*/
|
|
public function saveLookupData(AccessTable $access, $data)
|
|
{
|
|
if (!$access->getSchema()->isEditable()) {
|
|
throw new StructException('lookup save error: no permission for schema');
|
|
}
|
|
$validator = $access->getValidator($data);
|
|
if (!$validator->validate()) {
|
|
throw new StructException("Validation failed:\n%s", implode("\n", $validator->getErrors()));
|
|
}
|
|
if (!$validator->saveData()) {
|
|
throw new StructException('No data saved');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a new page revision with the same page content as before
|
|
*
|
|
* @param string $page
|
|
* @param string $summary
|
|
* @param bool $minor
|
|
* @return int the new revision
|
|
*/
|
|
public static function createPageRevision($page, $summary = '', $minor = false)
|
|
{
|
|
$summary = trim($summary);
|
|
// force a new page revision @see action_plugin_struct_entry::handle_pagesave_before()
|
|
$GLOBALS['struct_plugin_force_page_save'] = true;
|
|
saveWikiText($page, rawWiki($page), $summary, $minor);
|
|
unset($GLOBALS['struct_plugin_force_page_save']);
|
|
$file = wikiFN($page);
|
|
clearstatcache(false, $file);
|
|
return filemtime($file);
|
|
}
|
|
|
|
/**
|
|
* Get info about existing schemas
|
|
*
|
|
* @param string|null $schema the schema to query, null for all
|
|
* @return Schema[]
|
|
* @throws StructException
|
|
*/
|
|
public static function getSchema($schema = null)
|
|
{
|
|
if (is_null($schema)) {
|
|
$schemas = Schema::getAll();
|
|
} else {
|
|
$schemas = [$schema];
|
|
}
|
|
|
|
$result = [];
|
|
foreach ($schemas as $table) {
|
|
$result[$table] = new Schema($table);
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Returns all pages known to the struct plugin
|
|
*
|
|
* That means all pages that have or had once struct data saved
|
|
*
|
|
* @param string|null $schema limit the result to a given schema
|
|
* @return array (page => (schema => true), ...)
|
|
* @throws StructException
|
|
*/
|
|
public function getPages($schema = null)
|
|
{
|
|
$assignments = Assignments::getInstance();
|
|
return $assignments->getPages($schema);
|
|
}
|
|
|
|
/**
|
|
* Returns decoded JSON value or throws exception
|
|
* when passed parameter is not JSON
|
|
*
|
|
* @param string $value
|
|
* @return mixed
|
|
* @throws StructException
|
|
* @throws JsonException
|
|
*/
|
|
public static function decodeJson($value)
|
|
{
|
|
if (empty($value)) return $value;
|
|
if ($value[0] !== '[') throw new StructException('Lookup expects JSON');
|
|
return json_decode($value, null, 512, JSON_THROW_ON_ERROR);
|
|
}
|
|
}
|