/mvc/models/wiki
[return to app]1
<?php
2 /**
3 * Manages Wiki data
4 */
5 class wikiModel extends model {
6 /**
7 * Maximum number of search results to return
8 *
9 * @var int
10 */
11 public $searchLimit = 30;
12
13 /**
14 * Maximum length of search result descriptions
15 *
16 * @var int
17 */
18 public $maxSearchResultDescriptionLength = 200;
19
20 /**
21 * Establish the base location of the wiki
22 *
23 * @return string
24 */
25 protected function _getController() {
26 $return = mvc::$controller;
27 if (mvc::$action != 'index') {
28 $return .= '/' . mvc::$action;
29 }
30 return $return;
31 }
32
33 /**
34 * Retrieve the page data
35 *
36 * @param int $version Optional - if ommitted then most recent version will be used
37 * @return array
38 */
39 public function select($version = null) {
40 $sqlWhere = ' where controller=' . $this->db->cleanString($this->_getController())
41 . ' and wikiaction=' . $this->db->cleanString(mvc::$params[0]);
42 $sql = 'select title, body, keywords, description'
43 . (!$version ? ' from wikicache' : ', comments from wikilog') . $sqlWhere;
44 if ($version) {
45 $sql .= ' and version=' . $this->db->cleanString($version);
46 }
47 $res = $this->db->query($sql);
48 if (!$res) {
49 $this->initializeDb();
50 $res = $this->db->query($sql);
51 }
52 $row = $res->fetch_assoc();
53 if ($row) {
54 $return = array('title' => $row['title'], 'body' => $row['body']);
55 $return['head']['meta']['keywords'] = $row['keywords'];
56 $return['head']['meta']['description'] = $row['description'];
57 if ($version) {
58 $return['comments'] = $row['comments'];
59 }
60 } else {
61 $return = array('title' => '', 'body' => '', 'returncode' => 404);
62 $sql = 'select version from wikilog ' . $sqlWhere . ' limit 1';
63 $res = $this->db->query($sql);
64 $return['hasHistory'] = $res->fetch_assoc();
65 }
66 return $return;
67 }
68
69 /**
70 * Searches the wiki documents
71 *
72 * @param string $keyword
73 * @return array
74 */
75 public function search($keyword) {
76 $controller = $this->_getController();
77 $keyword = "'%" . $this->db->{db::ESCAPE_STRING}($keyword) . "%'";
78 $dbParents = class_parents($this->db);
79 $isMysql = (isset($dbParents['mysqli']) || isset($dbParents['mysql']));
80 //$this->maxSearchResultDescriptionLength + 150 accounts for up to 150 chars of inline HTML
81 $description = (!$isMysql ? 'description' : "if(description != '', description, substring(body, 1, "
82 . ($this->maxSearchResultDescriptionLength + 150)
83 . ")) as description");
84 $sql = 'select wikiaction, title, ' . $description . ' from wikicache where (body like ' . $keyword
85 . ' or keywords like ' . $keyword . ' or description like ' . $keyword
86 . ') and controller=' . $this->db->cleanString($controller);
87 if ($isMysql) {
88 $sql .= ' limit ' . $this->searchLimit;
89 } else if (isset($dbParents['oci8'])) {
90 $sql .= ' and rownum<=' . $this->searchLimit;
91 } else if (isset($dbParents['mssql'])) {
92 $sql = 'select top ' . $this->searchLimit . substr($sql, 6);
93 }
94 $res = $this->db->query($sql);
95 while ($row = $res->fetch_assoc()) {
96 $row['description'] = str_replace(array("\r\n", "\n", "\r", ' '), ' ',
strip_tags($row['description']));
97 if (strlen($row['description']) > $this->maxSearchResultDescriptionLength) {
98 $row['description'] = substr($row['description'], 0, $this->maxSearchResultDescriptionLength);
99 $lastSpace = strrpos($row['description'], ' ');
100 if ($lastSpace) {
101 $row['description'] = substr($row['description'], 0, $lastSpace);
102 }
103 $row['description'] .= '...';
104 }
105 $return['/' . $controller . '/' . $row['wikiaction']] = $row;
106 }
107 return (isset($return) ? $return : array());
108 }
109
110 /**
111 * Update the wiki page data
112 *
113 * Uses MySQL/SQLite-specific replace-into syntax, other databases will need to adjust syntax
114 *
115 * @param array $data
116 */
117 public function update(array $data) {
118 $controller = $this->db->cleanString($this->_getController());
119 $wikiaction = $this->db->cleanString(mvc::$params[0]);
120 $args = array('table' => 'wikilog',
121 'vals' => array_merge($this->db->cleanString($data), array('controller' => $controller,
122 'wikiaction' => $wikiaction,
123 'version' =>
'current_timestamp')));
124 $sql = $this->db->insertSql($args);
125 $this->db->query($sql);
126
127 $cols = 'controller, wikiaction, title, body, keywords, description';
128 $sql = 'replace into wikicache (' . $cols . ') select ' . $cols . ' from wikilog where controller='
129 . $controller . ' and wikiaction=' . $wikiaction . ' order by version desc limit 1';
130 $this->db->query($sql);
131 }
132
133 /**
134 * Revert the wiki to a different version
135 *
136 * @param string $version database date/time
137 */
138 public function revertToVersion($version) {
139 $data = $this->select($this->_getController(), mvc::$params[0], $version);
140 if ($data) {
141 $data['comments'] = 'Reverted to version: ' . $version;
142 $this->update($data);
143 }
144 }
145
146 /**
147 * Delete the wiki page
148 */
149 public function delete() {
150 $sql = 'delete from wikicache where controller=' . $this->db->cleanString($this->_getController())
151 . ' and wikiaction=' . $this->db->cleanString(mvc::$params[0]);
152 $this->db->query($sql);
153 }
154
155 /**
156 * Retrieve the list of changes made to a wiki page
157 *
158 * @return array
159 */
160 public function getHistory() {
161 $sql = 'select version, comments from wikilog where controller='
162 . $this->db->cleanString($this->_getController())
163 . ' and wikiaction=' . $this->db->cleanString(mvc::$params[0])
164 . ' order by version desc';
165 $res = $this->db->query($sql);
166 while ($row = $res->fetch_assoc()) {
167 $return[$row['version']] = $row['comments'];
168 }
169 return (isset($return) ? $return : array());
170 }
171
172 /**
173 * builds database tables automatically upon first usage
174 *
175 * If your database does not support the datetime and text column types then you will need to adjust this
method.
176 * Oracle users may also swap varchar with varchar2
177 */
178 public function initializeDb() {
179 $cols = 'controller varchar(100) not null,
180 wikiaction varchar(50) not null,
181 title varchar(255) not null,
182 body text not null,
183 keywords varchar(255) not null,
184 description varchar(255) not null,';
185
186 $sql = 'create table wikicache (' . $cols . ' primary key(controller, wikiaction))';
187 $this->db->query($sql);
188
189 $sql = 'create table wikilog (' . $cols . '
190 version datetime not null,
191 comments varchar(255) null,
192 primary key(controller, wikiaction, version))';
193 $this->db->query($sql);
194 }
195 }