146ca39b7SAndreas Gohr<?php 246ca39b7SAndreas Gohr/** 346ca39b7SAndreas Gohr * DokuWiki Plugin struct (Helper Component) 446ca39b7SAndreas Gohr * 546ca39b7SAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 646ca39b7SAndreas Gohr * @author Andreas Gohr, Michael Große <dokuwiki@cosmocode.de> 746ca39b7SAndreas Gohr */ 846ca39b7SAndreas Gohr 946ca39b7SAndreas Gohr// must be run within Dokuwiki 1093ca6f4fSAndreas Gohruse dokuwiki\plugin\struct\meta\AccessDataValidator; 11f411d872SAndreas Gohruse dokuwiki\plugin\struct\meta\AccessTable; 12f0ee60b9SMichael Großeuse dokuwiki\plugin\struct\meta\AccessTableLookup; 13ba766201SAndreas Gohruse dokuwiki\plugin\struct\meta\Assignments; 14ba766201SAndreas Gohruse dokuwiki\plugin\struct\meta\Schema; 15ba766201SAndreas Gohruse dokuwiki\plugin\struct\meta\StructException; 1646ca39b7SAndreas Gohr 1746ca39b7SAndreas Gohrif(!defined('DOKU_INC')) die(); 1846ca39b7SAndreas Gohr 1946ca39b7SAndreas Gohr/** 2046ca39b7SAndreas Gohr * The public interface for the struct plugin 2146ca39b7SAndreas Gohr * 227dac04ffSAndreas Gohr * 3rd party developers should always interact with struct data through this 237dac04ffSAndreas Gohr * helper plugin only. If additionional interface functionality is needed, 247dac04ffSAndreas Gohr * it should be added here. 2546ca39b7SAndreas Gohr * 2646ca39b7SAndreas Gohr * All functions will throw StructExceptions when something goes wrong. 277dac04ffSAndreas Gohr * 287dac04ffSAndreas Gohr * Remember to check permissions yourself! 2946ca39b7SAndreas Gohr */ 3046ca39b7SAndreas Gohrclass helper_plugin_struct extends DokuWiki_Plugin { 3146ca39b7SAndreas Gohr 3246ca39b7SAndreas Gohr /** 3346ca39b7SAndreas Gohr * Get the structured data of a given page 3446ca39b7SAndreas Gohr * 3546ca39b7SAndreas Gohr * @param string $page The page to get data for 3646ca39b7SAndreas Gohr * @param string|null $schema The schema to use null for all 37*387ee210SAnna Dabrowska * @param int $time A timestamp if you want historic data 3846ca39b7SAndreas Gohr * @return array ('schema' => ( 'fieldlabel' => 'value', ...)) 3946ca39b7SAndreas Gohr * @throws StructException 4046ca39b7SAndreas Gohr */ 4146ca39b7SAndreas Gohr public function getData($page, $schema = null, $time = 0) { 427dac04ffSAndreas Gohr $page = cleanID($page); 43*387ee210SAnna Dabrowska if (!$time) { 44*387ee210SAnna Dabrowska $time = time(); 45*387ee210SAnna Dabrowska } 4646ca39b7SAndreas Gohr 477dac04ffSAndreas Gohr if(is_null($schema)) { 48025cb9daSAndreas Gohr $assignments = Assignments::getInstance(); 497dac04ffSAndreas Gohr $schemas = $assignments->getPageAssignments($page, false); 507dac04ffSAndreas Gohr } else { 517dac04ffSAndreas Gohr $schemas = array($schema); 527dac04ffSAndreas Gohr } 537dac04ffSAndreas Gohr 547dac04ffSAndreas Gohr $result = array(); 557dac04ffSAndreas Gohr foreach($schemas as $schema) { 56f411d872SAndreas Gohr $schemaData = AccessTable::byTableName($schema, $page, $time); 570dd23cefSAndreas Gohr $result[$schema] = $schemaData->getDataArray(); 587dac04ffSAndreas Gohr } 597dac04ffSAndreas Gohr 607dac04ffSAndreas Gohr return $result; 6146ca39b7SAndreas Gohr } 6246ca39b7SAndreas Gohr 6346ca39b7SAndreas Gohr /** 6446ca39b7SAndreas Gohr * Saves data for a given page (creates a new revision) 6546ca39b7SAndreas Gohr * 667dac04ffSAndreas Gohr * If this call succeeds you can assume your data has either been saved or it was 677dac04ffSAndreas Gohr * not necessary to save it because the data already existed in the wanted form or 687dac04ffSAndreas Gohr * the given schemas are no longer assigned to that page. 697dac04ffSAndreas Gohr * 707dac04ffSAndreas Gohr * Important: You have to check write permissions for the given page before calling 717dac04ffSAndreas Gohr * this function yourself! 727dac04ffSAndreas Gohr * 737dac04ffSAndreas Gohr * this duplicates a bit of code from entry.php - we could also fake post data and let 747dac04ffSAndreas Gohr * entry handle it, but that would be rather unclean and might be problematic when multiple 757dac04ffSAndreas Gohr * calls are done within the same request. 767dac04ffSAndreas Gohr * 777dac04ffSAndreas Gohr * @todo should this try to lock the page? 787dac04ffSAndreas Gohr * 797dac04ffSAndreas Gohr * 8046ca39b7SAndreas Gohr * @param string $page 817dac04ffSAndreas Gohr * @param array $data ('schema' => ( 'fieldlabel' => 'value', ...)) 8246ca39b7SAndreas Gohr * @param string $summary 83178d3992SElan Ruusamäe * @param string $summary 8446ca39b7SAndreas Gohr * @throws StructException 8546ca39b7SAndreas Gohr */ 86178d3992SElan Ruusamäe public function saveData($page, $data, $summary = '', $minor = false) 87178d3992SElan Ruusamäe { 887dac04ffSAndreas Gohr $page = cleanID($page); 897dac04ffSAndreas Gohr $summary = trim($summary); 907dac04ffSAndreas Gohr if(!$summary) $summary = $this->getLang('summary'); 9146ca39b7SAndreas Gohr 927dac04ffSAndreas Gohr if(!page_exists($page)) throw new StructException("Page does not exist. You can not attach struct data"); 937dac04ffSAndreas Gohr 947dac04ffSAndreas Gohr // validate and see if anything changes 9593ca6f4fSAndreas Gohr $valid = AccessDataValidator::validateDataForPage($data, $page, $errors); 9693ca6f4fSAndreas Gohr if($valid === false) { 9793ca6f4fSAndreas Gohr throw new StructException("Validation failed:\n%s", join("\n", $errors)); 987dac04ffSAndreas Gohr } 9993ca6f4fSAndreas Gohr if(!$valid) return; // empty array when no changes were detected 1007dac04ffSAndreas Gohr 101178d3992SElan Ruusamäe $newrevision = self::createPageRevision($page, $summary, $minor); 1027dac04ffSAndreas Gohr 1037dac04ffSAndreas Gohr // save the provided data 104025cb9daSAndreas Gohr $assignments = Assignments::getInstance(); 10593ca6f4fSAndreas Gohr foreach($valid as $v) { 10693ca6f4fSAndreas Gohr $v->saveData($newrevision); 1077dac04ffSAndreas Gohr // make sure this schema is assigned 10893ca6f4fSAndreas Gohr $assignments->assignPageSchema($page, $v->getAccessTable()->getSchema()->getTable()); 1097dac04ffSAndreas Gohr } 11046ca39b7SAndreas Gohr } 11146ca39b7SAndreas Gohr 11246ca39b7SAndreas Gohr /** 11310575566SAnna Dabrowska * Save lookup data row 114ff2afc7cSMichael Große * 1150ceefd5cSAnna Dabrowska * @param AccessTable $access the table into which to save the data 116ff2afc7cSMichael Große * @param array $data data to be saved in the form of [columnName => 'data'] 117ff2afc7cSMichael Große */ 1180ceefd5cSAnna Dabrowska public function saveLookupData(AccessTable $access, $data) 119ff2afc7cSMichael Große { 120ff2afc7cSMichael Große if(!$access->getSchema()->isEditable()) { 121ff2afc7cSMichael Große throw new StructException('lookup save error: no permission for schema'); 122ff2afc7cSMichael Große } 123ff2afc7cSMichael Große $validator = $access->getValidator($data); 124ff2afc7cSMichael Große if(!$validator->validate()) { 125ff2afc7cSMichael Große throw new StructException("Validation failed:\n%s", implode("\n", $validator->getErrors())); 126ff2afc7cSMichael Große } 127ff2afc7cSMichael Große if(!$validator->saveData()) { 128ff2afc7cSMichael Große throw new StructException('No data saved'); 129ff2afc7cSMichael Große } 130ff2afc7cSMichael Große } 131ff2afc7cSMichael Große 132ff2afc7cSMichael Große /** 13313eddb0fSAndreas Gohr * Creates a new page revision with the same page content as before 13413eddb0fSAndreas Gohr * 13513eddb0fSAndreas Gohr * @param string $page 13613eddb0fSAndreas Gohr * @param string $summary 13713eddb0fSAndreas Gohr * @param bool $minor 13813eddb0fSAndreas Gohr * @return int the new revision 13913eddb0fSAndreas Gohr */ 14013eddb0fSAndreas Gohr static public function createPageRevision($page, $summary = '', $minor = false) { 14113eddb0fSAndreas Gohr $summary = trim($summary); 14213eddb0fSAndreas Gohr // force a new page revision @see action_plugin_struct_entry::handle_pagesave_before() 14313eddb0fSAndreas Gohr $GLOBALS['struct_plugin_force_page_save'] = true; 14413eddb0fSAndreas Gohr saveWikiText($page, rawWiki($page), $summary, $minor); 14513eddb0fSAndreas Gohr unset($GLOBALS['struct_plugin_force_page_save']); 14613eddb0fSAndreas Gohr $file = wikiFN($page); 14713eddb0fSAndreas Gohr clearstatcache(false, $file); 14813eddb0fSAndreas Gohr return filemtime($file); 14913eddb0fSAndreas Gohr } 15013eddb0fSAndreas Gohr 15113eddb0fSAndreas Gohr /** 15246ca39b7SAndreas Gohr * Get info about existing schemas 15346ca39b7SAndreas Gohr * 15446ca39b7SAndreas Gohr * @param string|null $schema the schema to query, null for all 1557dac04ffSAndreas Gohr * @return Schema[] 15646ca39b7SAndreas Gohr * @throws StructException 15746ca39b7SAndreas Gohr */ 15846ca39b7SAndreas Gohr public function getSchema($schema = null) { 1597dac04ffSAndreas Gohr if(is_null($schema)) { 1607dac04ffSAndreas Gohr $schemas = Schema::getAll(); 1617dac04ffSAndreas Gohr } else { 1627dac04ffSAndreas Gohr $schemas = array($schema); 1637dac04ffSAndreas Gohr } 16446ca39b7SAndreas Gohr 1657dac04ffSAndreas Gohr $result = array(); 1667dac04ffSAndreas Gohr foreach($schemas as $table) { 1677dac04ffSAndreas Gohr $result[$table] = new Schema($table); 1687dac04ffSAndreas Gohr } 1697dac04ffSAndreas Gohr return $result; 17046ca39b7SAndreas Gohr } 17146ca39b7SAndreas Gohr 17246ca39b7SAndreas Gohr /** 17346ca39b7SAndreas Gohr * Returns all pages known to the struct plugin 17446ca39b7SAndreas Gohr * 17546ca39b7SAndreas Gohr * That means all pages that have or had once struct data saved 17646ca39b7SAndreas Gohr * 17746ca39b7SAndreas Gohr * @param string|null $schema limit the result to a given schema 1787dac04ffSAndreas Gohr * @return array (page => (schema => true), ...) 17946ca39b7SAndreas Gohr * @throws StructException 18046ca39b7SAndreas Gohr */ 18146ca39b7SAndreas Gohr public function getPages($schema = null) { 182025cb9daSAndreas Gohr $assignments = Assignments::getInstance(); 1837dac04ffSAndreas Gohr return $assignments->getPages($schema); 18446ca39b7SAndreas Gohr } 18546ca39b7SAndreas Gohr 18646ca39b7SAndreas Gohr} 187