Commit 0cd525ef938471d6c30477fddbd7b3cf7d6367ef

Authored by Jarrett Jordaan
2 parents 59469153 6820c0aa

Merge branch 'edge' of git@github.com:ktgit/knowledgetree into edge

plugins/ktcore/KTWidgets.php
@@ -1113,9 +1113,13 @@ class KTCoreImageWidget extends KTWidget { @@ -1113,9 +1113,13 @@ class KTCoreImageWidget extends KTWidget {
1113 return $res; 1113 return $res;
1114 } 1114 }
1115 1115
1116 - $this->src = $aOptions['src'];  
1117 - $this->alt = $aOptions['alt'];  
1118 - $this->title = $aOptions['title']; 1116 + $this->aOptions['src'] = KTUtil::arrayGet($aOptions, 'src', '');
  1117 + $this->aOptions['alt'] = KTUtil::arrayGet($aOptions, 'alt', '');
  1118 + $this->aOptions['title'] = KTUtil::arrayGet($aOptions, 'title', '');
  1119 + $this->aOptions['width'] = KTUtil::arrayGet($aOptions, 'width', '');
  1120 + $this->aOptions['height'] = KTUtil::arrayGet($aOptions, 'height', '');
  1121 + $this->aOptions['has_width'] = ($this->aOptions['height'] !== null);
  1122 + $this->aOptions['has_height'] = ($this->aOptions['height'] !== null);
1119 1123
1120 } 1124 }
1121 1125
@@ -1146,12 +1150,14 @@ class KTCoreImageSelectWidget extends KTWidget { @@ -1146,12 +1150,14 @@ class KTCoreImageSelectWidget extends KTWidget {
1146 var $sNamespace = 'ktcore.widgets.imageselect'; 1150 var $sNamespace = 'ktcore.widgets.imageselect';
1147 var $sTemplate = 'ktcore/forms/widgets/imageselect'; 1151 var $sTemplate = 'ktcore/forms/widgets/imageselect';
1148 1152
  1153 + var $width;
  1154 + var $height;
  1155 +
1149 function configure($aOptions) { 1156 function configure($aOptions) {
1150 $res = parent::configure($aOptions); 1157 $res = parent::configure($aOptions);
1151 if (PEAR::isError($res)) { 1158 if (PEAR::isError($res)) {
1152 return $res; 1159 return $res;
1153 } 1160 }
1154 -  
1155 } 1161 }
1156 1162
1157 function render() { 1163 function render() {
plugins/ktcore/admin/deletedDocuments.php
@@ -5,32 +5,32 @@ @@ -5,32 +5,32 @@
5 * KnowledgeTree Community Edition 5 * KnowledgeTree Community Edition
6 * Document Management Made Simple 6 * Document Management Made Simple
7 * Copyright (C) 2008, 2009 KnowledgeTree Inc. 7 * Copyright (C) 2008, 2009 KnowledgeTree Inc.
8 - *  
9 - * 8 + *
  9 + *
10 * This program is free software; you can redistribute it and/or modify it under 10 * This program is free software; you can redistribute it and/or modify it under
11 * the terms of the GNU General Public License version 3 as published by the 11 * the terms of the GNU General Public License version 3 as published by the
12 * Free Software Foundation. 12 * Free Software Foundation.
13 - * 13 + *
14 * This program is distributed in the hope that it will be useful, but WITHOUT 14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * details. 17 * details.
18 - * 18 + *
19 * You should have received a copy of the GNU General Public License 19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>. 20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 - *  
22 - * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, 21 + *
  22 + * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco,
23 * California 94120-7775, or email info@knowledgetree.com. 23 * California 94120-7775, or email info@knowledgetree.com.
24 - * 24 + *
25 * The interactive user interfaces in modified source and object code versions 25 * The interactive user interfaces in modified source and object code versions
26 * of this program must display Appropriate Legal Notices, as required under 26 * of this program must display Appropriate Legal Notices, as required under
27 * Section 5 of the GNU General Public License version 3. 27 * Section 5 of the GNU General Public License version 3.
28 - * 28 + *
29 * In accordance with Section 7(b) of the GNU General Public License version 3, 29 * In accordance with Section 7(b) of the GNU General Public License version 3,
30 * these Appropriate Legal Notices must retain the display of the "Powered by 30 * these Appropriate Legal Notices must retain the display of the "Powered by
31 - * KnowledgeTree" logo and retain the original copyright notice. If the display of the 31 + * KnowledgeTree" logo and retain the original copyright notice. If the display of the
32 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices 32 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
33 - * must display the words "Powered by KnowledgeTree" and retain the original 33 + * must display the words "Powered by KnowledgeTree" and retain the original
34 * copyright notice. 34 * copyright notice.
35 * Contributor( s): ______________________________________ 35 * Contributor( s): ______________________________________
36 * 36 *
@@ -51,9 +51,9 @@ class DeletedDocumentsDispatcher extends KTAdminDispatcher { @@ -51,9 +51,9 @@ class DeletedDocumentsDispatcher extends KTAdminDispatcher {
51 var $sHelpPage = 'ktcore/admin/deleted documents.html'; 51 var $sHelpPage = 'ktcore/admin/deleted documents.html';
52 function do_main () { 52 function do_main () {
53 $this->aBreadcrumbs[] = array('url' => $_SERVER['PHP_SELF'], 'name' => _kt('Deleted Documents')); 53 $this->aBreadcrumbs[] = array('url' => $_SERVER['PHP_SELF'], 'name' => _kt('Deleted Documents'));
54 - 54 +
55 $this->oPage->setBreadcrumbDetails(_kt('view')); 55 $this->oPage->setBreadcrumbDetails(_kt('view'));
56 - 56 +
57 $aDocuments =& Document::getList('status_id=' . DELETED); 57 $aDocuments =& Document::getList('status_id=' . DELETED);
58 58
59 if(!empty($aDocuments)){ 59 if(!empty($aDocuments)){
@@ -72,12 +72,12 @@ var $sHelpPage = &#39;ktcore/admin/deleted documents.html&#39;; @@ -72,12 +72,12 @@ var $sHelpPage = &#39;ktcore/admin/deleted documents.html&#39;;
72 }else{ 72 }else{
73 $limit = 9; 73 $limit = 9;
74 } 74 }
75 - 75 +
76 for($i = 0; $i <= $limit; $i++){ 76 for($i = 0; $i <= $limit; $i++){
77 $aDocumentsList[] = $aDocuments[$i]; 77 $aDocumentsList[] = $aDocuments[$i];
78 } 78 }
79 } 79 }
80 - 80 +
81 $oTemplating =& KTTemplating::getSingleton(); 81 $oTemplating =& KTTemplating::getSingleton();
82 $oTemplate = $oTemplating->loadTemplate('ktcore/document/admin/deletedlist'); 82 $oTemplate = $oTemplating->loadTemplate('ktcore/document/admin/deletedlist');
83 $oTemplate->setData(array( 83 $oTemplate->setData(array(
@@ -90,7 +90,7 @@ var $sHelpPage = &#39;ktcore/admin/deleted documents.html&#39;; @@ -90,7 +90,7 @@ var $sHelpPage = &#39;ktcore/admin/deleted documents.html&#39;;
90 )); 90 ));
91 return $oTemplate; 91 return $oTemplate;
92 } 92 }
93 - 93 +
94 function do_branchConfirm() { 94 function do_branchConfirm() {
95 $submit = KTUtil::arrayGet($_REQUEST, 'submit' , array()); 95 $submit = KTUtil::arrayGet($_REQUEST, 'submit' , array());
96 if (array_key_exists('expunge',$submit)) { 96 if (array_key_exists('expunge',$submit)) {
@@ -104,33 +104,33 @@ var $sHelpPage = &#39;ktcore/admin/deleted documents.html&#39;; @@ -104,33 +104,33 @@ var $sHelpPage = &#39;ktcore/admin/deleted documents.html&#39;;
104 } 104 }
105 $this->errorRedirectToMain(_kt('No action specified.')); 105 $this->errorRedirectToMain(_kt('No action specified.'));
106 } 106 }
107 - 107 +
108 function do_confirm_expunge($all = false) { 108 function do_confirm_expunge($all = false) {
109 $this->aBreadcrumbs[] = array('url' => $_SERVER['PHP_SELF'], 'name' => _kt('Deleted Documents')); 109 $this->aBreadcrumbs[] = array('url' => $_SERVER['PHP_SELF'], 'name' => _kt('Deleted Documents'));
110 - 110 +
111 $selected_docs = KTUtil::arrayGet($_REQUEST, 'selected_docs', array()); 111 $selected_docs = KTUtil::arrayGet($_REQUEST, 'selected_docs', array());
112 $full_docs = KTUtil::arrayGet($_REQUEST, 'docIds', array()); 112 $full_docs = KTUtil::arrayGet($_REQUEST, 'docIds', array());
113 - 113 +
114 if($all == true){ 114 if($all == true){
115 $selected_docs = $full_docs; 115 $selected_docs = $full_docs;
116 } 116 }
117 - 117 +
118 $this->oPage->setTitle(sprintf(_kt('Confirm Expunge of %d documents'), count($selected_docs))); 118 $this->oPage->setTitle(sprintf(_kt('Confirm Expunge of %d documents'), count($selected_docs)));
119 - 119 +
120 $this->oPage->setBreadcrumbDetails(sprintf(_kt('confirm expunge of %d documents'), count($selected_docs))); 120 $this->oPage->setBreadcrumbDetails(sprintf(_kt('confirm expunge of %d documents'), count($selected_docs)));
121 - 121 +
122 $aDocuments = array(); 122 $aDocuments = array();
123 foreach ($selected_docs as $doc_id) { 123 foreach ($selected_docs as $doc_id) {
124 $oDoc =& Document::get($doc_id); 124 $oDoc =& Document::get($doc_id);
125 - if (PEAR::isError($oDoc) || ($oDoc === false)) { 125 + if (PEAR::isError($oDoc) || ($oDoc === false)) {
126 $this->errorRedirectToMain(_kt('Invalid document id specified. Aborting expunge')); 126 $this->errorRedirectToMain(_kt('Invalid document id specified. Aborting expunge'));
127 } else if ($oDoc->getStatusId() != DELETED) { 127 } else if ($oDoc->getStatusId() != DELETED) {
128 $this->errorRedirectToMain(sprintf(_kt('%s is not a deleted document. Aborting expunge'), $oDoc->getName())); 128 $this->errorRedirectToMain(sprintf(_kt('%s is not a deleted document. Aborting expunge'), $oDoc->getName()));
129 } 129 }
130 $aDocuments[] = $oDoc; 130 $aDocuments[] = $oDoc;
131 } 131 }
132 -  
133 - 132 +
  133 +
134 $oTemplating =& KTTemplating::getSingleton(); 134 $oTemplating =& KTTemplating::getSingleton();
135 $oTemplate = $oTemplating->loadTemplate('ktcore/document/admin/expungeconfirmlist'); 135 $oTemplate = $oTemplating->loadTemplate('ktcore/document/admin/expungeconfirmlist');
136 $oTemplate->setData(array( 136 $oTemplate->setData(array(
@@ -140,47 +140,49 @@ var $sHelpPage = &#39;ktcore/admin/deleted documents.html&#39;; @@ -140,47 +140,49 @@ var $sHelpPage = &#39;ktcore/admin/deleted documents.html&#39;;
140 return $oTemplate; 140 return $oTemplate;
141 } 141 }
142 142
143 - function do_finish_expunge() {  
144 - $selected_docs = KTUtil::arrayGet($_REQUEST, 'selected_docs', array());  
145 - 143 + function do_finish_expunge() {
  144 + $selected_docs = KTUtil::arrayGet($_REQUEST, 'selected_docs', array());
  145 +
146 $aDocuments = array(); 146 $aDocuments = array();
147 foreach ($selected_docs as $doc_id) { 147 foreach ($selected_docs as $doc_id) {
148 $oDoc =& Document::get($doc_id); 148 $oDoc =& Document::get($doc_id);
149 - if (PEAR::isError($oDoc) || ($oDoc === false)) { 149 + if (PEAR::isError($oDoc) || ($oDoc === false)) {
150 $this->errorRedirectToMain(_kt('Invalid document id specified. Aborting expunge')); 150 $this->errorRedirectToMain(_kt('Invalid document id specified. Aborting expunge'));
151 } else if ($oDoc->getStatusId() != DELETED) { 151 } else if ($oDoc->getStatusId() != DELETED) {
152 $this->errorRedirectToMain(sprintf(_kt('%s is not a deleted document. Aborting expunge'), $oDoc->getName())); 152 $this->errorRedirectToMain(sprintf(_kt('%s is not a deleted document. Aborting expunge'), $oDoc->getName()));
153 } 153 }
154 $aDocuments[] = $oDoc; 154 $aDocuments[] = $oDoc;
155 } 155 }
156 - 156 +
157 $this->startTransaction(); 157 $this->startTransaction();
158 $aErrorDocuments = array(); 158 $aErrorDocuments = array();
159 - $aSuccessDocuments = array(); 159 + $aSuccessDocuments = array();
  160 + $aDeletedDocs = array();
160 161
161 $oStorage =& KTStorageManagerUtil::getSingleton(); 162 $oStorage =& KTStorageManagerUtil::getSingleton();
  163 + $oKTTriggerRegistry = KTTriggerRegistry::getSingleton();
162 164
163 foreach ($aDocuments as $oDoc) { 165 foreach ($aDocuments as $oDoc) {
164 // first evaluate the folder for inconsistencies. 166 // first evaluate the folder for inconsistencies.
165 $oFolder = Folder::get($oDoc->getFolderID()); 167 $oFolder = Folder::get($oDoc->getFolderID());
166 if (PEAR::isError($oFolder)) { $oDoc->setFolderId(1); $oDoc->update(); } 168 if (PEAR::isError($oFolder)) { $oDoc->setFolderId(1); $oDoc->update(); }
167 - 169 +
168 if (!$oStorage->expunge($oDoc)) { $aErrorDocuments[] = $oDoc->getDisplayPath(); } 170 if (!$oStorage->expunge($oDoc)) { $aErrorDocuments[] = $oDoc->getDisplayPath(); }
169 else { 171 else {
170 $oDocumentTransaction = & new DocumentTransaction($oDoc, _kt('Document expunged'), 'ktcore.transactions.expunge'); 172 $oDocumentTransaction = & new DocumentTransaction($oDoc, _kt('Document expunged'), 'ktcore.transactions.expunge');
171 $oDocumentTransaction->create(); 173 $oDocumentTransaction->create();
172 - 174 +
173 // delete this from the db now 175 // delete this from the db now
174 if (!$oDoc->delete()) { 176 if (!$oDoc->delete()) {
175 - $aErrorDocuments[] = $oDoc->getId(); 177 + $aErrorDocuments[] = $oDoc->getId();
176 } else { 178 } else {
177 // removed succesfully 179 // removed succesfully
178 $aSuccessDocuments[] = $oDoc->getDisplayPath(); 180 $aSuccessDocuments[] = $oDoc->getDisplayPath();
179 - 181 + $aDeletedDocs[] = $oDoc->getId();
  182 +
180 // remove any document data 183 // remove any document data
181 $oDoc->cleanupDocumentData($oDoc->getId()); // silly - why the redundancy? 184 $oDoc->cleanupDocumentData($oDoc->getId()); // silly - why the redundancy?
182 -  
183 - $oKTTriggerRegistry = KTTriggerRegistry::getSingleton(); 185 +
184 $aTriggers = $oKTTriggerRegistry->getTriggers('expunge', 'finalised'); 186 $aTriggers = $oKTTriggerRegistry->getTriggers('expunge', 'finalised');
185 foreach ($aTriggers as $aTrigger) { 187 foreach ($aTriggers as $aTrigger) {
186 $sTrigger = $aTrigger[0]; 188 $sTrigger = $aTrigger[0];
@@ -189,38 +191,50 @@ var $sHelpPage = &#39;ktcore/admin/deleted documents.html&#39;; @@ -189,38 +191,50 @@ var $sHelpPage = &#39;ktcore/admin/deleted documents.html&#39;;
189 'document' => $oDoc, 191 'document' => $oDoc,
190 ); 192 );
191 $oTrigger->setInfo($aInfo); 193 $oTrigger->setInfo($aInfo);
192 - $ret = $oTrigger->finalised(); 194 + $ret = $oTrigger->finalised();
193 } 195 }
194 } 196 }
195 } 197 }
196 } 198 }
197 $this->commitTransaction(); 199 $this->commitTransaction();
  200 +
  201 + $aTriggers = $oKTTriggerRegistry->getTriggers('expunge', 'postValidate');
  202 + foreach ($aTriggers as $aTrigger) {
  203 + $sTrigger = $aTrigger[0];
  204 + $oTrigger = new $sTrigger;
  205 + $aInfo = array(
  206 + 'documents' => $aDeletedDocs,
  207 + );
  208 + $oTrigger->setInfo($aInfo);
  209 + $ret = $oTrigger->postValidate();
  210 + }
  211 +
198 $msg = sprintf(_kt('%d documents expunged.'), count($aSuccessDocuments)); 212 $msg = sprintf(_kt('%d documents expunged.'), count($aSuccessDocuments));
199 if (count($aErrorDocuments) != 0) { $msg .= _kt('Failed to expunge') . ': ' . join(', ', $aErrorDocuments); } 213 if (count($aErrorDocuments) != 0) { $msg .= _kt('Failed to expunge') . ': ' . join(', ', $aErrorDocuments); }
200 $this->successRedirectToMain($msg); 214 $this->successRedirectToMain($msg);
201 } 215 }
202 - 216 +
203 function do_confirm_restore() { 217 function do_confirm_restore() {
204 $this->aBreadcrumbs[] = array('url' => $_SERVER['PHP_SELF'], 'name' => _kt('Deleted Documents')); 218 $this->aBreadcrumbs[] = array('url' => $_SERVER['PHP_SELF'], 'name' => _kt('Deleted Documents'));
205 -  
206 - $selected_docs = KTUtil::arrayGet($_REQUEST, 'selected_docs', array());  
207 - 219 +
  220 + $selected_docs = KTUtil::arrayGet($_REQUEST, 'selected_docs', array());
  221 +
208 $this->oPage->setTitle(sprintf(_kt('Confirm Restore of %d documents'), count($selected_docs))); 222 $this->oPage->setTitle(sprintf(_kt('Confirm Restore of %d documents'), count($selected_docs)));
209 - 223 +
210 $this->oPage->setBreadcrumbDetails(sprintf(_kt('Confirm Restore of %d documents'), count($selected_docs))); 224 $this->oPage->setBreadcrumbDetails(sprintf(_kt('Confirm Restore of %d documents'), count($selected_docs)));
211 - 225 +
212 $aDocuments = array(); 226 $aDocuments = array();
213 foreach ($selected_docs as $doc_id) { 227 foreach ($selected_docs as $doc_id) {
214 $oDoc =& Document::get($doc_id); 228 $oDoc =& Document::get($doc_id);
215 - if (PEAR::isError($oDoc) || ($oDoc === false)) { 229 + if (PEAR::isError($oDoc) || ($oDoc === false)) {
216 $this->errorRedirectToMain(_kt('Invalid document id specified. Aborting expunge')); 230 $this->errorRedirectToMain(_kt('Invalid document id specified. Aborting expunge'));
217 } else if ($oDoc->getStatusId() != DELETED) { 231 } else if ($oDoc->getStatusId() != DELETED) {
218 $this->errorRedirectToMain(sprintf(_kt('%s is not a deleted document. Aborting expunge'), $oDoc->getName())); 232 $this->errorRedirectToMain(sprintf(_kt('%s is not a deleted document. Aborting expunge'), $oDoc->getName()));
219 } 233 }
220 $aDocuments[] = $oDoc; 234 $aDocuments[] = $oDoc;
221 } 235 }
222 -  
223 - 236 +
  237 +
224 $oTemplating =& KTTemplating::getSingleton(); 238 $oTemplating =& KTTemplating::getSingleton();
225 $oTemplate = $oTemplating->loadTemplate('ktcore/document/admin/restoreconfirmlist'); 239 $oTemplate = $oTemplating->loadTemplate('ktcore/document/admin/restoreconfirmlist');
226 $oTemplate->setData(array( 240 $oTemplate->setData(array(
@@ -230,36 +244,36 @@ var $sHelpPage = &#39;ktcore/admin/deleted documents.html&#39;; @@ -230,36 +244,36 @@ var $sHelpPage = &#39;ktcore/admin/deleted documents.html&#39;;
230 return $oTemplate; 244 return $oTemplate;
231 } 245 }
232 246
233 - function do_finish_restore() {  
234 - $selected_docs = KTUtil::arrayGet($_REQUEST, 'selected_docs', array());  
235 - 247 + function do_finish_restore() {
  248 + $selected_docs = KTUtil::arrayGet($_REQUEST, 'selected_docs', array());
  249 +
236 $aDocuments = array(); 250 $aDocuments = array();
237 foreach ($selected_docs as $doc_id) { 251 foreach ($selected_docs as $doc_id) {
238 $oDoc =& Document::get($doc_id); 252 $oDoc =& Document::get($doc_id);
239 - if (PEAR::isError($oDoc) || ($oDoc === false)) { 253 + if (PEAR::isError($oDoc) || ($oDoc === false)) {
240 $this->errorRedirectToMain(_kt('Invalid document id specified. Aborting restore')); 254 $this->errorRedirectToMain(_kt('Invalid document id specified. Aborting restore'));
241 } else if ($oDoc->getStatusId() != DELETED) { 255 } else if ($oDoc->getStatusId() != DELETED) {
242 $this->errorRedirectToMain(sprintf(_kt('%s is not a deleted document. Aborting restore'), $oDoc->getName())); 256 $this->errorRedirectToMain(sprintf(_kt('%s is not a deleted document. Aborting restore'), $oDoc->getName()));
243 } 257 }
244 $aDocuments[] = $oDoc; 258 $aDocuments[] = $oDoc;
245 } 259 }
246 - 260 +
247 $this->startTransaction(); 261 $this->startTransaction();
248 $aErrorDocuments = array(); 262 $aErrorDocuments = array();
249 - $aSuccessDocuments = array(); 263 + $aSuccessDocuments = array();
250 264
251 $oStorage =& KTStorageManagerUtil::getSingleton(); 265 $oStorage =& KTStorageManagerUtil::getSingleton();
252 266
253 foreach ($aDocuments as $oDoc) { 267 foreach ($aDocuments as $oDoc) {
254 $oFolder = Folder::get($oDoc->getRestoreFolderId()); 268 $oFolder = Folder::get($oDoc->getRestoreFolderId());
255 // move to root if parent no longer exists. 269 // move to root if parent no longer exists.
256 - if (PEAR::isError($oFolder)) {  
257 - $oDoc->setFolderId(1); 270 + if (PEAR::isError($oFolder)) {
  271 + $oDoc->setFolderId(1);
258 $oFolder = Folder::get(1); 272 $oFolder = Folder::get(1);
259 - } else { 273 + } else {
260 $oDoc->setFolderId($oDoc->getRestoreFolderId()); 274 $oDoc->setFolderId($oDoc->getRestoreFolderId());
261 } 275 }
262 - 276 +
263 if ($oStorage->restore($oDoc)) { 277 if ($oStorage->restore($oDoc)) {
264 $oDoc = Document::get($oDoc->getId()); // storage path has changed for most recent object... 278 $oDoc = Document::get($oDoc->getId()); // storage path has changed for most recent object...
265 $oDoc->setStatusId(LIVE); 279 $oDoc->setStatusId(LIVE);
@@ -269,14 +283,14 @@ var $sHelpPage = &#39;ktcore/admin/deleted documents.html&#39;; @@ -269,14 +283,14 @@ var $sHelpPage = &#39;ktcore/admin/deleted documents.html&#39;;
269 $aErrorDocuments[] = $oDoc->getName(); 283 $aErrorDocuments[] = $oDoc->getName();
270 continue; // skip transactions, etc. 284 continue; // skip transactions, etc.
271 } 285 }
272 - 286 +
273 $res = KTPermissionUtil::updatePermissionLookup($oDoc); 287 $res = KTPermissionUtil::updatePermissionLookup($oDoc);
274 - 288 +
275 if (PEAR::isError($res)) { 289 if (PEAR::isError($res)) {
276 $aErrorDocuments[] = $oDoc->getName(); 290 $aErrorDocuments[] = $oDoc->getName();
277 continue; // skip transactions, etc. 291 continue; // skip transactions, etc.
278 } 292 }
279 - 293 +
280 // create a doc-transaction. 294 // create a doc-transaction.
281 // FIXME does this warrant a transaction-type? 295 // FIXME does this warrant a transaction-type?
282 $oTransaction = new DocumentTransaction($oDoc, sprintf(_kt("Restored from deleted state by %s"), $this->oUser->getName()), 'ktcore.transactions.update'); 296 $oTransaction = new DocumentTransaction($oDoc, sprintf(_kt("Restored from deleted state by %s"), $this->oUser->getName()), 'ktcore.transactions.update');
@@ -293,14 +307,14 @@ var $sHelpPage = &#39;ktcore/admin/deleted documents.html&#39;; @@ -293,14 +307,14 @@ var $sHelpPage = &#39;ktcore/admin/deleted documents.html&#39;;
293 $msg = sprintf(_kt('%d documents restored.'), count($aSuccessDocuments)); 307 $msg = sprintf(_kt('%d documents restored.'), count($aSuccessDocuments));
294 if (count($aErrorDocuments) != 0) { $msg .= _kt('Failed to restore') . ': ' . join(', ', $aErrorDocuments); } 308 if (count($aErrorDocuments) != 0) { $msg .= _kt('Failed to restore') . ': ' . join(', ', $aErrorDocuments); }
295 $this->successRedirectToMain($msg); 309 $this->successRedirectToMain($msg);
296 - }  
297 - 310 + }
  311 +
298 function getRestoreLocationFor($oDocument) { 312 function getRestoreLocationFor($oDocument) {
299 - $iFolderId = $oDocument->getRestoreFolderId(); 313 + $iFolderId = $oDocument->getRestoreFolderId();
300 $oFolder = Folder::get($iFolderId); 314 $oFolder = Folder::get($iFolderId);
301 - 315 +
302 if (PEAR::isError($oFolder)) { 316 if (PEAR::isError($oFolder)) {
303 - return _kt('Original folder no longer exists. Document will be restored in the root folder.'); 317 + return _kt('Original folder no longer exists. Document will be restored in the root folder.');
304 } else { 318 } else {
305 $aCrumbs = KTBrowseUtil::breadcrumbsForFolder($oFolder); 319 $aCrumbs = KTBrowseUtil::breadcrumbsForFolder($oFolder);
306 $aParts = array(); 320 $aParts = array();
plugins/ktcore/admin/manageBranding.php
@@ -52,6 +52,7 @@ class ManageBrandDispatcher extends KTAdminDispatcher { @@ -52,6 +52,7 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
52 52
53 private $maxLogoWidth = 313; 53 private $maxLogoWidth = 313;
54 private $maxLogoHeight = 50; 54 private $maxLogoHeight = 50;
  55 + public $supportedTypes = array('gif', 'png', 'pjpeg', 'jpe', 'jpeg', 'jpg', 'jfif', 'jfif-tbnl');
55 56
56 function check() { 57 function check() {
57 58
@@ -104,7 +105,7 @@ class ManageBrandDispatcher extends KTAdminDispatcher { @@ -104,7 +105,7 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
104 105
105 $aVocab['crop'] = 'Crop - Cut out a selection'; 106 $aVocab['crop'] = 'Crop - Cut out a selection';
106 $aVocab['scale'] = 'Scale - Stretch or Shrink to fit'; 107 $aVocab['scale'] = 'Scale - Stretch or Shrink to fit';
107 - $aVocab['nothing'] = 'Don\'t do anything'; 108 + $aVocab['nothing'] = 'Don\'t do anything <span class="descriptiveText">(My image has the correct dimensions)</span>';
108 109
109 //Adding document type lookup widget 110 //Adding document type lookup widget
110 $widgets[] = $oWF->get('ktcore.widgets.selection',array( 111 $widgets[] = $oWF->get('ktcore.widgets.selection',array(
@@ -117,7 +118,7 @@ class ManageBrandDispatcher extends KTAdminDispatcher { @@ -117,7 +118,7 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
117 'label_method' => 'getName', 118 'label_method' => 'getName',
118 'simple_select' => true, 119 'simple_select' => true,
119 )); 120 ));
120 - 121 +
121 $oForm->setWidgets($widgets); 122 $oForm->setWidgets($widgets);
122 $oForm->setValidators($validators); 123 $oForm->setValidators($validators);
123 124
@@ -306,11 +307,14 @@ class ManageBrandDispatcher extends KTAdminDispatcher { @@ -306,11 +307,14 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
306 307
307 $logoFileName = 'var'.DIRECTORY_SEPARATOR.'branding'.DIRECTORY_SEPARATOR.'logo'.DIRECTORY_SEPARATOR.$logoFileName; 308 $logoFileName = 'var'.DIRECTORY_SEPARATOR.'branding'.DIRECTORY_SEPARATOR.'logo'.DIRECTORY_SEPARATOR.$logoFileName;
308 309
309 - // Adding the Image Crop Widget 310 + // Adding the Image Widget
310 $widgets[] = $oWF->get('ktcore.widgets.image', array( 311 $widgets[] = $oWF->get('ktcore.widgets.image', array(
311 'label' => _kt('Logo Preview'), 312 'label' => _kt('Logo Preview'),
312 'name' => $logoFileName, // title and alt attributes get set to this. 313 'name' => $logoFileName, // title and alt attributes get set to this.
313 'value' => $logoFileName, 314 'value' => $logoFileName,
  315 + 'width' => $this->maxLogoWidth,
  316 + 'height' => $this->maxLogoHeight,
  317 + 'widgetwidth' => 20
314 )); 318 ));
315 319
316 // Adding the Hidden FileName Input String 320 // Adding the Hidden FileName Input String
@@ -366,6 +370,21 @@ class ManageBrandDispatcher extends KTAdminDispatcher { @@ -366,6 +370,21 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
366 370
367 //Changing to logo.jpg (Need to preserve extention as GD requires the exact image type to work) 371 //Changing to logo.jpg (Need to preserve extention as GD requires the exact image type to work)
368 $ext = end(explode('.', $logoFileName)); 372 $ext = end(explode('.', $logoFileName));
  373 +
  374 + $type = $_FILES['_kt_attempt_unique_file']['type'];
  375 +
  376 + //Stage 1 filename based ext check:
  377 + if (!$this->isSupportedExtension($ext)) {
  378 + //If filename based extension isn't supported will try and guess based on mime type
  379 + $default->log->error("Stage 1: Unsupported file type: '".$type."' for file: ':".$_FILES['_kt_attempt_unique_file']['name']."'");
  380 + $ext = $this->getExtension($type);
  381 +
  382 + if (!$this->isSupportedExtension($ext)) {
  383 + $default->log->error("Unsupported file type: '".$type."' for file: ':".$_FILES['_kt_attempt_unique_file']['name']."'");
  384 + $this->errorRedirectToMain("The file you tried to upload is not supported.");
  385 + }
  386 + }
  387 +
369 $logoFileName = 'logo_tmp_'.md5(Date('ymd-hms')).'.'.$ext; //Fighting the browser cache here 388 $logoFileName = 'logo_tmp_'.md5(Date('ymd-hms')).'.'.$ext; //Fighting the browser cache here
370 $logoFile = $logoDir.DIRECTORY_SEPARATOR.$logoFileName; 389 $logoFile = $logoDir.DIRECTORY_SEPARATOR.$logoFileName;
371 390
@@ -373,7 +392,7 @@ class ManageBrandDispatcher extends KTAdminDispatcher { @@ -373,7 +392,7 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
373 if (file_exists($logoFile)) { 392 if (file_exists($logoFile)) {
374 @unlink($logoFile); 393 @unlink($logoFile);
375 } 394 }
376 - 395 +
377 //TODO: Test Upload Failure by setting the $logoFile to '' 396 //TODO: Test Upload Failure by setting the $logoFile to ''
378 397
379 if(!move_uploaded_file($_FILES['_kt_attempt_unique_file']['tmp_name'], $logoFile)) { 398 if(!move_uploaded_file($_FILES['_kt_attempt_unique_file']['tmp_name'], $logoFile)) {
@@ -388,8 +407,14 @@ class ManageBrandDispatcher extends KTAdminDispatcher { @@ -388,8 +407,14 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
388 407
389 switch ($resizeMethod) { 408 switch ($resizeMethod) {
390 case 'crop': 409 case 'crop':
391 - $cropLogoForm = $this->getCropLogoForm($logoFileName);  
392 - return $cropLogoForm->render(); 410 + if ($this->isImageCroppable($logoFile, $this->maxLogoWith, $this->maxLogoHeight)) {
  411 + $retForm = $this->getCropLogoForm($logoFileName);
  412 + } else {
  413 + $_SESSION['KTErrorMessage'][] = _kt("The image was too small to be cropped.");
  414 + $retForm = $this->getApplyLogoForm($logoFileName);
  415 + }
  416 +
  417 + return $retForm->render();
393 418
394 case 'scale': 419 case 'scale':
395 $type = $_FILES['_kt_attempt_unique_file']['type']; 420 $type = $_FILES['_kt_attempt_unique_file']['type'];
@@ -421,6 +446,82 @@ class ManageBrandDispatcher extends KTAdminDispatcher { @@ -421,6 +446,82 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
421 } 446 }
422 447
423 448
  449 + /**
  450 + * Returns the MIME of the filename, deducted from its extension
  451 + * If the extension is unknown, returns "image/jpeg"
  452 + */
  453 + function getMime($filename)
  454 + {
  455 + $pos = strrpos($filename, '.');
  456 + $extension = "";
  457 + if ($pos !== false) {
  458 + $extension = strtolower(substr($filename, $pos+1));
  459 + }
  460 +
  461 + switch($extension) {
  462 + case 'gif':
  463 + return 'image/gif';
  464 + case 'jfif':
  465 + return 'image/jpeg';
  466 + case 'jfif-tbnl':
  467 + return 'image/jpeg';
  468 + case 'png':
  469 + return 'image/png';
  470 + case 'jpe':
  471 + return 'image/jpeg';
  472 + case 'jpeg':
  473 + return 'image/jpeg';
  474 + case 'jpg':
  475 + return 'image/jpeg';
  476 + default:
  477 + return 'image/jpeg';
  478 + }
  479 + }
  480 +
  481 +
  482 + /**
  483 + * Returns the MIME of the filename, deducted from its extension
  484 + * If the extension is unknown, returns "image/jpeg"
  485 + */
  486 + function getExtension($type)
  487 + {
  488 +
  489 + switch($type) {
  490 + case 'image/gif':
  491 + return 'gif';
  492 + case 'image/jpeg':
  493 + return 'jfif';
  494 + case 'image/jpeg':
  495 + return 'jfif-tbnl';
  496 + case 'image/png':
  497 + return 'png';
  498 + case 'image/jpeg':
  499 + return 'jpe';
  500 + case 'image/jpeg':
  501 + return 'jpeg';
  502 + case 'image/jpeg':
  503 + return 'jpg';
  504 + case 'image/pjpeg':
  505 + return 'jpg';
  506 + default:
  507 + return 'image/jpeg';
  508 + }
  509 + }
  510 +
  511 +
  512 + /**
  513 + * Returns TRUE of the extension is supported
  514 + */
  515 + function isSupportedExtension($extension)
  516 + {
  517 + if (in_array($extension, $this->supportedTypes)) {
  518 + return TRUE;
  519 + }
  520 +
  521 + return FALSE;
  522 + }
  523 +
  524 +
424 /* 525 /*
425 * This method uses the GD library to scale an image. 526 * This method uses the GD library to scale an image.
426 * - Supported images are jpeg, png and gif 527 * - Supported images are jpeg, png and gif
@@ -569,39 +670,60 @@ class ManageBrandDispatcher extends KTAdminDispatcher { @@ -569,39 +670,60 @@ class ManageBrandDispatcher extends KTAdminDispatcher {
569 670
570 } 671 }
571 672
572 -  
573 - /**  
574 - * Returns the MIME of the filename, deducted from its extension  
575 - * If the extension is unknown, returns "image/jpeg" 673 + /*
  674 + * This method is used to determine if the image actually can be cropped
  675 + * - Supported images are jpeg, png and gif
  676 + *
576 */ 677 */
577 - function getMime($filename)  
578 - {  
579 - $pos = strrpos($filename, '.');  
580 - $extension = "";  
581 - if ($pos !== false) {  
582 - $extension = strtolower(substr($filename, $pos+1)); 678 + public function isImageCroppable( $origFile, $width, $height) {
  679 + global $default;
  680 +
  681 + //Requires the GD library if not exit gracefully
  682 + if (!extension_loaded('gd')) {
  683 + $default->log->error("The GD library isn't loaded");
  684 + return false;
  685 + }
  686 +
  687 + switch($type) {
  688 + case 'image/jpeg':
  689 + $orig = imagecreatefromjpeg($origFile);
  690 + break;
  691 + case 'image/pjpeg':
  692 + $orig = imagecreatefromjpeg($origFile);
  693 + break;
  694 + case 'image/png':
  695 + $orig = imagecreatefrompng($origFile);
  696 + break;
  697 + case 'image/gif':
  698 + $orig = imagecreatefromgif($origFile);
  699 + break;
  700 + default:
  701 + //Handle Error
  702 + $default->log->error("Tried to determine crop for an unsupported file type: $type");
  703 + return false;
583 } 704 }
584 705
585 - switch($extension) {  
586 - case 'gif':  
587 - return 'image/gif';  
588 - case 'jfif':  
589 - return 'image/jpeg';  
590 - case 'jfif-tbnl':  
591 - return 'image/jpeg';  
592 - case 'png':  
593 - return 'image/png';  
594 - case 'jpe':  
595 - return 'image/jpeg';  
596 - case 'jpeg':  
597 - return 'image/jpeg';  
598 - case 'jpg':  
599 - return 'image/jpeg';  
600 - default:  
601 - return 'image/jpeg'; 706 + if($orig) {
  707 + /*
  708 + * calculate the size of the new image.
  709 + */
  710 + $orig_x = imagesx($orig);
  711 + $orig_y = imagesy($orig);
  712 +
  713 + if (($orig_x > $width) || ($orig_y > $height)) {
  714 + return true;
  715 + }
  716 +
  717 + } else {
  718 + //Handle Error
  719 + $default->log->error("Couldn't obtain a valid GD resource $origFile");
  720 + return false;
602 } 721 }
  722 +
  723 + return true;
603 } 724 }
604 725
  726 +
605 /* 727 /*
606 * This method uses the GD library to crop an image. 728 * This method uses the GD library to crop an image.
607 * - Supported images are jpeg, png and gif 729 * - Supported images are jpeg, png and gif
plugins/ktcore/admin/manageCleanup.php
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 * KnowledgeTree Community Edition 5 * KnowledgeTree Community Edition
6 * Document Management Made Simple 6 * Document Management Made Simple
7 * Copyright (C) 2008, 2009 KnowledgeTree Inc. 7 * Copyright (C) 2008, 2009 KnowledgeTree Inc.
8 - * 8 + *
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify it under 10 * This program is free software; you can redistribute it and/or modify it under
11 * the terms of the GNU General Public License version 3 as published by the 11 * the terms of the GNU General Public License version 3 as published by the
@@ -69,6 +69,8 @@ class ManageCleanupDispatcher extends KTAdminDispatcher { @@ -69,6 +69,8 @@ class ManageCleanupDispatcher extends KTAdminDispatcher {
69 69
70 function do_main() 70 function do_main()
71 { 71 {
  72 + $this->aBreadcrumbs[] = array('url' => $_SERVER['PHP_SELF'], 'name' => _kt('Document Storage Verification'));
  73 + $this->oPage->setTitle(_kt('Document Storage Verification'));
72 74
73 $oForm = new KTForm; 75 $oForm = new KTForm;
74 $oForm->setOptions(array( 76 $oForm->setOptions(array(
@@ -82,7 +84,12 @@ class ManageCleanupDispatcher extends KTAdminDispatcher { @@ -82,7 +84,12 @@ class ManageCleanupDispatcher extends KTAdminDispatcher {
82 } 84 }
83 85
84 86
85 - function do_verify() { 87 + function do_verify()
  88 + {
  89 + $this->aBreadcrumbs[] = array('url' => $_SERVER['PHP_SELF'], 'name' => _kt('Document Storage Verification'));
  90 + $this->oPage->setTitle(_kt('Document Storage Verification'));
  91 + $this->oPage->setBreadcrumbDetails(_kt('verify'));
  92 +
86 global $aFoldersToRemove; 93 global $aFoldersToRemove;
87 global $aFilesToRemove; 94 global $aFilesToRemove;
88 global $aRepoDocumentProblems; 95 global $aRepoDocumentProblems;
plugins/thumbnails/templates/thumbnail_viewlet.smarty
@@ -13,14 +13,16 @@ @@ -13,14 +13,16 @@
13 <div id="thumb_{/literal}{$documentId}{literal}" class="thumb"> 13 <div id="thumb_{/literal}{$documentId}{literal}" class="thumb">
14 <a href='{$url}' rel="lightbox" title="{$title}"> 14 <a href='{$url}' rel="lightbox" title="{$title}">
15 <img id="img{$documentId}" src="{$thumbnail}" {if $height}height="{$height}"{/if} class="lightbox_window"/> 15 <img id="img{$documentId}" src="{$thumbnail}" {if $height}height="{$height}"{/if} class="lightbox_window"/>
  16 + </a>
16 </div> 17 </div>
17 {else} 18 {else}
18 - <a href='{$url}' target='_blank'>  
19 - <img src="{$thumbnail}" {if $height}height="{$height}"{/if}/>  
20 - {/if}  
21 -  
22 - {if $url}  
23 - </a> 19 + {if $url}
  20 + <a href='{$url}' target='_blank'>
  21 + <img src="{$thumbnail}" {if $height}height="{$height}"{/if}/>
  22 + </a>
  23 + {else}
  24 + <img src="{$thumbnail}" {if $height}height="{$height}"{/if}/>
  25 + {/if}
24 {/if} 26 {/if}
25 </div> 27 </div>
26 </div> 28 </div>
27 \ No newline at end of file 29 \ No newline at end of file
plugins/thumbnails/thumbnails.php
@@ -194,9 +194,12 @@ class thumbnailGenerator extends BaseProcessor @@ -194,9 +194,12 @@ class thumbnailGenerator extends BaseProcessor
194 $thumbnailfile = $thumbnaildir.DIRECTORY_SEPARATOR.$this->document->iId.'.jpg'; 194 $thumbnailfile = $thumbnaildir.DIRECTORY_SEPARATOR.$this->document->iId.'.jpg';
195 //if thumbail dir does not exist, generate one and add an index file to block access 195 //if thumbail dir does not exist, generate one and add an index file to block access
196 if (!file_exists($thumbnaildir)) { 196 if (!file_exists($thumbnaildir)) {
197 - mkdir($thumbnaildir, 0755);  
198 - touch($thumbnaildir.DIRECTORY_SEPARATOR.'index.html');  
199 - file_put_contents($thumbnaildir.DIRECTORY_SEPARATOR.'index.html', 'You do not have permission to access this directory.'); 197 + mkdir($thumbnaildir, 0755);
  198 + }
  199 +
  200 + if (!file_exists($thumbnaildir.DIRECTORY_SEPARATOR.'index.html')) {
  201 + touch($thumbnaildir.DIRECTORY_SEPARATOR.'index.html');
  202 + file_put_contents($thumbnaildir.DIRECTORY_SEPARATOR.'index.html', 'You do not have permission to access this directory.');
200 } 203 }
201 204
202 // if there is no pdf that exists - hop out 205 // if there is no pdf that exists - hop out
@@ -219,8 +222,22 @@ class thumbnailGenerator extends BaseProcessor @@ -219,8 +222,22 @@ class thumbnailGenerator extends BaseProcessor
219 else { 222 else {
220 $cmd = "{$pathConvert} {$srcFile}" . $pageNumber . " -resize 200x200 $thumbnailfile"; 223 $cmd = "{$pathConvert} {$srcFile}" . $pageNumber . " -resize 200x200 $thumbnailfile";
221 } 224 }
222 -  
223 - $result = KTUtil::pexec($cmd); 225 +
  226 + $default->log->debug($cmd);
  227 +
  228 + $output = KTUtil::pexec($cmd);
  229 +
  230 + // Log the output
  231 + if(isset($output['out'])){
  232 + $out = $output['out'];
  233 + if(is_array($out)){
  234 + $out = array_pop($out);
  235 + }
  236 + if(strpos($out, 'ERROR') === 0){
  237 + $default->log->error('InstaView Plugin: error in creation of document thumbnail '.$this->document->iId.': '. $out);
  238 + }
  239 + }
  240 +
224 return true; 241 return true;
225 } 242 }
226 } 243 }
templates/ktcore/forms/widgets/image.smarty
1 - <img id="kt_image_to_crop" {if $has_value} src="{$value}"{/if} alt="{$name}" title="{$name}" /> 1 + <img {if $has_id} id="{$id}" {/if} {if $has_value} src="{$value}"{/if} alt="{$name}" title="{$name}" {if $options.has_width} width="{$options.width}" {/if} {if $options.has_height} height="{$options.height}" {/if}/>