The query shouldn't be too expensive: it'll use an index to narrow
down the resultset for 1 user. After that, it'll be sorted based on
a grouped by value, but that should fit in memory: it'll never be
on more than 2000 entries, which is the max amount of notifications
per user.
Change-Id: I271ea7f7a6e010284739bfce02c4ec8a077148fc
There was quite a small link under the main title in Special:Notifications
which pointed to a related help page. Now the OutputPage::addHelpLink()
method is used which moves this link to the upper right corner and allows
configuring this on-wiki (instead of LocalSettings.php or so).
Bug: T101057
Change-Id: Ib4aecee8006b8d71bb3cd86f1d4ebdfee9080870
It's probably not realistically possible for a revision to be oversighted
by the time generateMentionEvents() runs, but for consistency
we should be using RAW here.
Change-Id: If73b4abe5fbae5cadb75c5e09137299873f2a764
Right now we don't actually know how many times
each of these cases happen so add some basic tracking
so we can make some informed decisions.
Bug: T135719
Change-Id: Id4d519aefe96ecca2e3c51dd1c8128de70d0caac
Will only show for new instances, because the information
will be unavailable for old ones.
Bug: T135959
Depends-On: I3d894acaf3d85b790e5034c7d9f76bf94672f445
Change-Id: I04620678dd0ebffb3b1a92a9a0587cb7557d77f4
Also, get rid of the feature where we hide the project name when there
is only one project available. The titles are always showing.
Bug: T127419
Change-Id: I1b1285d84b7fb4775d13067e6ae1c50602ed3baf
This was causing warnings in production:
Invalid parameter for message "notification-body-edit-user-talk-with-section": a:1:{s:9:"plaintext";N;}
Change-Id: Ibdea5d899caf446a8c7f811416fdabaa3dccccdd
Check for proper unserialization in EchoEvent::loadFromRow(), and return
false if not possible. Callers were updated to check for a false return.
Bug: T73489
Change-Id: I33867aa9bbbc5f0ecfe0d2a9e1b03eb1a937ae83
CA tokens are single-use, and the fact that they even worked
for multiple requests was a race condition. Instead of getting
one CA token and using it for all requests, get a fresh token
for each request.
Bug: T135250
Change-Id: Ie1bbdefd3e265d009d0c42ff27da447b8da7f1fd
This is needed because global tables and cache keys will attempt to be used
even for users who don't have the preference enabled.
Bug: T135266
Change-Id: I6208a12d46c8cd0275a232663cd50ac2bd2fed1c
Allow marking notifications as read per 'section' (days) in the
Special:Notifications page.
Bug: T115528
Bug: T134204
Change-Id: I7324a2c693aa92b9327cf8ff98f125293d5fba10
When updating notification counts, we already called User::invalidateCache(),
which bumps the local user's touched timestamp, which is taken into
account by OutputPage when computing the last-modified timestamp of the response.
However, this only works for one wiki, while the changed global count
needs to be displayed on every wiki. To accomplish this, track the
timestamp of the last update in NotifUser, and hook it into
OutputPageCheckLastModified.
Change-Id: I22c88a017f18a28179906049ee423c2d7e81c939
If all server-side cross-wiki requests fail, we'd return an empty API response.
This is invalid, the frontend expects things like list:[] to still be there.
Change-Id: I72fc5a017647ca28abbc061992fa4868ca5737f4
We were using the local user ID instead, which is not the
same on every wiki, which caused strange cache staleness
and pollution behavior.
Run sets through a wrapper function (gets were already wrapped)
so we can update the instance cache and deal with uncomputable
cache keys in one place. A global cache key may be uncomputable
if we fail to obtain the user's global user ID (users aren't
supposed to be unattached, but some are).
Also bump the cache version to get rid of polluted cache entries.
Bumping this version number was probably a good idea anyway,
with all the recent changes.
Bug: T134533
Change-Id: I1c4f0c2f2eded480c80f8ec7a49a04feb7c5ecfb
If we don't initialize $results, getForeignNotifications() will return
null, and this will cause a fatal when trying to += it into an array.
Change-Id: Ibb868cbf0b52ff2de41c5be82c9605801e51ffae
Formatters based on presentation models for
individual event emails and digest (daily, weekly)
plain text emails.
Bug: T121067
Change-Id: I4eceaf521315adab7429a8a73ffca70ebcddab86
Passing a param 'wiki' with a list of wiki names will now
result in getting notifications from these wikis too.
It'll execute multi-curl calls to the given wikis to fetch
their results.
Bug: T130636
Change-Id: I89df54366501acfe3e5cf6d2f313ee32694ba387
Notifications were being marked as read in response to a click event
in JavaScript, but that causes a jarring effect in the UI, and it's
not reliable (the browser could abort the AJAX request).
Instead, add ?markasread=XYZ to the end of every primary link URL,
where XYZ is the event ID.
Bug: T133975
Depends-On: Icb99d5479836fea25a47451b5a758dd71f642f71
Change-Id: I8047d121584b43e6172463a50ad0e0de5f7fa73c
Previously, getNotificationCount() only looked at local notifications,
and foreign notifications were added in separately by getMessageCount()
and getAlertCount(). This didn't make any sense and resulted in
counter-intuitive things like I4d49b543.
Instead, add a $global flag to getNotificationCount(). If $global=false,
the local count is returned as before, but if $global=true, the
global count (=local+foreign) is returned. If $global is omitted,
the user's cross-wiki notification preference determines which is returned.
Update getLastUnreadNotificationCount() in the same way, since it had
the same issues.
Also add caching for global counts and timestamps, using a global
memc key.
Bug: T133623
Change-Id: If78bfc710acd91a075771b565cc99f4c302a104d
Replace getAlertEvents and getMessageEvents with
getEventsForSection.
Also, add IDs for linking to sections
Bug: T123018
Change-Id: Ic480320a52a401609d853fc8c75c781b89bb8722
Instead of checking the cross-wiki notifications preference
in the constructor, move it to a method that other code can reuse.
Also add a parameter allowing foreign notification data to be
inspected even if the user has disabled the preference.
Change-Id: I6600ff27aa5af1737b3a6c3cde586d325886bc86
Removing the info popup because we don't have to show
a privacy notice when linking within the wiki.
This adds a database query to every page view for logged-in
users; If78bfc710, once merged, will fix that.
Bug: T117669
Change-Id: I8451db34ae8e94264e4921ecd6df6e4b32c7623a
It doesn't use $this, except to call getWikiTitle(), so make that
static too. This allows us to use it in EchoForeignPresentationModel
without creating a second instance there.
Change-Id: If778db0852de1cbf5c2190ce50ce561745bb3887
This provides a simple unlisted special page,
Special:DisplayNotificationsConfiguration, to document how the
notifications are structured and configured. It shows:
* Which types are in each category
* Which notify types (web/email) can be enabled for each category
* Which notify types are mandatory for each category
* Which notify types are enabled by default:
** For existing users
** For new users
Bug: T132127
Change-Id: I25b447a69a7c984941dfd703345d7977c0000bfe
Merge and deploy at the *same time* as:
* BounceHandler - I3c669945080d8e1f67880bd8a31af7f88a70904d
* mediawiki-config - I13817c139967ed9e230cfb0c87c5de66da793c96
Despite claiming to be about categories, $wgEchoDefaultNotificationTypes
was actually configuring both categories and types (which go inside
categories).
For example, 'thank-you-edit' is a type, but 'emailuser' is both
a category and a type (when used as a category, this has special
effects at Special:Preferences).
Since types and categories can and sometimes do have the same names,
this leaves no way to properly and clearly configure them. It also
makes it difficult to document what is going on (as required by
T132127).
Split into three variables:
$wgDefaultNotifyTypeAvailability - Applies unless overriden
$wgNotifyTypeAvailabilityByCategory - By category; this can be and is
displayed at Special:Preferences
$wgNotifyTypeAvailabilityByNotificationType - By type; this cannot
be displayed at Special:Preferences. To avoid confusing the user,
we introduce a restriction (which was previously followed in practice,
AFAICT) that types can only be overridden if the category is not
displayed in preferences.
Otherwise, it can look to the user like a category is on/off, but the
types within might have the opposite state.
Due to this configuration change, this is a breaking change, and needs
coordinated deployments.
This also lays the groundwork for T132127
Also change terminology to consistently use "notify type" for web/email.
It was mixing between that and output format (which unfortunately
sounds like the API format, e.g. 'model').
Bug: T132820
Bug: T132127
Change-Id: I09f39f5fc5f13f3253af9f7819bca81f1601da93
I thought the name was confusing, and would be even more so
if we get real notifications from other sources.
Meanwhile also split $crossWikiSummary into 2 properties:
- 1 with the class
- 1 to indicate if it should be used
Change-Id: I0e83be7924c8c77680ea1ada3f2bd6a190ce6149
This would soon become problematic when output can come from
multiple sources, with potentially conflicting ids.
The ID is already included in the result anyway.
Change-Id: Id92150c71c68958819fe0ee329e70393052c34c9
They were using different code and different approaches.
I've left getSection() and the code for creating a Title
with a section duplicated for now, and I'll move them
into a trait in the next commit. I wanted to do that
separately because we aren't using traits in this
code base yet.
Change-Id: I56cf745d2cc8a6c43caec08024187de9598cecb8
It's (mostly) unused, and it would become problematic once we have
notifications from multiple places (where those ids could conflict)
Change-Id: Ib3bb5ae1e5689037b38290c9ce3d8691f52582b0
We ended up double-parsing section titles, which resulted
in strange behavior when the section title was something like
{{tl|infobox}}.
Bug: T132872
Change-Id: I4434624f392cd0e1df39374d45d60f7d83be7161
This caused notifications on mobile to show notifications for
both alert|message, as the type was always "all".
Bug: T130801
Change-Id: Ice245eb407ca360d8e882c0ba48cb7b3e0ecb851
formatSummary() was first parsing the summary using the
summary parser, then handing off the resulting HTML to
getTextSnippet() which parsed it again with the normal parser.
Bug: T131087
Change-Id: I2724ccb7c23579b3f02dea57d4fc833079169adf
There is currently a hard cap of badge display count.
We'll want to be able to request a different count for other purposes:
cleaning up old notifications, for example. We want to keep around a
certain amount of motifications (which is higher than the display count)
so we must be able to query a different count.
Change-Id: Id460fd7f46e397d22da49283b30fd12a6bbb0c9f
Both in the order of the cross-wiki bundles themselves, and
in the message in the notification body.
ForeignNotifications tracks timestamps per wiki per section,
and exposes these through getWikiTimestamp(). ApiEchoNotifications
adds these timestamps to the sources manifest, and also sorts
the list of wikis by timestamp (it'd be nicer to do this in
ForeignPresentationModel instead, but then we'd have to create a new
ForeignNotifications instance which causes a duplicated DB query).
NotificationsModel receives the timestamp for its wiki as its
fallback timestamp, and makes getTimestamp() return this value
during the pre-population phase. This causes its parent to
automatically sort it correctly.
Because the timestamp of a wiki depends on the section (alerts vs messages),
we can't put it in the global sources manifest at the top level
of the API response. Instead, get rid of this global sources
manifest and put all the sources data in the foreign notifications
directly. This allows us to specify different timestamps, and also
allows us to get rid of code in EchoApi that was already remapping
the API response to this format.
Bug: T130298
Change-Id: Ie083fbb1ccaf74fbe804633d87ef03c9e71b120f
This involves:
* Making this value no longer admin-configurable.
* Changing getNotificationCountForOutput to return only a single value
Since there is no + in the formatted value anymore, we can actually
use the same value for both.
This is a B/C break, but hopefully worth it to simplify the method
call.
For now, the excess parameter is just marked unused. It could be
removed at some point if the translations are updated.
This must be merged at the same time as:
* Flow - Ibfa56b1af9e8c56b4c5f900e0d487bc09688b2a2
* MobileFrontend - Ibf784b279d56773a227ff261b75f2b26125bbb63 (well, MF
can be merged first)
* translatewiki - I2a4b6938aed49e4101deb6b9351c43656a863490
Also, change 1 to One/one, per Siebrand on the task. This can easily
be dropped/undone if we don't want it.
Also, remove reference to no-longer-existent notification-page-linked-bundle
Bug: T127288
Change-Id: Iabeaae747f99980c0610d552f6b38f89d940b890
Add a 'mark as unread' to all unread notifications and allow them
to be marked unread. These notifications will no longer be automatically
marked as read when the pages they refer to are visited.
Bug: T73564
Change-Id: I677d3c0399e46fd7c35531df1cc0e61db2d4eb1b
Don't try to render if page was deleted, and fix 'extra' parameter
(was breaking message key and thus rendering)
Bug: T129641
Change-Id: I5d0fdfd3921427993211969eb5793f8e9e7667a8
The previous implementation did the following weird things:
* Stripped tags before parsing
* Stripped templates before parsing using a hacky while loop
that bails after ten attempts
* Decoded entities using htmlspecialchars_decode(), while
html_entity_decode() makes more sense
* ...which meant it had to manually convert   back
to spaces, which is not necessary if you use html_entity_decode()
* Removed any single braces ('{' and '}') from the output
* Rejected the entire output if there were any entities left,
which is fairly likely since htmlspecialchars_decode()
only decodes a few of them
Instead of all this, just parse, strip tags, decode entities
(all of them, not just a few), trim and truncate. In particular,
don't strip templates, because we use getTextSnippet() in mention
notifications, which look weird when {{ping}} templates are stripped.
Bug: T129531
Change-Id: I956b2f6badc40d2f5bf90a0458ccab8b8fc6fefb
This reverts commit e372f3ce6f.
The previous attempt was broken because
EchoTargetPageMapper::fetchByUserPageId() returns a list of
EchoTargetPage objects, not a single one.
Bug: T117531
Change-Id: Id02a025e3736a7b92d9d6fb8adf29ef674f8e2fa
Title::newFromId() can return null, and if this were the case the
instance caching would never work, so it would continually make useless
database queries.
Initialize the $title member variable as false to begin with, and use
that to check whether we've already checked Title::newFromId().
Change-Id: Id07c2c963ffcd03e212bed0a666735bcb68b92e0
We calculate how many messages and alerts are being marked as read, and
subtract them from the count since the database and caches won't be
updated until the end of the request.
For performance, we also get the event_type while doing the
EchoTargetPage lookup query to avoid having to query it individually
later on.
Bug: T117531
Change-Id: I0d9302adf1b4b07a4ff26a04b00d4498aa3fe7ee
When $adjustLength is false, truncation will only happen
when the string is longer than the limit + the length of
the ellipsis to avoid the case where the ellipsis make
the string longer than the original.
Bug: T121822
Change-Id: I731a3c38b96ede6c6510f64771be0b9662dcba43
It's terrible that in groupbysection mode, you still have to pass
messageunreadfirst and alertunreadfirst separately, but at least
this way the unreadfirst feature is available at all in the
non-grouped mode.
Change-Id: Ifb0707be484bda8e33810c888bae1d008cac2d9f
API requests with notgroupbysection disabled but notsection set
to 'alert' would return foreign notification bundles for both
alerts and messages, separately.
The frontend always pasess notgroupbysection=1 in practice because
notmessageunreadfirst=1 doesn't work without it; but regardless of
that, the API module shouldn't return a foreign notification bundle
for messages when only alerts are requested.
Change-Id: I9fa6d1411a8c121591ce6dd75ee8052bcdcb478b
Using wiki names in the header is problematic because the messages
we were using weren't designed to be used in a sentence, only in headings.
This removes the wiki names from the sentence in the header, and
instead puts a comma-separated list (with "and") of wikis in the body.
The messages keep $3 and $4 for backwards compatibility, so translations
of the form "from Commons and 2 other wikis" will keep working.
Bug: T121936
Change-Id: Ideeba794e260b3c388fa29226b53197c050162ef
It wasn't meant to be there, and flow-mention doesn't have it either.
We also don't have any other notification types with
three prioritized secondary links.
Bug: T125949
Change-Id: Icbffa185b1116b1a6beb9bb3585339fdf7e82cdd
The approach here is to use $msg->escaped() to
remove all markup and then replace new lines
with a single space.
Bug: T128062
Change-Id: I1d5a6e57fbae9b6a441671beff1c60720b9445d5
Some notifications return relative urls in their
primary or secondary links. This change makes those
urls absolute so they point to the right wiki
when viewed from another wiki (cross-wiki notifications).
Bug: T125738
Bug: T127697
Change-Id: Ib65337430eb2484f9491668a9998deef70589fb1
It used to be like this, but in order to get the messages badge to show
in the correct circumstances, I had to know if the user had ever had
foreign messages before & I also needed euw_messages_ts even if those
messages had already been read.
Now that we're unconditionally showing messages, we no longer need these
0-value rows.
Bug: T127731
Change-Id: I1fc13bf0e5133ae39224f66d1b5a59c769bfcee2
Current situation: cross-wiki can be enabled on certain wikis &
disabled on others.
Code used to check if cross-wiki was enabled before fetching the
status of unread messages on foreign wikis. However, it would then
write that result to a shared memcached key.
The cross-wiki check should not happen before data is stored to
cache: what is stored should always be for all wikis. Only when
we fetch it, should we check if cross-wiki is enabled. And if it's
not, we can't use the cross-wiki data - we have to hack around it
ourselves...
Bug: T124372
Change-Id: I3d3d54fc3cbfbf73b51e97acfd8d355dd0cea36d
when the subject line is left with the default
generated value, we take the begining of the
email content to add a preview in the
notification.
Bug: T121831
Change-Id: Ib7c646f6709c7100ef51186f84fe14807d6a211a
Objects can be different instances (and for User, they can contain
very different data) in which case they wouldn't be recognized even
if they were the same user.
Let's find by ID instead.
Bug: T124803
Change-Id: Ia166fd4190f264354cea83d98047c62c7e0714ea
This code is completely useless:
* for format=flyout, the new EchoFlyoutFormatter.php will be run
* and even that one has already been deprecated as it was replaced
by format=model (flyout html is now built in client)
Change-Id: Iea23abb66397ecc4efb575fe33fdbedc5b4e0f70
The existing "html" formatter was used for the special page & is now
superseeded by the new-style "special" formatter. Previous "html"
notifications are no longer used & could even be broken.
Instead of keeping the old "html" formatter around, we should let it
use the new formatter (and eventually just kill that redundant format
in the API)
Change-Id: Ibbd40aafa9eee718b196ad62f6edc99629b263b4
We now have 'special' in $formatters, there's no need to keep
the mapping to the legacy formatter around.
Change-Id: I66f330e8c84a50858658361caef521a3e5717d58
Right now, if certain users should be excluded, that would have
to be part of the user-locators already. This is annoying because
it's hard to write "generic" user locators when you want to exclude
just a couple of people in certain cases.
In Flow, for example, we have user-locators for users watching a
board or topic. We don't want to send the notification to people
that have also been mentioned in that post (they'll get a separate
notification). We could build that exception into those
user-locators, but then we couldn't re-use them in other places...
This basically means we couldn't use EchoUserLocator::locateUsersWatchingTitle,
we would have to roll our own that also excludes mentioned users.
Instead, this lets you add 'user-filters' (that functionality
actually exists already, but is not currently exposed), which
lists users to not send the notification to, even though they could
be in a user-locator.
Bug: T125428
Change-Id: Ifa0e2d3283f57624af4c5ec264f9f66223508e83
Split mentions into 4 cases:
- Mentioned on article talk page
- Mentioned on agent's talk page
- Mentioned on another user's talk page
- Mentioned on any other page
Adjust secondary link
icon: article or talk
text: without namespace for article and article talk
Bug: T56433
Change-Id: Ibf965dad4f9cc468fdd4321b2450d6eaec0ac1d7
Wrap the CallbackFilterIterator backport class in a conditional check
for PHP runtimes that include the class natively. This really should
only be needed for linting as the class is loaded via an autoloader
and thus should not be loaded if the runtime already has it
available.
Bug: T124828
Change-Id: I39d27385186d4693a8babdd2b818e6b4bc16255a
Only display when it's different than the pre-populated
edit summary (Undo revision 123 by User).
Bug: T121808
Change-Id: I5a00ff174fd31fdbf776a06b7b9375f63b921677
There was no point in letting it extend EchoFlyoutFormatter instead
of the base EchoEventFormatter. The only things in EchoFlyoutFormatter
are formatModel & getIconURL, both of which aren't being called.
Change-Id: I89511530a41976974f4d51d55379a617dfe503ec
WikiMap is almost useful for this purpose, but not quite
because it doesn't provide the script path, only the article path.
Change-Id: I1627d58cab5ff518be3c3e14e05a53899b083503
All extensions seem to have been updated to use the current formats,
so we can get rid of this tech debt.
Depends-On: I7503db28b0d81fb818b525ea9362e49b9b56342a
Change-Id: Idbcbbf95eab1172015bceea4e8124ba4c639efa8
Also updated description value in agent link: '' is used everywhere
else to mean "no description" (because that's exactly what '' is)
Change-Id: Ib77c0f1843593abf67e9d726a80bb4fbe1ec7d84
We already output unix timestamp both in user preference timezone as well as
utc, but we only had the user timezone version for TS_MW format.
While we could change the frontend to use the unix timestamp format, I don't see
any reason not to also include the MW format in utc. Frontend can now easily use
that.
Also fixed creation of the moment object. The timestamp was created as UTC, but
the way it got there was wrong: it expects the timezone offset (Z) to be
included in the timestamp, which is not the case (so it just ended up at +0:00,
which was fine, but confusing). I removed the 'Z' and forced it to be
interpreted as utc.
Bug: T121813
Change-Id: I09403615a1ffbde5dd69af9914afdbdd86cbfe4d
We're trying to get rid of links in notification
messages, and the link was redundant with the primary link
in both cases.
Change-Id: I69e888a355c263b5a8c5ca7a46430746895de44c
They're currently auto-converted to the new format, but ideally,
we wouldn't need that B/C code. And since this is the extension
others will likely look at for examples when implementing, we
should do it right here.
Also: there is no B/C correction for missing keys in secondary
links (description, icon).
Change-Id: If1a8b9911e81bb4c565f21a4b9e31fdc73426d93
Also removes tests for the class.
Bug: T119253
Change-Id: I4c0d7187c2b847297dd0867faecba26185cfba37
Depends-On: Iccafbbdb06711463fee0f30a11326c7771df30e2
Right now, it'll only respond a certain, fixed, amount,
not allowing you to paginate the list.
Note: haven't properly tested all possible cases yet!
Change-Id: I84761b13a1b9203cb8e3fcc80941d739cd28659f
The only difference at this point is that fetchByUser initializes
the EchoNotification object with $targetPages. It doesn't really
matter that it doesn't have the target pages, since fetchUnreadByUser
is currently only used in the flyout, where those target pages aren't
used. But regardless of what method was used to fetch the data, I
think the data should be the same.
And now, there's less code duplication...
Change-Id: I04c7b98794af5427a2217dd337108e7eea1e65c5
Added code to redirect the user and display a short message informing
them of the need to login.
Bug: T118873
Change-Id: I2145bc1502dbd19d660302d9f19e0d4a2ad5ad50
Presentation models that display the number of bundled notifications
typically group these by a property like agent or page ID. For example,
every edit someone makes to a user talk page generates an event,
so there could be 5 edit-user-talk events by only 2 distinct users;
in that case we want to display "Foo and 1 other user left a message",
not "Foo and 4 other users".
With this change, a presentation model that wants such behavior
can pass a callback to getBundleCount() that retursn the user ID, which
will cause getBundleCount() to return the number of distinct
users rather than the total number of notifications.
Change-Id: I79c8dd14277eff0d2ec27f155b1d13dca1e571a8