QvitterPlugin.php 60.1 KB
Newer Older
hannes's avatar
hannes committed
1 2
<?php

3
 /* · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
hannes's avatar
hannes committed
4 5 6 7
  ·                                                                             ·
  ·                                                                             ·
  ·                             Q V I T T E R                                   ·
  ·                                                                             ·
hannes's avatar
hannes committed
8
  ·                      https://git.gnu.io/h2p/Qvitter                         ·
hannes's avatar
hannes committed
9 10 11 12 13 14 15 16 17
  ·                                                                             ·
  ·                                                                             ·
  ·                                 <o)                                         ·
  ·                                  /_////                                     ·
  ·                                 (____/                                      ·
  ·                                          (o<                                ·
  ·                                   o> \\\\_\                                 ·
  ·                                 \\)   \____)                                ·
  ·                                                                             ·
18
  ·                                                                             ·
hannes's avatar
hannes committed
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
  ·                                                                             ·
  ·  Qvitter is free  software:  you can  redistribute it  and / or  modify it  ·
  ·  under the  terms of the GNU Affero General Public License as published by  ·
  ·  the Free Software Foundation,  either version three of the License or (at  ·
  ·  your option) any later version.                                            ·
  ·                                                                             ·
  ·  Qvitter is distributed  in hope that  it will be  useful but  WITHOUT ANY  ·
  ·  WARRANTY;  without even the implied warranty of MERCHANTABILTY or FITNESS  ·
  ·  FOR A PARTICULAR PURPOSE.  See the  GNU Affero General Public License for  ·
  ·  more details.                                                              ·
  ·                                                                             ·
  ·  You should have received a copy of the  GNU Affero General Public License  ·
  ·  along with Qvitter. If not, see <http://www.gnu.org/licenses/>.            ·
  ·                                                                             ·
  ·  Contact h@nnesmannerhe.im if you have any questions.                       ·
34
  ·                                                                             ·
hannes's avatar
hannes committed
35 36
  · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */

mmn's avatar
mmn committed
37 38
const QVITTERDIR = __DIR__;

hannes's avatar
hannes committed
39 40
class QvitterPlugin extends Plugin {

hannes's avatar
hannes committed
41
    protected $hijack_ui = false;
hannes's avatar
hannes committed
42
    protected $qvitter_hide_replies = false;
43

44
	static function settings($setting)
hannes's avatar
hannes committed
45
	{
46

47 48 49 50
 	/* · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
         ·        							     ·
         ·                          S E T T I N G S                          ·
         ·         							     ·
51
         · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */
hannes's avatar
hannes committed
52

hannes's avatar
hannes committed
53
		// THESE SETTINGS CAN BE OVERRIDDEN IN CONFIG.PHP
mmn's avatar
mmn committed
54
		// e.g. $config['site']['qvitter']['enabledbydefault'] = false;
hannes's avatar
hannes committed
55

hannes's avatar
hannes committed
56 57 58 59 60 61
		// ENABLED BY DEFAULT (true/false)
		$settings['enabledbydefault'] = true;

		// DEFAULT BACKGROUND COLOR
		$settings['defaultbackgroundcolor'] = '#f4f4f4';

62 63
		// DEFAULT BACKGROUND IMAGE
		$settings['sitebackground'] = 'img/vagnsmossen.jpg';
64

hannes's avatar
hannes committed
65 66
		// FAVICON PATH (we've used realfavicongenerator.net to generate the icons)
		$settings['favicon_path'] = Plugin::staticPath('Qvitter', '').'img/gnusocial-favicons/';
67

hannes's avatar
hannes committed
68
		// DEFAULT SPRITE
69
		$settings['sprite'] = Plugin::staticPath('Qvitter', '').'img/sprite.png?v=41';
hannes's avatar
hannes committed
70

hannes's avatar
hannes committed
71 72 73
		// DEFAULT LINK COLOR
		$settings['defaultlinkcolor'] = '#0084B4';

74
		// ENABLE DEFAULT WELCOME TEXT
75
		$settings['enablewelcometext'] = true;
76

hannes's avatar
hannes committed
77
		// CUSTOM WELCOME TEXT (overrides the previous setting)
78
		$settings['customwelcometext'] = false;
79 80

// 		Example:
hannes's avatar
hannes committed
81 82
// 		$settings['customwelcometext']['sv'] = '<h1>Välkommen till Quitter.se – en federerad<sup>1</sup> mikrobloggsallmänning!</h1><p>Etc etc...</p>';
// 		$settings['customwelcometext']['en'] = '<h1>Welcome to Quitter.se – a federated microblog common!</h1><p>Etc etc...</p>';
83

hannes's avatar
hannes committed
84 85
		// TIME BETWEEN POLLING
		$settings['timebetweenpolling'] = 5000; // ms
86

hannes's avatar
hannes committed
87 88
		// URL SHORTENER
		$settings['urlshortenerapiurl'] = 'http://qttr.at/yourls-api.php';
hannes's avatar
hannes committed
89
		$settings['urlshortenersignature'] = 'b6afeec983';
90
        $settings['urlshortenerformat'] = 'jsonp'; // if you're using shortener.php you can set this to 'json', which enables you to use YOURLS versions below 1.5.1
91

92 93
		// CUSTOM TERMS OF USE
		$settings['customtermsofuse'] = false;
94

95 96
		// IP ADDRESSES BLOCKED FROM REGISTRATION
		$settings['blocked_ips'] = array();
hannes's avatar
hannes committed
97

hannes's avatar
hannes committed
98 99 100
        // LINKIFY DOMAINS WITHOUT PROTOCOL AS DEFAULT
        $settings['linkify_bare_domains'] = true;

hannes's avatar
hannes committed
101 102

		 /* · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
103
		  ·                                                                   ·
hannes's avatar
hannes committed
104 105
		  ·                (o>                                  >o)           ·
		  ·            \\\\_\                                    /_////       .
106
		  ·             \____)                                  (____/        ·
hannes's avatar
hannes committed
107
		  ·                                                                   ·
108 109 110
		  · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */

		// config.php settings override the settings in this file
111
		$configphpsettings = common_config('site','qvitter') ?: array();
hannes's avatar
hannes committed
112 113
		foreach($configphpsettings as $configphpsetting=>$value) {
			$settings[$configphpsetting] = $value;
hannes's avatar
hannes committed
114
		}
hannes's avatar
hannes committed
115

hannes's avatar
hannes committed
116 117 118
        // set linkify setting
        common_config_set('linkify', 'bare_domains', $settings['linkify_bare_domains']);

hannes's avatar
hannes committed
119
		if(isset($settings[$setting])) {
120
			return $settings[$setting];
hannes's avatar
hannes committed
121 122 123 124
		}
		else {
			return false;
		}
hannes's avatar
hannes committed
125
	}
126 127 128 129 130 131

