1<?php
2/*
3 * Gallery - a web based photo album viewer and editor
4 * Copyright (C) 2000-2008 Bharat Mediratta
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or (at
9 * your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21/** Possible GalleryComment::publishStatus constants */
22define('COMMENT_PUBLISH_STATUS_PUBLISHED', 0);
23define('COMMENT_PUBLISH_STATUS_UNPUBLISHED', 1);
24define('COMMENT_PUBLISH_STATUS_SPAM', 2);
25
26/**
27 * Comment Module
28 *
29 * This module provides support for adding comments to items
30 *
31 * @package Comment
32 * @author Bharat Mediratta <bharat@menalto.com>
33 * @version $Revision: 18172 $
34 */
35class CommentModule extends GalleryModule {
36
37    function CommentModule() {
38	global $gallery;
39
40	$this->setId('comment');
41	$this->setName($gallery->i18n('Comments'));
42	$this->setDescription($gallery->i18n('User commenting system'));
43	$this->setVersion('1.1.14'); /* Update upgrade() function below too */
44	$this->_templateVersion = 1;
45	$this->setGroup('data', $gallery->i18n('Extra Data'));
46	$this->setCallbacks('getItemLinks|getItemSummaries|' .
47			    'getSiteAdminViews|getItemAdminViews');
48	$this->setRequiredCoreApi(array(7, 41));
49	$this->setRequiredModuleApi(array(3, 9));
50    }
51
52    /**
53     * @see GalleryModule::upgrade
54     */
55    function upgrade($currentVersion) {
56	global $gallery;
57	$storage =& $gallery->getStorage();
58
59	if (!isset($currentVersion)) {
60	    $currentVersion = '0';
61	} else if (version_compare($currentVersion, '0.9.6', '<=')
62		|| substr($currentVersion, 0, 4) == '0.81') {
63	    /* Instead of enumerating all previous versions... */
64	    $currentVersion = '0.9.6';
65	}
66
67	switch ($currentVersion) {
68	case '0':
69	    /* Initial install.  Register our permissions */
70	    $permissions[] = array('add', $gallery->i18n('[comment] Add comments'), 0, array());
71	    $permissions[] = array('edit', $gallery->i18n('[comment] Edit comments'), 0, array());
72	    $permissions[] = array('delete', $gallery->i18n('[comment] Delete comments'),
73				   0, array());
74	     $permissions[] = array('view', $gallery->i18n('[comment] View comments'), 0, array());
75	     $permissions[] = array('all', $gallery->i18n('[comment] All access'),
76		 GALLERY_PERMISSION_COMPOSITE,
77		 array('comment.add', 'comment.edit', 'comment.delete', 'comment.view'));
78	     foreach ($permissions as $p) {
79		$ret = GalleryCoreApi::registerPermission($this->getId(),
80							  'comment.' . $p[0],
81							  $p[1], $p[2], $p[3]);
82		if ($ret) {
83		    return $ret;
84		}
85	     }
86
87	     foreach (array('comments.show' => 10, 'comments.latest' => 1,
88			    'comments.moderate' => 0, 'validation.level' => 'HIGH')
89		     as $key => $value) {
90		$ret = $this->setParameter($key, $value);
91		if ($ret) {
92		    return $ret;
93		}
94	    }
95	    break;
96
97	case '0.9.6':
98	    /*
99	     * Remove comment.search permission included in older module versions.
100	     * As this is a composite permission we can simply remove its entry in the
101	     * PermissionSet table and not touch any item permissions.
102	     */
103	    $ret = GalleryCoreApi::removeMapEntry(
104		'GalleryPermissionSetMap',
105		array('module' => 'comment', 'permission' => 'comment.search'));
106	    if ($ret) {
107		return $ret;
108	    }
109
110	case '0.9.7':
111	case '1.0.0':
112	    $ret = $storage->configureStore($this->getId(), array('GalleryComment:1.0'));
113	    if ($ret) {
114		return $ret;
115	    }
116
117	case '1.0.1':
118	case '1.0.2':
119	case '1.0.3':
120	case '1.0.4':
121	case '1.0.5':
122	    foreach (array('comments.show' => 10, 'comments.captcha' => 0, 'comments.latest' => 1)
123		     as $key => $value) {
124		$ret = $this->setParameter($key, $value);
125		if ($ret) {
126		    return $ret;
127		}
128	    }
129
130	case '1.0.6':
131	case '1.0.7':
132	    list ($ret, $level) = $this->getParameter('comments.captcha');
133	    if ($ret) {
134		return $ret;
135	    }
136	    $ret = $this->setParameter('validation.level', $level ? 'HIGH' : 'OFF');
137	    if ($ret) {
138		return $ret;
139	    }
140	    $ret = $this->removeParameter('comments.captcha');
141	    if ($ret) {
142		return $ret;
143	    }
144
145	case '1.0.8':
146	case '1.0.9':
147	case '1.1.0':
148	case '1.1.1':
149	    $ret = $storage->configureStore($this->getId(), array('GalleryComment:1.1'));
150	    if ($ret) {
151		return $ret;
152	    }
153
154	case '1.1.2':
155	case '1.1.3':
156	case '1.1.3.1':
157	    /* .mo file migration */
158	case '1.1.3.2':
159	    /* Gallery 2.2.4 security release */
160	case '1.1.4':
161	case '1.1.5':
162	    /* Add Akismet support */
163	    $ret = $storage->configureStore($this->getId(), array('GalleryComment:1.2'));
164	    if ($ret) {
165		return $ret;
166	    }
167	case '1.1.6':
168	    /* Add CommentAddNotification class */
169	case '1.1.7':
170	    /* Refactored to new event registration from core API 7.34 */
171	case '1.1.8':
172	case '1.1.9':
173	    /* Combined YUI libraries into a single utilities.js file */
174	case '1.1.10':
175	case '1.1.11':
176	    /* Add Comment Moderation Queue Support */
177	    $ret = $this->setParameter('comments.moderate', 0);
178	    if ($ret) {
179		return $ret;
180	    }
181
182	case '1.1.12':
183	case '1.1.13':
184
185	case 'end of upgrade path':
186	    /*
187	     * Leave this bogus case at the end of the legitimate case statements so that we
188	     * always properly terminate our upgrade path with a break.
189	     */
190	    break;
191
192	default:
193	    return GalleryCoreApi::error(ERROR_BAD_PLUGIN, __FILE__, __LINE__,
194					 sprintf('Unknown module version %s', $currentVersion));
195	}
196
197	return null;
198    }
199
200    /**
201     * @see GalleryModule::performFactoryRegistrations
202     */
203    function performFactoryRegistrations() {
204	$ret = GalleryCoreApi::registerFactoryImplementation(
205	    'GalleryEventListener', 'GalleryCommentHelper', 'GalleryCommentHelper',
206	    'modules/comment/classes/GalleryCommentHelper.class', 'comment',
207	    array('GalleryEntity::delete', 'GalleryEntity::save'));
208	if ($ret) {
209	    return $ret;
210	}
211
212	$ret = GalleryCoreApi::registerFactoryImplementation(
213	    'GalleryEntity', 'GalleryComment', 'GalleryComment',
214	    'modules/comment/classes/GalleryComment.class', 'comment', null);
215	if ($ret) {
216	    return $ret;
217	}
218
219	$ret = GalleryCoreApi::registerFactoryImplementation(
220	    'GallerySearchInterface_1_0', 'GalleryCommentSearch', 'comment',
221	    'modules/comment/classes/GalleryCommentSearch.class', 'comment', null);
222	if ($ret) {
223	    return $ret;
224	}
225
226	$ret = GalleryCoreApi::registerFactoryImplementation(
227	    'CaptchaAdminOption', 'CommentCaptchaAdminOption', 'CommentCaptchaAdminOption',
228	    'modules/comment/classes/CommentCaptchaAdminOption.class', 'comment', null);
229	if ($ret) {
230	    return $ret;
231	}
232
233	$ret = GalleryCoreApi::registerFactoryImplementation(
234	    'NotificationEvent_1_0', 'CommentAddNotification', 'CommentAddNotification',
235	    'modules/comment/classes/CommentAddNotification.class', 'comment',
236	    array('GalleryEntity::save'));
237	if ($ret) {
238	    return $ret;
239	}
240
241	return null;
242    }
243
244    /**
245     * @see GalleryModule::getModuleEntityTypes
246     */
247    function getModuleEntityTypes() {
248	return array('GalleryComment');
249    }
250
251    /**
252     * @see GalleryModule::getItemLinks
253     */
254    function getItemLinks($items, $wantsDetailedLinks, $permissions) {
255	list ($ret, $showAll) = $this->getParameter('comments.latest');
256	if ($ret) {
257	    return array($ret, null);
258	}
259	$links = array();
260	foreach ($items as $item) {
261	    $itemId = $item->getId();
262	    if (isset($wantsDetailedLinks[$itemId])) {
263		if (isset($permissions[$itemId]['comment.add'])) {
264		    $links[$itemId][] = array(
265			'text' => $this->translate('Add Comment'),
266			'params' => array('view' => 'comment.AddComment',
267					  'itemId' => $itemId, 'return' => 1));
268		}
269
270		if ($showAll && isset($permissions[$itemId]['comment.view'])) {
271		    $links[$itemId][] = array(
272			'text' => $this->translate('View Latest Comments'),
273			'params' => array('view' => 'comment.ShowAllComments',
274					  'itemId' => $itemId, 'return' => 1));
275		}
276	    }
277	}
278
279	return array(null, $links);
280    }
281
282    /**
283     * @see GalleryModule::getItemSummaries
284     */
285    function getItemSummaries($items, $permissions, &$template) {
286	$ids = array();
287	foreach ($items as $item) {
288	    $ids[] = $item->getId();
289	}
290
291	GalleryCoreApi::requireOnce('modules/comment/classes/GalleryCommentHelper.class');
292	list ($ret, $commentCounts) = GalleryCommentHelper::fetchCommentCounts($ids);
293	if ($ret) {
294	    return array($ret, null);
295	}
296
297	$summaries = array();
298	foreach ($items as $item) {
299	    $message = array();
300
301	    if (isset($permissions[$item->getId()]['comment.view'])) {
302		if (!empty($commentCounts[$item->getId()])) {
303		    $summaries[$item->getId()] =
304			$this->translate(array('text' => 'Comments: %d',
305					       'arg1' => $commentCounts[$item->getId()]));
306		}
307	    }
308	}
309
310	return array(null, $summaries);
311    }
312
313    /**
314     * @see GalleryModule::getItemAdminViews
315     */
316    function getItemAdminViews($item) {
317	$views = array();
318	list ($ret, $permissions) = GalleryCoreApi::getPermissions($item->getId());
319	if ($ret) {
320	    return array($ret, null);
321	}
322
323	if (isset($permissions['comment.edit']) ||
324	    isset($permissions['comment.delete']) ||
325	    isset($permissions['comment.view'])) {
326		$views[] = array('name' => $this->translate('View Comments'),
327				 'view' => 'comment.ShowComments');
328	}
329
330	return array(null, $views);
331    }
332
333    /**
334     * @see GalleryModule::getSiteAdminViews
335     */
336    function getSiteAdminViews() {
337	return array(null,
338		     array(array('name' => $this->translate('Comments'),
339				 'view' => 'comment.CommentSiteAdmin'),
340			   array('name' => $this->translate('Moderate Comments'),
341				 'view' => 'comment.AdminModerateSpam')));
342    }
343
344    /**
345     * @see GalleryModule::getRewriteRules
346     */
347    function getRewriteRules() {
348	$rules = array();
349
350	$rule = array();
351	$rule['match'] = array('view' => 'comment.AddComment');
352	$rule['pattern'] = 'c/add/%itemId%.html';
353	$rule['comment'] = $this->translate('Add Comment');
354	$rules[] = $rule;
355
356	$rule = array();
357	$rule['match'] = array('view' => 'comment.ShowAllComments');
358	$rule['pattern'] = 'c/view/%itemId%.html';
359	$rule['comment'] = $this->translate('View Comments');
360	$rules[] = $rule;
361
362	return $rules;
363    }
364}
365?>
366