xref: /plugin/struct/helper.php (revision 387ee21016a7563cdd2c65a487aa6c785b1d5de4)
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\AccessDataValidator;
11use dokuwiki\plugin\struct\meta\AccessTable;
12use dokuwiki\plugin\struct\meta\AccessTableLookup;
13use dokuwiki\plugin\struct\meta\Assignments;
14use dokuwiki\plugin\struct\meta\Schema;
15use dokuwiki\plugin\struct\meta\StructException;
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
38     * @return array ('schema' => ( 'fieldlabel' => 'value', ...))
39     * @throws StructException
40     */
41    public function getData($page, $schema = null, $time = 0) {
42        $page = cleanID($page);
43        if (!$time) {
44            $time = time();
45        }
46
47        if(is_null($schema)) {
48            $assignments = Assignments::getInstance();
49            $schemas = $assignments->getPageAssignments($page, false);
50        } else {
51            $schemas = array($schema);
52        }
53
54        $result = array();
55        foreach($schemas as $schema) {
56            $schemaData = AccessTable::byTableName($schema, $page, $time);
57            $result[$schema] = $schemaData->getDataArray();
58        }
59
60        return $result;
61    }
62
63    /**
64     * Saves data for a given page (creates a new revision)
65     *
66     * If this call succeeds you can assume your data has either been saved or it was
67     * not necessary to save it because the data already existed in the wanted form or
68     * the given schemas are no longer assigned to that page.
69     *
70     * Important: You have to check write permissions for the given page before calling
71     * this function yourself!
72     *
73     * this duplicates a bit of code from entry.php - we could also fake post data and let
74     * entry handle it, but that would be rather unclean and might be problematic when multiple
75     * calls are done within the same request.
76     *
77     * @todo should this try to lock the page?
78     *
79     *
80     * @param string $page
81     * @param array $data ('schema' => ( 'fieldlabel' => 'value', ...))
82     * @param string $summary
83     * @param string $summary
84     * @throws StructException
85     */
86    public function saveData($page, $data, $summary = '', $minor = false)
87    {
88        $page = cleanID($page);
89        $summary = trim($summary);
90        if(!$summary) $summary = $this->getLang('summary');
91
92        if(!page_exists($page)) throw new StructException("Page does not exist. You can not attach struct data");
93
94        // validate and see if anything changes
95        $valid = AccessDataValidator::validateDataForPage($data, $page, $errors);
96        if($valid === false) {
97            throw new StructException("Validation failed:\n%s", join("\n", $errors));
98        }
99        if(!$valid) return; // empty array when no changes were detected
100
101        $newrevision = self::createPageRevision($page, $summary, $minor);
102
103        // save the provided data
104        $assignments = Assignments::getInstance();
105        foreach($valid as $v) {
106            $v->saveData($newrevision);
107            // make sure this schema is assigned
108            $assignments->assignPageSchema($page, $v->getAccessTable()->getSchema()->getTable());
109        }
110    }
111
112    /**
113     * Save lookup data row
114     *
115     * @param AccessTable        $access the table into which to save the data
116     * @param array             $data   data to be saved in the form of [columnName => 'data']
117     */
118    public function saveLookupData(AccessTable $access, $data)
119    {
120        if(!$access->getSchema()->isEditable()) {
121            throw new StructException('lookup save error: no permission for schema');
122        }
123        $validator = $access->getValidator($data);
124        if(!$validator->validate()) {
125            throw new StructException("Validation failed:\n%s", implode("\n", $validator->getErrors()));
126        }
127        if(!$validator->saveData()) {
128            throw new StructException('No data saved');
129        }
130    }
131
132    /**
133     * Creates a new page revision with the same page content as before
134     *
135     * @param string $page
136     * @param string $summary
137     * @param bool $minor
138     * @return int the new revision
139     */
140    static public function createPageRevision($page, $summary = '', $minor = false) {
141        $summary = trim($summary);
142        // force a new page revision @see action_plugin_struct_entry::handle_pagesave_before()
143        $GLOBALS['struct_plugin_force_page_save'] = true;
144        saveWikiText($page, rawWiki($page), $summary, $minor);
145        unset($GLOBALS['struct_plugin_force_page_save']);
146        $file = wikiFN($page);
147        clearstatcache(false, $file);
148        return filemtime($file);
149    }
150
151    /**
152     * Get info about existing schemas
153     *
154     * @param string|null $schema the schema to query, null for all
155     * @return Schema[]
156     * @throws StructException
157     */
158    public function getSchema($schema = null) {
159        if(is_null($schema)) {
160            $schemas = Schema::getAll();
161        } else {
162            $schemas = array($schema);
163        }
164
165        $result = array();
166        foreach($schemas as $table) {
167            $result[$table] = new Schema($table);
168        }
169        return $result;
170    }
171
172    /**
173     * Returns all pages known to the struct plugin
174     *
175     * That means all pages that have or had once struct data saved
176     *
177     * @param string|null $schema limit the result to a given schema
178     * @return array (page => (schema => true), ...)
179     * @throws StructException
180     */
181    public function getPages($schema = null) {
182        $assignments = Assignments::getInstance();
183        return $assignments->getPages($schema);
184    }
185
186}
187