    public function initialize()
    {
        // show qvitter link in the admin panel
        common_config_append('admin', 'panels', 'qvitteradm');
    }
132

133

hannes's avatar
hannes committed
134 135 136
    function onCheckSchema()
    {
        $schema = Schema::get();
137 138

        // make sure we have a notifications table
hannes's avatar
hannes committed
139
        $schema->ensureTable('qvitternotification', QvitterNotification::schemaDef());
140 141 142 143 144 145 146 147 148 149 150

        // index the url column in the notice table
        $notice_schemadef = $schema->getTableDef('notice');
        if(!isset($notice_schemadef['indexes']['notice_url_idx'])) {
            try {
                $schema->createIndex('notice', 'url');
            } catch (Exception $e) {
                common_log(LOG_ERR, __METHOD__ . ': ' . $e->getMessage());
            }
        }

hannes's avatar
hannes committed
151
        return true;
mmn's avatar
mmn committed
152 153 154 155 156 157
    }

    public function onBeforePluginCheckSchema()
    {
        QvitterNotification::beforeSchemaUpdate();
        return true;
hannes's avatar
hannes committed
158
    }
159

hannes's avatar
hannes committed
160
	// route/reroute urls
hannes's avatar
hannes committed
161 162
    public function onRouterInitialized($m)
    {
163 164 165 166

        $m->connect('api/qvitter/statuses/user_timeline.:format',
                    array('action' => 'ApiQvitterTimelineUser',
                          'format' => '(xml|json|rss|atom|as)'));
hannes's avatar
hannes committed
167 168 169 170 171
		$m->connect(':nickname/mutes',
					array('action' => 'qvitter',
						  'nickname' => Nickname::INPUT_FMT));
        $m->connect('api/qvitter/mutes.json',
					array('action' => 'ApiQvitterMutes'));
172 173 174 175 176 177
        $m->connect('api/qvitter/sandboxed.:format',
                    array('action' => 'ApiQvitterSandboxed',
                          'format' => '(xml|json)'));
        $m->connect('api/qvitter/silenced.:format',
                    array('action' => 'ApiQvitterSilenced',
                          'format' => '(xml|json)'));
hannes's avatar
hannes committed
178 179 180 181
        $m->connect('api/qvitter/sandbox/create.json',
					array('action' => 'ApiQvitterSandboxCreate'));
        $m->connect('api/qvitter/sandbox/destroy.json',
					array('action' => 'ApiQvitterSandboxDestroy'));
182 183
        $m->connect('api/qvitter/silence/create.json',
					array('action' => 'ApiQvitterSilenceCreate'));
hannes's avatar
hannes committed
184 185
        $m->connect('api/qvitter/silence/destroy.json',
					array('action' => 'ApiQvitterSilenceDestroy'));
186
        $m->connect('services/oembed.:format',
hannes's avatar
hannes committed
187 188
                    array('action' => 'apiqvitteroembednotice',
                          'format' => '(xml|json)'));
189 190
        $m->connect('api/qvitter/check_email.json',
					array('action' => 'ApiQvitterCheckEmail'));
hannes's avatar
lists  
hannes committed
191 192 193 194 195 196 197 198 199 200 201 202
        $m->connect('api/qvitter/:nickname/lists/:id/subscribers.json',
                    array('action' => 'ApiQvitterListSubscribers',
                          'nickname' => '[a-zA-Z0-9]+',
                          'id' => '[a-zA-Z0-9]+'));
        $m->connect('api/qvitter/:nickname/lists/:id/members.json',
                    array('action' => 'ApiQvitterListMembers',
                          'nickname' => '[a-zA-Z0-9]+',
                          'id' => '[a-zA-Z0-9]+'));
        $m->connect('api/qvitter/:nickname/lists/:id/statuses.json',
                    array('action' => 'ApiQvitterTimelineList',
                          'nickname' => '[a-zA-Z0-9]+',
                          'id' => '[a-zA-Z0-9]+'));
203 204
        $m->connect('api/qvitter/blocks.json',
					array('action' => 'ApiQvitterBlocks'));
205 206 207 208
        $m->connect('api/qvitter/hello.json',
					array('action' => 'ApiQvitterHello'));
        $m->connect('api/qvitter/mark_all_notifications_as_seen.json',
					array('action' => 'ApiQvitterMarkAllNotificationsAsSeen'));
209 210 211
		$m->connect('api/qvitter/favs_and_repeats/:notice_id.json',
					array('action' => 'ApiFavsAndRepeats'),
					array('notice_id' => '[0-9]+'));
hannes's avatar
hannes committed
212 213 214
		$m->connect('api/statuses/public_and_external_timeline.:format',
					array('action' => 'ApiTimelinePublicAndExternal',
						  'format' => '(xml|json|rss|atom|as)'));
215 216
        $m->connect('api/qvitter/update_bookmarks.json',
					array('action' => 'ApiQvitterUpdateBookmarks'));
217 218
        $m->connect('api/qvitter/set_profile_pref.json',
					array('action' => 'ApiQvitterSetProfilePref'));
219
        $m->connect('api/qvitter/update_link_color.json',
hannes's avatar
hannes committed
220 221 222
					array('action' => 'apiqvitterupdatelinkcolor'));
		$m->connect('api/qvitter/update_background_color.json',
					array('action' => 'apiqvitterupdatebackgroundcolor'));
223
		$m->connect('api/qvitter/checklogin.json',
224
					array('action' => 'apiqvitterchecklogin'));
hannes's avatar
hannes committed
225 226
		$m->connect('api/qvitter/allfollowing/:id.json',
					array('action' => 'apiqvitterallfollowing',
227
						  'id' => Nickname::INPUT_FMT));
228 229
		$m->connect('api/account/update_profile_banner.json',
					array('action' => 'ApiAccountUpdateProfileBanner'));
230 231 232 233 234 235
		$m->connect('api/saved_searches/list.json',
					array('action' => 'ApiSavedSearchesList'));
		$m->connect('api/trends/place.json',
					array('action' => 'ApiTrendsPlace'));
		$m->connect('api/activity/about_me/unread.json',
					array('action' => 'ApiActivityAboutMeUnread'));
236
		$m->connect('api/qvitter/update_background_image.json',
237
					array('action' => 'ApiUpdateBackgroundImage'));
238
		$m->connect('api/qvitter/update_avatar.json',
239
					array('action' => 'ApiUpdateAvatar'));
hannes's avatar
hannes committed
240
		$m->connect('api/qvitter/upload_image.json',
241
					array('action' => 'ApiUploadImage'));
242 243 244
		$m->connect('api/qvitter/external_user_show.json',
					array('action' => 'ApiExternalUserShow'));
		$m->connect('api/qvitter/toggle_qvitter.json',
245
					array('action' => 'ApiToggleQvitter'));
hannes's avatar
hannes committed
246
		$m->connect('api/qvitter/statuses/notifications.json',
247
					array('action' => 'apiqvitternotifications'));
hannes's avatar
hannes committed
248 249
		$m->connect(':nickname/notifications',
					array('action' => 'qvitter',
250
						  'nickname' => Nickname::INPUT_FMT));
hannes's avatar
hannes committed
251 252 253
		$m->connect(':nickname/blocks',
					array('action' => 'qvitter',
						  'nickname' => Nickname::INPUT_FMT));
hannes's avatar
hannes committed
254 255
        $m->connect('settings/qvitter',
                    array('action' => 'qvittersettings'));
hannes's avatar
hannes committed
256
        $m->connect('panel/qvitter',
257
                    array('action' => 'qvitteradminsettings'));
hannes's avatar
hannes committed
258
        $m->connect('main/qlogin',
259
                    array('action' => 'qvitterlogin'));
260 261 262
        $m->connect('api/qvitter/statuses/update.:format',
					array('action' => 'ApiQvitterStatusesUpdate'),
					array('format' => '(xml|json)'));
hannes's avatar
hannes committed
263

264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
		// check if we should reroute UI to qvitter, and which home-stream the user wants (hide-replies or normal)
		$scoped = Profile::current();
		$qvitter_enabled_by_user = 0;
		$qvitter_disabled_by_user = 0;
		if ($scoped instanceof Profile) {
			$qvitter_enabled_by_user = (int)$scoped->getPref('qvitter', 'enable_qvitter', false);
			$qvitter_disabled_by_user = (int)$scoped->getPref('qvitter', 'disable_qvitter', false);
            $this->qvitter_hide_replies = $scoped->getPref('qvitter', 'hide_replies', false);
		}

        // reroute to qvitter if we're logged out and qvitter is enabled by default
        if(static::settings('enabledbydefault') === true && is_null($scoped)) {
            $this->hijack_ui = true;
        }
        // if we're logged in and qvitter is enabled by default, reroute if the user has not disabled qvitter
        elseif(static::settings('enabledbydefault') === true && $qvitter_disabled_by_user == 0){
            $this->hijack_ui = true;
        }
        // if we're logged in, and qvitter is _not_ enabled by default, reroute if the user enabled qvitter
        elseif(static::settings('enabledbydefault') === false && $qvitter_enabled_by_user == 1) {
            $this->hijack_ui = true;
        }


hannes's avatar
hannes committed
288
        if ($this->hijack_ui === true) {
289 290 291 292 293

            // other plugins might want to reroute to qvitter
            Event::handle('QvitterHijackUI', array($m));

            $m->connect('', array('action' => 'qvitter'));
294
			$m->connect('main/all', array('action' => 'qvitter'));
hannes's avatar
hannes committed
295
            $m->connect('main/public', array('action' => 'qvitter'));
296 297
			$m->connect('main/silenced', array('action' => 'qvitter'));
            $m->connect('main/sandboxed', array('action' => 'qvitter'));
298 299
			$m->connect('search/notice', array('action' => 'qvitter'));

hannes's avatar
hannes committed
300
            // if the user wants the twitter style home stream with hidden replies to non-friends
301
            if ($this->qvitter_hide_replies == 1) {
hannes's avatar
hannes committed
302 303 304 305 306
			URLMapperOverwrite::overwrite_variable($m, 'api/statuses/friends_timeline.:format',
									array('action' => 'ApiTimelineFriends'),
									array('format' => '(xml|json|rss|atom|as)'),
									'ApiTimelineFriendsHiddenReplies');
                }
307

hannes's avatar
hannes committed
308 309
			URLMapperOverwrite::overwrite_variable($m, ':nickname',
									array('action' => 'showstream'),
310
									array('nickname' => Nickname::DISPLAY_FMT),
hannes's avatar
hannes committed
311 312 313
									'qvitter');
			URLMapperOverwrite::overwrite_variable($m, ':nickname/',
									array('action' => 'showstream'),
314 315
									array('nickname' => Nickname::DISPLAY_FMT),
									'qvitter');
hannes's avatar
hannes committed
316 317
			URLMapperOverwrite::overwrite_variable($m, ':nickname/all',
									array('action' => 'all'),
318
									array('nickname' => Nickname::DISPLAY_FMT),
hannes's avatar
hannes committed
319 320 321
									'qvitter');
			URLMapperOverwrite::overwrite_variable($m, ':nickname/subscriptions',
									array('action' => 'subscriptions'),
322 323
									array('nickname' => Nickname::DISPLAY_FMT),
									'qvitter');
hannes's avatar
hannes committed
324 325
			URLMapperOverwrite::overwrite_variable($m, ':nickname/subscribers',
									array('action' => 'subscribers'),
326 327
									array('nickname' => Nickname::DISPLAY_FMT),
									'qvitter');
hannes's avatar
hannes committed
328 329
			URLMapperOverwrite::overwrite_variable($m, ':nickname/groups',
									array('action' => 'usergroups'),
330 331
									array('nickname' => Nickname::DISPLAY_FMT),
									'qvitter');
hannes's avatar
hannes committed
332 333
			URLMapperOverwrite::overwrite_variable($m, ':nickname/replies',
									array('action' => 'replies'),
334 335
									array('nickname' => Nickname::DISPLAY_FMT),
									'qvitter');
hannes's avatar
hannes committed
336 337
			URLMapperOverwrite::overwrite_variable($m, ':nickname/favorites',
									array('action' => 'showfavorites'),
338 339
									array('nickname' => Nickname::DISPLAY_FMT),
									'qvitter');
hannes's avatar
hannes committed
340 341
			URLMapperOverwrite::overwrite_variable($m, 'group/:nickname',
									array('action' => 'showgroup'),
342 343
									array('nickname' => Nickname::DISPLAY_FMT),
									'qvitter');
hannes's avatar
hannes committed
344 345
			URLMapperOverwrite::overwrite_variable($m, 'group/:nickname/members',
									array('action' => 'groupmembers'),
346 347
									array('nickname' => Nickname::DISPLAY_FMT),
									'qvitter');
hannes's avatar
lists  
hannes committed
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
			URLMapperOverwrite::overwrite_variable($m, ':nickname/all/:tag',
									array('action' => 'showprofiletag'),
									array('nickname' => Nickname::DISPLAY_FMT,
                                          'tag' => Router::REGEX_TAG),
									'qvitter');
			URLMapperOverwrite::overwrite_variable($m, ':tagger/all/:tag/tagged',
									array('action' => 'peopletagged'),
									array('tagger' => Nickname::DISPLAY_FMT,
                                          'tag' => Router::REGEX_TAG),
									'qvitter');
			URLMapperOverwrite::overwrite_variable($m, ':tagger/all/:tag/subscribers',
									array('action' => 'peopletagsubscribers'),
									array('tagger' => Nickname::DISPLAY_FMT,
                                          'tag' => Router::REGEX_TAG),
									'qvitter');


hannes's avatar
hannes committed
365 366 367 368 369 370 371

			$m->connect('group/:nickname/admins',
						array('action' => 'qvitter'),
						array('nickname' => Nickname::DISPLAY_FMT));

			URLMapperOverwrite::overwrite_variable($m, 'tag/:tag',
									array('action' => 'showstream'),
372 373
									array('tag' => Router::REGEX_TAG),
									'qvitter');
hannes's avatar
hannes committed
374 375
			URLMapperOverwrite::overwrite_variable($m, 'notice/:notice',
									array('action' => 'shownotice'),
376 377
									array('notice' => '[0-9]+'),
									'qvitter');
378 379 380 381
			URLMapperOverwrite::overwrite_variable($m, 'user/:id',
									array('action' => 'userbyid'),
									array('id' => '[0-9]+'),
									'qvitter');
382 383 384 385
			URLMapperOverwrite::overwrite_variable($m, 'conversation/:id',
									array('action' => 'conversation'),
									array('id' => '[0-9]+'),
									'qvitter');
386 387
		}

388
		// if qvitter is opt-out, disable the default register page (if we don't have a valid invitation code)
mmn's avatar
mmn committed
389 390 391
        $valid_code = isset($_POST['code'])
                        ? Invitation::getKV('code', $_POST['code'])
                        : null;
392
		if(self::settings('enabledbydefault') && empty($valid_code)) {
393
			$m->connect('main/register',
394
						array('action' => 'qvitter'));
395
			}
396 397 398 399


		// add user arrays for some urls, to use to build profile cards
		// this way we don't have to request this in a separate http request
400 401 402 403 404 405 406 407
		if(isset($_GET['withuserarray'])) switch (getPath($_REQUEST)) {
		case 'api/statuses/followers.json':
		case 'api/statuses/friends.json':
		case 'api/statusnet/groups/list.json':
		case 'api/statuses/mentions.json':
		case 'api/favorites.json':
		case 'api/statuses/friends_timeline.json':
		case 'api/statuses/user_timeline.json':
408
        case 'api/qvitter/statuses/user_timeline.json':
409

410
			// add logged in user's user array
411
			if (common_logged_in() && !isset($_GET['screen_name']) && !isset($_GET['id'])) {
412
				$profilecurrent = Profile::current();
413 414 415 416
				header('Qvitter-User-Array: '.json_encode($this->qvitterTwitterUserArray($profilecurrent)));
				}

			// add screen_name's user array
417 418 419 420
			elseif(isset($_GET['screen_name']) || isset($_GET['id'])){

                if(isset($_GET['screen_name'])) {
                    $user = User::getKV('nickname', $_GET['screen_name']);
421 422 423
                    if($user instanceof User) {
                        $profile = $user->getProfile();
                        }
424 425
                    }
                elseif(isset($_GET['id'])) {
426
                    $profile = Profile::getKV('id', $_GET['id']);
427 428 429
                    $user = User::getKV('id', $_GET['id']);
                    }

430 431
                if(isset($profile) && $profile instanceof Profile) {
					header('Qvitter-User-Array: '.json_encode($this->qvitterTwitterUserArray($profile)));
432
					}
433
				}
434
			break;
435 436
		 	}

hannes's avatar
hannes committed
437
    }
438 439


440 441 442 443
    /**
     * Add script to default ui, to be able to toggle Qvitter with one click
     *
     * @return boolean hook return
444
     */
445 446 447

    function onEndShowScripts($action){

448
        if (common_logged_in()) {
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468

			$user = common_current_user();
			$profile = $user->getProfile();
			$qvitter_enabled='false';

			// if qvitter is enabled by default but _not_ disabled by the user,
			if(QvitterPlugin::settings('enabledbydefault')) {
				$disabled = Profile_prefs::getConfigData($profile, 'qvitter', 'disable_qvitter');
				if($disabled == 0) {
					$qvitter_enabled='true';
					}
				}
			// if qvitter is disabled by default and _enabled_ by the user,
			else {
				$enabled = Profile_prefs::getConfigData($profile, 'qvitter', 'enable_qvitter');
				if($enabled == 1) {
					$qvitter_enabled='true';
					}
				}

469
            $action->inlineScript(' var toggleQvitterAPIURL = \''.common_path('', true).'api/qvitter/toggle_qvitter.json\';
hannes's avatar
hannes committed
470
            						var toggleText = \''._('New').' '.str_replace("'","\'",common_config('site','name')).'\';
471 472
            						var qvitterEnabled = '.$qvitter_enabled.';
            						var qvitterAllLink = \''.common_local_url('all', array('nickname' => $user->nickname)).'\';
473
            						');
474
            $action->script($this->path('js/toggleqvitter.js').'?changed='.date('YmdHis',filemtime(QVITTERDIR.'/js/toggleqvitter.js')));
475 476 477 478
        }
    }


479

hannes's avatar
hannes committed
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
    /**
     * Menu item for Qvitter
     *
     * @param Action $action action being executed
     *
     * @return boolean hook return
     */

    function onEndAccountSettingsNav($action)
    {
        $action_name = $action->trimmed('action');

        $action->menuItem(common_local_url('qvittersettings'),
                          // TRANS: Poll plugin menu item on user settings page.
                          _m('MENU', 'Qvitter'),
                          // TRANS: Poll plugin tooltip for user settings menu item.
hannes's avatar
hannes committed
496
                          _m('Qvitter Settings'),
hannes's avatar
hannes committed
497 498 499 500
                          $action_name === 'qvittersettings');

        return true;
    }
501

hannes's avatar
hannes committed
502 503 504 505 506 507 508 509 510 511
    /**
     * Menu item for admin panel
     *
     * @param Action $action action being executed
     *
     * @return boolean hook return
     */

    function onEndAdminPanelNav($action)
    {
512

hannes's avatar
hannes committed
513 514 515 516 517 518 519 520 521 522
        $action_name = $action->trimmed('action');

        $action->out->menuItem(common_local_url('qvitteradminsettings'),
                          // TRANS: Poll plugin menu item on user settings page.
                          _m('MENU', 'Qvitter'),
                          // TRANS: Poll plugin tooltip for user settings menu item.
                          _m('Qvitter Sidebar Notice'),
                          $action_name === 'qvitteradminsettings');

        return true;
523
    }
hannes's avatar
hannes committed
524 525


526 527 528


    /**
529
     * Add stuff to notices in API responses
530 531 532 533 534 535
     *
     * @param Action $action action being executed
     *
     * @return boolean hook return
     */

536
    function onNoticeSimpleStatusArray($notice, &$twitter_status, $scoped)
537
    {
538

hannes's avatar
hannes committed
539 540 541
        // strip tags from source, we can't trust html here, because of gs bug
        $twitter_status['source'] = htmlspecialchars(strip_tags($twitter_status['source']));

542
    	// groups
543 544 545
		$notice_groups = $notice->getGroups();
		$group_addressees = false;
		foreach($notice_groups as $g) {
546
			$group_addressees[] = array('nickname'=>$g->nickname,'url'=>$g->mainpage);
547
			}
548
		$twitter_status['statusnet_in_groups'] = $group_addressees;
549

550 551 552 553 554 555 556 557 558
		// for older verions of gnu social: include the repeat-id, which we need when unrepeating later
		if(array_key_exists('repeated', $twitter_status) && $twitter_status['repeated'] === true) {
            $repeated = Notice::pkeyGet(array('profile_id' => $scoped->id,
                                        	'repeat_of' => $notice->id,
                                            'verb' => 'http://activitystrea.ms/schema/1.0/share'));
			$twitter_status['repeated_id'] = $repeated->id;

			}

559
		// more metadata about attachments
560

561
        // get all attachments first, and put all the extra meta data in an array
562
        $attachments = $notice->attachments();
563
        $attachment_url_to_id = array();
564 565
        if (!empty($attachments)) {
            foreach ($attachments as $attachment) {
566
				if(is_object($attachment)) {
567
                    try {
hannes's avatar
hannes committed
568
						$enclosure_o = $attachment->getEnclosure();
569

hannes's avatar
hannes committed
570 571 572 573
                        // Oembed
                        if(array_key_exists('Oembed', StatusNet::getActivePlugins())) {
                            $oembed = File_oembed::getKV('file_id',$attachment->id);
                            if($oembed instanceof File_oembed) {
hannes's avatar
hannes committed
574
                                $oembed_html = str_replace('&lt;!--//--&gt;','',$oembed->html); // trash left of wordpress' javascript after htmLawed removed the tags
hannes's avatar
hannes committed
575 576 577
                                if($oembed->provider == 'Twitter' && strstr($oembed_html, '>— '.$oembed->author_name)) {
                                    $oembed_html = substr($oembed_html,0,strpos($oembed_html, '>— '.$oembed->author_name)+1); // remove user data from twitter oembed html (we have it in )
                                    $twitter_username = substr($oembed->html,strpos($oembed->html, '>— '.$oembed->author_name)+strlen('>— '.$oembed->author_name));
578 579 580 581
                                    $twitter_username = substr($twitter_username, strpos($twitter_username,'(@')+1);
                                    $twitter_username = substr($twitter_username, 0,strpos($twitter_username,')'));
                                    $oembed->title = $twitter_username;
                                    }
hannes's avatar
hannes committed
582
                                $oembed_html = str_replace('&#8230;','...',$oembed_html); // ellipsis is sometimes stored as html in db, for some reason
hannes's avatar
hannes committed
583 584
                                $oembed_html = mb_substr(trim(strip_tags($oembed_html)),0,250);
                                $oembed_title = trim(strip_tags(html_entity_decode($oembed->title,ENT_QUOTES))); // sometimes we have html charachters that we want to decode and then strip
585 586
                                $oembed_provider = trim(strip_tags(html_entity_decode($oembed->provider,ENT_QUOTES)));
                                $oembed_author_name = trim(strip_tags(html_entity_decode($oembed->author_name,ENT_QUOTES)));
hannes's avatar
hannes committed
587
                                $attachment_url_to_id[$enclosure_o->url]['oembed'] = array(
588
                                    'type'=> $oembed->type,
589
                                    'provider'=> $oembed_provider,
hannes's avatar
hannes committed
590
                                    'provider_url'=> $oembed->provider_url,
hannes's avatar
hannes committed
591
                                    'oembedHTML'=> $oembed_html,
hannes's avatar
hannes committed
592
                                    'title'=> $oembed_title,
593
                                    'author_name'=> $oembed_author_name,
hannes's avatar
hannes committed
594 595 596 597 598 599 600
                                    'author_url'=> $oembed->author_url
                                );
                            } else {
                                $attachment_url_to_id[$enclosure_o->url]['oembed'] = false;
                            }
                        }

601 602 603
                        // add id to all attachments
                        $attachment_url_to_id[$enclosure_o->url]['id'] = $attachment->id;

604 605 606 607
                        // add an attachment version to all attachments
                        // this means we can force all cached attachments to update, if we change this
                        $attachment_url_to_id[$enclosure_o->url]['version'] = '1.2';

608 609
                        // add data about thumbnails
                        $thumb = $attachment->getThumbnail();
610 611 612 613 614 615 616 617 618 619
						$large_thumb = $attachment->getThumbnail(1000,3000,false);
                        if(method_exists('File_thumbnail','url')) {
                            $thumb_url = File_thumbnail::url($thumb->filename);
                            $large_thumb_url = File_thumbnail::url($large_thumb->filename);
                        } else {
                            $thumb_url = $thumb->getUrl();
                            $large_thumb_url = $large_thumb->getUrl();
                        }
						$attachment_url_to_id[$enclosure_o->url]['thumb_url'] = $thumb_url;
                        $attachment_url_to_id[$enclosure_o->url]['large_thumb_url'] = $large_thumb_url;
hannes's avatar
hannes committed
620
						$attachment_url_to_id[$enclosure_o->url]['width'] = $attachment->width;
621 622
						$attachment_url_to_id[$enclosure_o->url]['height'] = $attachment->height;

623 624 625 626 627
						// animated gif?
						if($attachment->mimetype == 'image/gif') {
							$image = ImageFile::fromFileObject($attachment);
							if($image->animated == 1) {
								$attachment_url_to_id[$enclosure_o->url]['animated'] = true;
hannes's avatar
hannes committed
628
							} else {
629
								$attachment_url_to_id[$enclosure_o->url]['animated'] = false;
630
							}
hannes's avatar
hannes committed
631
                        }
632

633
                    // this applies to older versions of gnu social, i think
hannes's avatar
hannes committed
634
					} catch (Exception $e) {
635
                        $twitter_status['attachment_error'] = array('code'=>$e->getCode(),'message'=>$e->getMessage(),'file'=>$e->getFile(),'line'=>$e->getLine(),'trace'=>$e->getTraceAsString());
hannes's avatar
hannes committed
636 637
						$thumb = File_thumbnail::getKV('file_id', $attachment->id);
						if ($thumb instanceof File_thumbnail) {
638
                            $thumb_url = $thumb->getUrl();
hannes's avatar
hannes committed
639
							$attachment_url_to_id[$enclosure_o->url]['id'] = $attachment->id;
640 641
							$attachment_url_to_id[$enclosure_o->url]['thumb_url'] = $thumb_url;
                            $attachment_url_to_id[$enclosure_o->url]['large_thumb_url'] = $thumb_url;
hannes's avatar
hannes committed
642
							$attachment_url_to_id[$enclosure_o->url]['width'] = $attachment->width;
643 644
							$attachment_url_to_id[$enclosure_o->url]['height'] = $attachment->height;

645 646 647 648 649 650 651
							// animated gif?
							if($attachment->mimetype == 'image/gif') {
								$image = ImageFile::fromFileObject($attachment);
								if($image->animated == 1) {
									$attachment_url_to_id[$enclosure_o->url]['animated'] = true;
								}
								else {
652
									$attachment_url_to_id[$enclosure_o->url]['animated'] = false;
653
								}
654 655
							}
						}
hannes's avatar
hannes committed
656 657
					}
            	}
658
            }
659
        }
660

661
		// add the extra meta data to $twitter_status
662 663
        if (!empty($twitter_status['attachments'])) {
            foreach ($twitter_status['attachments'] as &$attachment) {
664
                if (!empty($attachment_url_to_id[$attachment['url']])) {
665
                    $attachment = array_merge($attachment,$attachment_url_to_id[$attachment['url']]);
666 667
                }
            }
668 669
        }

hannes's avatar
hannes committed
670 671 672 673 674 675 676 677 678 679 680
        // quoted notices
        if (!empty($twitter_status['attachments'])) {
            foreach ($twitter_status['attachments'] as &$attachment) {

                $quoted_notice = false;

                // if this attachment has an url this might be a notice url
                if (isset($attachment['url'])) {
                    $noticeurl = common_path('notice/', StatusNet::isHTTPS());
                    $instanceurl = common_path('', StatusNet::isHTTPS());

681 682 683 684 685
                    // remove protocol for the comparison below
                    $noticeurl_wo_protocol = preg_replace('(^https?://)', '', $noticeurl);
                    $instanceurl_wo_protocol = preg_replace('(^https?://)', '', $instanceurl);
                    $attachment_url_wo_protocol = preg_replace('(^https?://)', '', $attachment['url']);

hannes's avatar
hannes committed
686
                    // local notice urls
687 688
                    if(strpos($attachment_url_wo_protocol, $noticeurl_wo_protocol) === 0) {
                        $possible_notice_id = str_replace($noticeurl_wo_protocol,'',$attachment_url_wo_protocol);
hannes's avatar
hannes committed
689 690 691 692 693 694 695
                        if(ctype_digit($possible_notice_id)) {
                            $quoted_notice = Notice::getKV('id',$possible_notice_id);;
                        }
                    }
                    // remote. but we don't want to lookup every url in the db,
                    // so only do this if we have reason to believe this might
                    // be a remote notice url
696
                    elseif(strpos($attachment_url_wo_protocol, $instanceurl_wo_protocol) !== 0 && stristr($attachment_url_wo_protocol,'/notice/')) {
hannes's avatar
hannes committed
697
                        $quoted_notice = Notice::getKV('url',$attachment['url']);
698 699 700 701 702 703 704 705
                        // try with http<->https if no match. applies to quitter.se notices mostly
                        if(!$quoted_notice instanceof Notice) {
                            if(strpos($attachment['url'],'https://') === 0) {
                                $quoted_notice = Notice::getKV('url',str_replace('https://','http://', $attachment['url']));
                            } else {
                                $quoted_notice = Notice::getKV('url',str_replace('http://','https://', $attachment['url']));
                            }
                        }
hannes's avatar
hannes committed
706 707 708 709 710 711 712 713 714 715
                    }

                    // include the quoted notice in the attachment
                    if($quoted_notice instanceof Notice) {
                        $quoted_notice_author = Profile::getKV('id',$quoted_notice->profile_id);
                        if($quoted_notice_author instanceof Profile) {
                            $attachment['quoted_notice']['id'] = $quoted_notice->id;
                            $attachment['quoted_notice']['content'] = $quoted_notice->content;
                            $attachment['quoted_notice']['nickname'] = $quoted_notice_author->nickname;
                            $attachment['quoted_notice']['fullname'] = $quoted_notice_author->fullname;
716
                            $attachment['quoted_notice']['is_local'] = $quoted_notice_author->isLocal();
hannes's avatar
hannes committed
717 718 719 720 721
                            $quoted_notice_attachments = $quoted_notice->attachments();
                            foreach($quoted_notice_attachments as $q_attach) {
                                if(is_object($q_attach)) {
                                    try {
                                        $qthumb = $q_attach->getThumbnail();
hannes's avatar
hannes committed
722 723 724 725 726
                                        if(method_exists('File_thumbnail','url')) {
                                            $thumb_url = File_thumbnail::url($qthumb->filename);
                                        } else {
                                            $thumb_url = $qthumb->getUrl();
                                        }
hannes's avatar
hannes committed
727 728 729
                                        $attachment['quoted_notice']['attachments'][] = array('thumb_url'=>$thumb_url,
                                                                                              'attachment_id'=>$q_attach->id);
                                    } catch (Exception $e) {
hannes's avatar
hannes committed
730
                                        common_debug('Qvitter: could not get thumbnail for attachment id='.$q_attach->id.' in quoted notice id='.$quoted_notice->id);
hannes's avatar
hannes committed
731 732 733 734 735 736 737 738 739 740
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }


hannes's avatar
hannes committed
741 742 743 744 745
        try {
            $twitter_status['external_url'] = $notice->getUrl(true);
        } catch (InvalidUrlException $e) {
		    common_debug('Qvitter: No URL available for external notice: id='.$notice->id);
        }
hannes's avatar
hannes committed
746 747


748
		// reply-to profile url
749 750
        try {
            $reply = $notice->getParent();
751 752 753
            $reply_profile = $reply->getProfile();
			$twitter_status['in_reply_to_profileurl'] = $reply_profile->getUrl();
            $twitter_status['in_reply_to_ostatus_uri'] = $reply_profile->getUri();
754 755
        } catch (ServerException $e) {
		    $twitter_status['in_reply_to_profileurl'] = null;
hannes's avatar
hannes committed
756
            $twitter_status['in_reply_to_ostatus_uri'] = null;
757
        }
hannes's avatar
hannes committed
758

759 760 761 762 763
        // attentions
        try {
            $attentions = $notice->getAttentionProfiles();
            $attentions_array = array();
            foreach ($attentions as $attn) {
hannes's avatar
hannes committed
764 765 766 767 768 769 770 771 772
                if(!$attn->isGroup()) {
                    $attentions_array[] = array(
                        'id' => $attn->getID(),
                        'screen_name' => $attn->getNickname(),
                        'fullname' => $attn->getStreamName(),
                        'profileurl' => $attn->getUrl(),
                        'ostatus_uri' => $attn->getUri(),
                    );
                }
773 774 775 776 777
            }
        $twitter_status['attentions'] = $attentions_array;
        } catch (Exception $e) {
            //
        }
778

hannes's avatar
hannes committed
779 780 781 782
		// fave number
		$faves = Fave::byNotice($notice);
		$favenum = count($faves);
		$twitter_status['fave_num'] = $favenum;
783

hannes's avatar
hannes committed
784 785 786 787
		// repeat number
		$repeats = $notice->repeatStream();
        $repeatnum=0;
        while ($repeats->fetch()) {
788 789 790
            if($repeats->verb == ActivityVerb::SHARE) { // i.e. not deleted repeats
                $repeatnum++;
                }
hannes's avatar
hannes committed
791
        	}
792 793
		$twitter_status['repeat_num'] = $repeatnum;

hannes's avatar
hannes committed
794 795 796 797 798 799 800
        // is this a post? (previously is_activity)
        if(method_exists('ActivityUtils','compareVerbs')) {
            $twitter_status['is_post_verb'] = ActivityUtils::compareVerbs($notice->verb, array(ActivityVerb::POST));
            }
        else {
            $twitter_status['is_post_verb'] = ($notice->verb == ActivityVerb::POST ? true : false);
            }
801

802 803
        // some more metadata about notice
		if($notice->is_local == '1') {
804
			$twitter_status['is_local'] = true;
805 806
			}
		else {
807
			$twitter_status['is_local'] = false;
808
			if ($twitter_status['is_post_verb'] === true) {
809 810 811 812 813
                try {
                    $twitter_status['external_url'] = $notice->getUrl(true);
                } catch (InvalidUrlException $e) {
        		    common_debug('Qvitter: No URL available for external notice: id='.$notice->id);
                }
814
				}
815
			}
816 817


818
		if(ActivityUtils::compareTypes($notice->verb, array('qvitter-delete-notice', 'delete'))) {
819
			$twitter_status['qvitter_delete_notice'] = true;
820
			}
821

822 823
        return true;
    }
824 825


826
    /**
827
     * Cover photo in API response, also follows_you, etc
828 829 830 831
     *
     * @return boolean hook return
     */

hannes's avatar
hannes committed
832
    function onTwitterUserArray($profile, &$twitter_user, $scoped)
833 834
    {

835 836 837
        $twitter_user['cover_photo'] = Profile_prefs::getConfigData($profile, 'qvitter', 'cover_photo');
        $twitter_user['background_image'] = Profile_prefs::getConfigData($profile, 'qvitter', 'background_image');

hannes's avatar
hannes committed
838 839 840 841 842
        // twitter compatible
        $twitter_user['profile_link_color'] = Profile_prefs::getConfigData($profile, 'theme', 'linkcolor');
        $twitter_user['profile_background_color'] = Profile_prefs::getConfigData($profile, 'theme', 'backgroundcolor');
        $twitter_user['profile_banner_url'] = Profile_prefs::getConfigData($profile, 'qvitter', 'cover_photo');

hannes's avatar
hannes committed
843

hannes's avatar
hannes committed
844
		if ($scoped) {
hannes's avatar
hannes committed
845 846 847 848 849 850
            // follows me?
            $twitter_user['follows_you'] = $profile->isSubscribed($scoped);

            // blocks me?
            $twitter_user['blocks_you']  = $profile->hasBlocked($scoped);
        }
851 852

		// local user?
853
		$twitter_user['is_local'] = $profile->isLocal();
hannes's avatar
hannes committed
854 855


856 857 858
		// silenced?
		$twitter_user['is_silenced'] = $profile->isSilenced();

hannes's avatar
hannes committed
859 860 861 862 863 864 865
        // rights
        $twitter_user['rights'] = array();
        $twitter_user['rights']['delete_user'] = $profile->hasRight(Right::DELETEUSER);
        $twitter_user['rights']['delete_others_notice'] = $profile->hasRight(Right::DELETEOTHERSNOTICE);
        $twitter_user['rights']['silence'] = $profile->hasRight(Right::SILENCEUSER);
        $twitter_user['rights']['sandbox'] = $profile->hasRight(Right::SANDBOXUSER);

866 867 868
		// sandboxed?
		$twitter_user['is_sandboxed'] = $profile->isSandboxed();

869 870 871 872 873 874 875 876 877 878 879 880 881
        // ostatus uri
        if($twitter_user['is_local']) {
            $user = $profile->getUser();
            if($user instanceof User) {
                $twitter_user['ostatus_uri'] = $user->uri;
            }
        } else {
            $ostatus_profile = Ostatus_profile::getKV('profile_id',$profile->id);
            if($ostatus_profile instanceof Ostatus_profile) {
                $twitter_user['ostatus_uri'] = $ostatus_profile->uri;
            }
        }

882
        return true;
883 884
    }

hannes's avatar
hannes committed
885 886 887 888 889 890 891


   /**
     * Insert into notification table
     */
    function insertNotification($to_profile_id, $from_profile_id, $ntype, $notice_id=false)
    {
892

893
		$to_user = User::getKV('id', $to_profile_id);
hannes's avatar
hannes committed
894 895 896 897 898 899 900 901 902
		$from_profile = Profile::getKV($from_profile_id);

		// don't notify remote profiles
		if (!$to_user instanceof User) {
			return false;
			}

		// no notifications from blocked profiles
		if ($to_user->hasBlocked($from_profile)) {
903 904
			return false;
			}
905

hannes's avatar
hannes committed
906
		// never notify myself
907 908 909
		if($to_profile_id == $from_profile_id) {
			return false;
			}
910 911

		// insert
912 913
		$notif = new QvitterNotification();
		$notif->to_profile_id = $to_profile_id;
914
		$notif->from_profile_id = $from_profile_id;
915
		$notif->ntype = $ntype;
916 917
		$notif->notice_id = $notice_id;
		$notif->created = common_sql_now();
918 919 920
		if (!$notif->insert()) {
			common_log_db_error($notif, 'INSERT', __FILE__);
			return false;
hannes's avatar
hannes committed
921
			}
922

hannes's avatar
hannes committed
923
        return true;
924 925
    }

hannes's avatar
hannes committed
926 927 928 929 930 931

    /**
     * Insert likes in notification table
     */
    public function onEndFavorNotice($profile, $notice)
    {
932 933

		// don't notify people favoriting their own notices
hannes's avatar
hannes committed
934
 		if($notice->profile_id != $profile->id) {
935
            $this->insertNotification($notice->profile_id, $profile->id, 'like', $notice->id);
936
 			}
937 938 939 940

        // mark reply and mention notifications as seen if i'm liking a notice i'm notified about
        self::markNotificationAsSeen($notice->id,$profile->id,'mention');
        self::markNotificationAsSeen($notice->id,$profile->id,'reply');
941 942 943
    }


944 945 946
    /**
     * Mark single notification as seen
     */
947
    public static function markNotificationAsSeen($notice_id, $to_profile_id, $ntype)
948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963
    {
    $notification_to_mark_as_seen = QvitterNotification::pkeyGet(array(
        'is_seen' => 0,
        'notice_id' => $notice_id,
        'to_profile_id' => $to_profile_id,
        'ntype' => $ntype
    ));
    if($notification_to_mark_as_seen instanceof QvitterNotification) {
        $orig = clone($notification_to_mark_as_seen);
        $notification_to_mark_as_seen->is_seen = 1;
        $notification_to_mark_as_seen->update($orig);
    	}
    }



hannes's avatar
hannes committed
964 965 966 967 968 969
    /**
     * Remove likes in notification table on dislike
     */
    public function onEndDisfavorNotice($profile, $notice)
    {
		$notif = new QvitterNotification();
970
		$notif->from_profile_id = $profile->id;
hannes's avatar
hannes committed
971 972 973 974
		$notif->notice_id = $notice->id;
		$notif->ntype = 'like';
		$notif->delete();
        return true;
975 976 977 978
    }



hannes's avatar
hannes committed
979 980 981 982 983 984
    /**
     * Insert notifications for replies, mentions and repeats
     *
     * @return boolean hook flag
     */
    function onStartNoticeDistribute($notice) {
985

mmn's avatar
mmn committed
986
        assert($notice->id > 0);    // since we removed tests below
hannes's avatar
hannes committed
987 988 989 990

		// repeats
        if ($notice->isRepeat()) {
			$repeated_notice = Notice::getKV('id', $notice->repeat_of);
991
			if ($repeated_notice instanceof Notice) {
hannes's avatar
hannes committed
992
	            $this->insertNotification($repeated_notice->profile_id, $notice->profile_id, 'repeat', $repeated_notice->id);
993 994 995 996

                // mark reply/mention-notifications as read if we're repeating to a notice we're notified about
                self::markNotificationAsSeen($repeated_notice->id,$notice->profile_id,'mention');
                self::markNotificationAsSeen($repeated_notice->id,$notice->profile_id,'reply');
997 998 999

                // (no other notifications repeats)
                return true;
1000
                }
1001
 			}
hannes's avatar
hannes committed
1002

1003
		// don't add notifications for activity/non-post-verb notices
hannes's avatar
hannes committed
1004 1005 1006 1007 1008 1009 1010
        if(method_exists('ActivityUtils','compareVerbs')) {
            $is_post_verb = ActivityUtils::compareVerbs($notice->verb, array(ActivityVerb::POST));
            }
        else {
            $is_post_verb = ($notice->verb == ActivityVerb::POST ? true : false);
            }
        if($notice->source == 'activity' || !$is_post_verb) {
1011
			return true;
1012
			}
hannes's avatar
hannes committed
1013

1014 1015 1016 1017 1018
		// mark reply/mention-notifications as read if we're replying to a notice we're notified about
		if($notice->reply_to) {
            self::markNotificationAsSeen($notice->reply_to,$notice->profile_id,'mention');
            self::markNotificationAsSeen($notice->reply_to,$notice->profile_id,'reply');
			}
hannes's avatar
hannes committed
1019

1020

1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
		// replies and mentions
 		$reply_notification_to = false;
		// check for reply to insert in notifications
		if($notice->reply_to) {
			try {
				$replyauthor = $notice->getParent()->getProfile();
				$reply_notification_to = $replyauthor->id;
				$this->insertNotification($replyauthor->id, $notice->profile_id, 'reply', $notice->id);
			//} catch (NoParentNoticeException $e) {	// TODO: catch this when everyone runs latest GNU social!
				// This is not a reply to something (has no parent)
			} catch (NoResultException $e) {
				// Parent author's profile not found! Complain louder?
				common_log(LOG_ERR, "Parent notice's author not found: ".$e->getMessage());
			}
		}

		// check for mentions to insert in notifications
		$mentions = $notice->getReplies();
		$sender = Profile::getKV($notice->profile_id);
		$all_mentioned_user_ids = array();
		foreach ($mentions as $mentioned) {

			// no duplicate mentions
			if(in_array($mentioned, $all_mentioned_user_ids)) {
				continue;
1046
				}
1047 1048 1049 1050 1051 1052 1053
			$all_mentioned_user_ids[] = $mentioned;

			// only notify if mentioned user is not already notified for reply
			if($reply_notification_to != $mentioned) {
				$this->insertNotification($mentioned, $notice->profile_id, 'mention', $notice->id);
				}
			}
1054

hannes's avatar
hannes committed
1055 1056
        return true;
    	}
1057

hannes's avatar
hannes committed
1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071

   /**
     * Delete any notifications tied to deleted notices and un-repeats
     *
     * @return boolean hook flag
     */
    public function onNoticeDeleteRelated($notice)
    {

		$notif = new QvitterNotification();

		// unrepeats
        if ($notice->isRepeat()) {
			$repeated_notice = Notice::getKV('id', $notice->repeat_of);
1072 1073 1074
			$notif->notice_id = $repeated_notice->id;
			$notif->from_profile_id = $notice->profile_id;
 			}
hannes's avatar
hannes committed
1075 1076 1077
		// notices
		else {
			$notif->notice_id = $notice->id;
1078 1079 1080 1081
			}

		$notif->delete();

hannes's avatar
hannes committed
1082 1083 1084
        // don't delete if this is a user is being deleted
        // because that creates an infinite loop of deleting and creating notices...
        $user_is_deleted = false;
1085 1086 1087 1088 1089 1090 1091 1092
        try {
            // outputs an activity notice that this notice was deleted
            $profile = $notice->getProfile();
            $user = User::getKV('id',$profile->id);
            if($user instanceof User && $user->hasRole(Profile_role::DELETED)) {
                $user_is_deleted = true;
            }
        } catch (NoProfileException $e) {
hannes's avatar
hannes committed
1093 1094 1095
            $user_is_deleted = true;
        }

1096
        if(!$user_is_deleted && class_exists('StatusNet') && !array_key_exists('ActivityModeration', StatusNet::getActivePlugins())) {
hannes's avatar
hannes committed
1097
            $rendered = sprintf(_m('<a href="%1$s">%2$s</a> deleted notice <a href="%3$s">{{%4$s}}</a>.'),
hannes's avatar
hannes committed
1098 1099 1100 1101
                                htmlspecialchars($profile->getUrl()),
                                htmlspecialchars($profile->getBestName()),
                                htmlspecialchars($notice->getUrl()),
                                htmlspecialchars($notice->uri));
hannes's avatar
hannes committed
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118
            $text = sprintf(_m('%1$s deleted notice {{%2$s}}.'),
                                $profile->getBestName(),
                                $notice->uri);
            $uri = TagURI::mint('delete-notice:%d:%d:%s',
                                $notice->profile_id,
                                $notice->id,
                                common_date_iso8601(common_sql_now()));
            $notice = Notice::saveNew($notice->profile_id,
                                      $text,
                                      ActivityPlugin::SOURCE,
                                      array('rendered' => $rendered,
                                            'urls' => array(),
                                            'uri' => $uri,
                                            'verb' => 'qvitter-delete-notice',
                                            'object_type' => ActivityObject::ACTIVITY));
        }

1119

hannes's avatar
hannes committed
1120
        return true;
1121 1122
    }

1123 1124 1125 1126 1127 1128 1129 1130


   /**
     * Checks for deleted remote notices and deleted the locally
     * A local qvitter-delete-notice is outputted in the onNoticeDeleteRelated event above
     *
     * @return boolean hook flag
     */
1131

1132 1133
    public function onEndHandleFeedEntry($activity) {

1134
		if($activity->verb == 'qvitter-delete-notice' && class_exists('StatusNet') && !array_key_exists('ActivityModeration', StatusNet::getActivePlugins())) {
1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148

			$deleter_profile_uri = $activity->actor->id;
			$deleted_notice_uri = $activity->objects[0]->objects[0]->content;
			$deleted_notice_uri = substr($deleted_notice_uri,strpos($deleted_notice_uri,'{{')+2);
			$deleted_notice_uri = substr($deleted_notice_uri,0,strpos($deleted_notice_uri,'}}'));

			$deleter_ostatus_profile = Ostatus_profile::getKV('uri', $deleter_profile_uri);

			if(!$deleter_ostatus_profile instanceof Ostatus_profile) {
				return true;
				}

			$deleter_profile = Profile::getKV('id', $deleter_ostatus_profile->profile_id);
			$deleted_notice = Notice::getKV('uri', $deleted_notice_uri);
1149

1150 1151
			if(!($deleter_profile instanceof Profile) || !($deleted_notice instanceof Notice)) {
				return true;
1152 1153
				}

1154
			if($deleter_profile->id != $deleted_notice->profile_id) {
1155 1156
				return true;
				}
1157 1158

			$deleted_notice->delete();
1159 1160
			}

1161 1162 1163 1164
        return true;
    }


1165 1166


1167

hannes's avatar
hannes committed
1168 1169 1170 1171 1172 1173 1174 1175
   /**
     * Add notification on subscription, remove on unsubscribe
     *
     * @return boolean hook flag
     */
    public function onEndSubscribe($subscriber, $other)
    {
		if(Subscription::exists($subscriber, $other)) {
1176
			$this->insertNotification($other->id, $subscriber->id, 'follow', 1);
hannes's avatar
hannes committed
1177
			}