xref: /plugin/struct/helper.php (revision ba4522e61dba3c7a23392ee7b5cd4e65a38da6fa)
1<?php
2/**
3 * DokuWiki Plugin struct (Helper Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Andreas Gohr, Michael Große <dokuwiki@cosmocode.de>
7 */
8
9// must be run within Dokuwiki
10use dokuwiki\plugin\struct\meta\AccessTable;
11use dokuwiki\plugin\struct\meta\Assignments;
12use dokuwiki\plugin\struct\meta\Schema;
13use dokuwiki\plugin\struct\meta\AccessTableData;
14use dokuwiki\plugin\struct\meta\StructException;
15use dokuwiki\plugin\struct\meta\Validator;
16
17if(!defined('DOKU_INC')) die();
18
19/**
20 * The public interface for the struct plugin
21 *
22 * 3rd party developers should always interact with struct data through this
23 * helper plugin only. If additionional interface functionality is needed,
24 * it should be added here.
25 *
26 * All functions will throw StructExceptions when something goes wrong.
27 *
28 * Remember to check permissions yourself!
29 */
30class helper_plugin_struct extends DokuWiki_Plugin {
31
32    /**
33     * Get the structured data of a given page
34     *
35     * @param string $page The page to get data for
36     * @param string|null $schema The schema to use null for all
37     * @param int $time A timestamp if you want historic data (0 for now)
38     * @return array ('schema' => ( 'fieldlabel' => 'value', ...))
39     * @throws StructException
40     */
41    public function getData($page, $schema=null, $time=0) {
42        $page = cleanID($page);
43
44        if(is_null($schema)) {
45            $assignments = new Assignments();
46            $schemas = $assignments->getPageAssignments($page, false);
47        } else {
48            $schemas = array($schema);
49        }
50
51        $result = array();
52        foreach($schemas as $schema) {
53            $schemaData = AccessTable::byTableName($schema, $page, $time);
54            $result[$schema] = $schemaData->getDataArray();
55        }
56
57        return $result;
58    }
59
60    /**
61     * Saves data for a given page (creates a new revision)
62     *
63     * If this call succeeds you can assume your data has either been saved or it was
64     * not necessary to save it because the data already existed in the wanted form or
65     * the given schemas are no longer assigned to that page.
66     *
67     * Important: You have to check write permissions for the given page before calling
68     * this function yourself!
69     *
70     * this duplicates a bit of code from entry.php - we could also fake post data and let
71     * entry handle it, but that would be rather unclean and might be problematic when multiple
72     * calls are done within the same request.
73     *
74     * @todo should this try to lock the page?
75     *
76     *
77     * @param string $page
78     * @param array $data ('schema' => ( 'fieldlabel' => 'value', ...))
79     * @param string $summary
80     * @throws StructException
81     */
82    public function saveData($page, $data, $summary='') {
83        $page = cleanID($page);
84        $summary = trim($summary);
85        if(!$summary) $summary = $this->getLang('summary');
86
87        if(!page_exists($page)) throw new StructException("Page does not exist. You can not attach struct data");
88
89        // validate and see if anything changes
90        $validator = new Validator();
91        if(!$validator->validate($data, $page)) {
92            throw new StructException("Validation failed:\n%s", join("\n", $validator->getErrors()));
93        }
94        $data = $validator->getCleanedData();
95        $tosave = $validator->getChangedSchemas();
96        if(!$tosave) return;
97
98        $newrevision = self::createPageRevision($page, $summary);
99
100        // save the provided data
101        $assignments = new Assignments();
102        foreach($tosave as $table) {
103            $schemaData = AccessTable::byTableName($table, $page, $newrevision);
104            $schemaData->saveData($data[$table]);
105            // make sure this schema is assigned
106            $assignments->assignPageSchema($page, $table);
107        }
108    }
109
110    /**
111     * Creates a new page revision with the same page content as before
112     *
113     * @param string $page
114     * @param string $summary
115     * @param bool $minor
116     * @return int the new revision
117     */
118    static public function createPageRevision($page, $summary='', $minor=false) {
119        $summary = trim($summary);
120        // force a new page revision @see action_plugin_struct_entry::handle_pagesave_before()
121        $GLOBALS['struct_plugin_force_page_save'] = true;
122        saveWikiText($page, rawWiki($page), $summary, $minor);
123        unset($GLOBALS['struct_plugin_force_page_save']);
124        $file = wikiFN($page);
125        clearstatcache(false, $file);
126        return filemtime($file);
127    }
128
129    /**
130     * Get info about existing schemas
131     *
132     * @param string|null $schema the schema to query, null for all
133     * @return Schema[]
134     * @throws StructException
135     */
136    public function getSchema($schema=null) {
137        if(is_null($schema)) {
138            $schemas = Schema::getAll();
139        } else {
140            $schemas = array($schema);
141        }
142
143        $result = array();
144        foreach($schemas as $table) {
145            $result[$table] = new Schema($table);
146        }
147        return $result;
148    }
149
150    /**
151     * Returns all pages known to the struct plugin
152     *
153     * That means all pages that have or had once struct data saved
154     *
155     * @param string|null $schema limit the result to a given schema
156     * @return array (page => (schema => true), ...)
157     * @throws StructException
158     */
159    public function getPages($schema=null) {
160        $assignments = new Assignments();
161        return $assignments->getPages($schema);
162    }
163
164}
165