Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F4130567
EventMapper.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
EventMapper.php
View Options
<?php
namespace
MediaWiki\Extension\Notifications\Mapper
;
use
InvalidArgumentException
;
use
MediaWiki\Extension\Notifications\Model\Event
;
use
MediaWiki\User\UserIdentity
;
/**
* Database mapper for Event model, which is an immutable class, there should
* not be any update to it
*/
class
EventMapper
extends
AbstractMapper
{
/**
* Insert an event record
*
* @param Event $event
* @return int
*/
public
function
insert
(
Event
$event
)
{
$dbw
=
$this
->
dbFactory
->
getEchoDb
(
DB_PRIMARY
);
$row
=
$event
->
toDbArray
();
$dbw
->
newInsertQueryBuilder
()
->
insertInto
(
'echo_event'
)
->
row
(
$row
)
->
caller
(
__METHOD__
)
->
execute
();
$id
=
$dbw
->
insertId
();
$listeners
=
$this
->
getMethodListeners
(
__FUNCTION__
);
foreach
(
$listeners
as
$listener
)
{
$dbw
->
onTransactionCommitOrIdle
(
$listener
,
__METHOD__
);
}
return
$id
;
}
/**
* Create an Event by id
*
* @param int $id
* @param bool $fromPrimary
* @return Event|false False if it wouldn't load/unserialize
*/
public
function
fetchById
(
$id
,
$fromPrimary
=
false
)
{
$db
=
$fromPrimary
?
$this
->
dbFactory
->
getEchoDb
(
DB_PRIMARY
)
:
$this
->
dbFactory
->
getEchoDb
(
DB_REPLICA
);
$row
=
$db
->
newSelectQueryBuilder
()
->
select
(
Event
::
selectFields
()
)
->
from
(
'echo_event'
)
->
where
(
[
'event_id'
=>
$id
]
)
->
caller
(
__METHOD__
)
->
fetchRow
();
// If the row was not found, fall back on the primary database if it makes sense to do so
if
(
!
$row
&&
!
$fromPrimary
&&
$this
->
dbFactory
->
canRetryPrimary
()
)
{
return
$this
->
fetchById
(
$id
,
true
);
}
elseif
(
!
$row
)
{
throw
new
InvalidArgumentException
(
"No Event found with ID: $id"
);
}
return
Event
::
newFromRow
(
$row
);
}
/**
* @param int[] $eventIds
* @param bool $deleted
*/
public
function
toggleDeleted
(
array
$eventIds
,
$deleted
)
{
$dbw
=
$this
->
dbFactory
->
getEchoDb
(
DB_PRIMARY
);
$selectDeleted
=
$deleted
?
0
:
1
;
$setDeleted
=
$deleted
?
1
:
0
;
$dbw
->
newUpdateQueryBuilder
()
->
update
(
'echo_event'
)
->
set
(
[
'event_deleted'
=>
$setDeleted
,
]
)
->
where
(
[
'event_deleted'
=>
$selectDeleted
,
'event_id'
=>
$eventIds
,
]
)
->
caller
(
__METHOD__
)
->
execute
();
}
/**
* Fetch events associated with a page
*
* @param int $pageId
* @return Event[] Events
*/
public
function
fetchByPage
(
$pageId
)
{
$events
=
[];
$seenEventIds
=
[];
$dbr
=
$this
->
dbFactory
->
getEchoDb
(
DB_REPLICA
);
// From echo_event
$res
=
$dbr
->
newSelectQueryBuilder
()
->
select
(
Event
::
selectFields
()
)
->
from
(
'echo_event'
)
->
where
(
[
'event_page_id'
=>
$pageId
]
)
->
caller
(
__METHOD__
)
->
fetchResultSet
();
foreach
(
$res
as
$row
)
{
$event
=
Event
::
newFromRow
(
$row
);
$events
[]
=
$event
;
$seenEventIds
[]
=
$event
->
getId
();
}
// From echo_target_page
$conds
=
[
'etp_page'
=>
$pageId
];
if
(
$seenEventIds
)
{
// Some events have both a title and target page(s).
// Skip the events that were already found in the echo_event table (the query above).
$conds
[]
=
$dbr
->
expr
(
'event_id'
,
'!='
,
$seenEventIds
);
}
$res
=
$dbr
->
newSelectQueryBuilder
()
->
select
(
Event
::
selectFields
()
)
->
distinct
()
->
from
(
'echo_event'
)
->
join
(
'echo_target_page'
,
null
,
'event_id=etp_event'
)
->
where
(
$conds
)
->
caller
(
__METHOD__
)
->
fetchResultSet
();
foreach
(
$res
as
$row
)
{
$events
[]
=
Event
::
newFromRow
(
$row
);
}
return
$events
;
}
/**
* Fetch event IDs associated with a page
*
* @param int $pageId
* @return int[] Event IDs
*/
public
function
fetchIdsByPage
(
$pageId
)
{
$events
=
$this
->
fetchByPage
(
$pageId
);
$eventIds
=
array_map
(
static
function
(
Event
$event
)
{
return
$event
->
getId
();
},
$events
);
return
$eventIds
;
}
/**
* Fetch events unread by a user and associated with a page
*
* @param UserIdentity $user
* @param int $pageId
* @return Event[]
*/
public
function
fetchUnreadByUserAndPage
(
UserIdentity
$user
,
$pageId
)
{
$dbr
=
$this
->
dbFactory
->
getEchoDb
(
DB_REPLICA
);
$fields
=
array_merge
(
Event
::
selectFields
(),
[
'notification_timestamp'
]
);
$res
=
$dbr
->
newSelectQueryBuilder
()
->
select
(
$fields
)
->
from
(
'echo_event'
)
->
join
(
'echo_notification'
,
null
,
'notification_event=event_id'
)
->
join
(
'echo_target_page'
,
null
,
'etp_event=event_id'
)
->
where
(
[
'event_deleted'
=>
0
,
'notification_user'
=>
$user
->
getId
(),
'notification_read_timestamp'
=>
null
,
'etp_page'
=>
$pageId
,
]
)
->
caller
(
__METHOD__
)
->
fetchResultSet
();
$data
=
[];
foreach
(
$res
as
$row
)
{
$data
[]
=
Event
::
newFromRow
(
$row
);
}
return
$data
;
}
/**
* Find out which of the given event IDs are orphaned, and delete them.
*
* An event is orphaned if it is not referred to by any rows in the echo_notification or
* echo_email_batch tables. If $ignoreUserId is set, rows for that user are not considered when
* determining orphanhood; if $ignoreUserTable is set, this only applies to that table.
* Use this when you've just recently deleted rows related to this user on the primary database, so that
* this function won't refuse to delete recently-orphaned events because it still sees the
* recently-deleted rows on the replica.
*
* @param array $eventIds Event IDs to check to see if they have become orphaned
* @param int|null $ignoreUserId Allow events to be deleted if the only referring rows
* have this user ID
* @param string|null $ignoreUserTable Restrict $ignoreUserId to this table only
* ('echo_notification' or 'echo_email_batch')
*/
public
function
deleteOrphanedEvents
(
array
$eventIds
,
$ignoreUserId
=
null
,
$ignoreUserTable
=
null
)
{
$dbw
=
$this
->
dbFactory
->
getEchoDb
(
DB_PRIMARY
);
$dbr
=
$this
->
dbFactory
->
getEchoDb
(
DB_REPLICA
);
$notifJoinConds
=
[];
$emailJoinConds
=
[];
if
(
$ignoreUserId
!==
null
)
{
if
(
$ignoreUserTable
===
null
||
$ignoreUserTable
===
'echo_notification'
)
{
$notifJoinConds
[]
=
$dbr
->
expr
(
'notification_user'
,
'!='
,
$ignoreUserId
);
}
if
(
$ignoreUserTable
===
null
||
$ignoreUserTable
===
'echo_email_batch'
)
{
$emailJoinConds
[]
=
$dbr
->
expr
(
'eeb_user_id'
,
'!='
,
$ignoreUserId
);
}
}
$orphanedEventIds
=
$dbr
->
newSelectQueryBuilder
()
->
select
(
'event_id'
)
->
from
(
'echo_event'
)
->
leftJoin
(
'echo_notification'
,
null
,
array_merge
(
[
'notification_event=event_id'
],
$notifJoinConds
)
)
->
leftJoin
(
'echo_email_batch'
,
null
,
array_merge
(
[
'eeb_event_id=event_id'
],
$emailJoinConds
)
)
->
where
(
[
'event_id'
=>
$eventIds
,
'notification_timestamp'
=>
null
,
'eeb_user_id'
=>
null
]
)
->
caller
(
__METHOD__
)
->
fetchFieldValues
();
if
(
$orphanedEventIds
)
{
$dbw
->
newDeleteQueryBuilder
()
->
deleteFrom
(
'echo_event'
)
->
where
(
[
'event_id'
=>
$orphanedEventIds
]
)
->
caller
(
__METHOD__
)
->
execute
();
$dbw
->
newDeleteQueryBuilder
()
->
deleteFrom
(
'echo_target_page'
)
->
where
(
[
'etp_event'
=>
$orphanedEventIds
]
)
->
caller
(
__METHOD__
)
->
execute
();
}
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Wed, Aug 19, 10:27 (2 w, 6 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
74/ef/d19a5e7d2f91dad59bd9ba3879aa
Default Alt Text
EventMapper.php (6 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment