jenkins-bot has submitted this change and it was merged.
Change subject: Add capability for managing campaigns
......................................................................
Add capability for managing campaigns
Bug: T90085
Change-Id: Ie69d855e32b7256aa3ceb38ebf559a677f894c88
---
M data/i18n/en.json
M data/i18n/qqq.json
A data/templates/admin/campaign.html
A data/templates/admin/campaigns.html
M data/templates/nav_user.html
M src/App.php
A src/Controllers/Admin/Campaign.php
A src/Controllers/Admin/Campaigns.php
M src/Controllers/Admin/User.php
M src/Dao/Campaigns.php
M src/Dao/Proposals.php
M src/Dao/Reports.php
12 files changed, 422 insertions(+), 12 deletions(-)
Approvals:
BryanDavis: Looks good to me, approved
jenkins-bot: Verified
diff --git a/data/i18n/en.json b/data/i18n/en.json
index 6d81318..d329907 100644
--- a/data/i18n/en.json
+++ b/data/i18n/en.json
@@ -1,7 +1,8 @@
{
"@metadata": {
"authors": [
- "Bryan Davis"
+ "Bryan Davis",
+ "Niharika Kohli"
]
},
"header-title": "IEG grant review",
@@ -21,6 +22,7 @@
"nav-admin": "Admin",
"nav-users": "Manage users",
"nav-account": "My Account",
+ "nav-campaigns": "Manage campaigns",
"new-account-subject": "New IEG review account",
"new-account-email": "A new IEG review account has been created for
you.\n\nYour login info is:\n\nusername: $1\npassword: $2\n\nYou may login at:
$3\n\nYou may change your password at: $4\n\nSincerely,\nIndividual Engagement
Grants team",
@@ -69,8 +71,8 @@
"admin-user-viewreports": "View reports?",
"admin-user-blocked": "Is blocked:",
"admin-user-save": "Save changes",
-
"admin-users-id": "Id",
+
"admin-users-username": "Username",
"admin-users-email": "Email",
"admin-users-admin": "Admin?",
@@ -81,8 +83,29 @@
"admin-users-yes": "yes",
"admin-users-no": "no",
"admin-users-add": "Add new user",
+ "admin-campaign-add": "Manage campaign",
"admin-users-form-go": "Search",
+ "admin-campaign-name": "Campaign in progress:",
+ "admin-campaign-end": "End campaign?",
+ "admin-campaign-start": "Create campaign",
+ "admin-campaign-start-date": "Start date:",
+ "admin-campaign-end-date": "End date:",
+ "admin-campaign-add": "Add new campaign",
+ "admin-campaign-manage": "Manage campaigns",
+ "admin-campaign-save": "Save",
+ "admin-campaign-new": "Name of campaign:",
+ "admin-campaigns-name": "Campaign name",
+ "admin-campaigns-add": "Add a campaign",
+ "admin-campaigns-form-go": "Search",
+ "admin-campaigns-start": "Start date",
+ "admin-campaigns-end": "End date",
+ "admin-campaigns-id": "ID",
+ "admin-campaign-create-success": "Campaign created succesfully.",
+ "admin-campaign-create-fail": "Campaign creation failed. Check logs.",
+ "admin-campaign-update-success": "Campaign updated.",
+ "admin-campaign-update-fail": "Error. Check logs.",
+
"page-of-pages": "Page $1 of $2",
"no-results": "No results found",
diff --git a/data/i18n/qqq.json b/data/i18n/qqq.json
index 279c528..86ebc0a 100644
--- a/data/i18n/qqq.json
+++ b/data/i18n/qqq.json
@@ -25,6 +25,23 @@
"admin-users-valid": "Table column header, is user
valid.\n{{Identical|Valid}}",
"admin-users-viewreports": "Table column header, is user allowed to run
reports.",
"admin-users-yes": "Table cell value indicating that true\/false value
is true.\n\nSee also:\n* {{msg-wm|Wsa-admin-users-no}}\n{{Identical|Yes}}",
+
+
+ "admin-campaign-add": "Navigation menu item, links to form for starting
a new campaign",
+ "admin-campaign-name": "Input label, followed by textbox",
+ "admin-campaign-end": "Table column header, end date for campagin",
+ "admin-campaign-start": "Table column header, start date for campaign",
+ "admin-campaign-start-date": "Input label, followed by textbox",
+ "admin-campaign-end-date": "Input label, followed by textbox",
+ "admin-campaign-manage": "Navigation menu item, links to form for
starting a new campaign",
+ "admin-campaigns-add": "Navigation menu item, links to form for
starting a new campaign",
+ "admin-campaigns-name": "Input label, followed by textbox",
+ "admin-campaigns-add": "Form submit button label",
+ "admin-campaigns-form-go": "Form submit button label.",
+ "admin-campaigns-start": "Input label, followed by textbox",
+ "admin-campaigns-end": "Input label, followed by textbox",
+ "admin-campaigns-id": "Table column header, ID of
campaign.\n{{Identical|ID}}",
+
"change-password": "Navigation menu item, links to password change
page.\n{{Identical|Change password}}",
"credits": "Credits page heading",
"credits-page-license": "Credits page content",
@@ -63,6 +80,7 @@
"nav-reports-wikitext": "Navigation menu label for wikitext export
report.",
"nav-reports-campaigns": "Navigation menu label for current and
previous campaigns report",
"nav-users": "Navigation menu label, links to user list page",
+ "nav-campaigns": "Navigation menu label, links to campaigns list page",
"new-account-email": "Email body. Parameters:\n* $1 - Account
username\n* $2 - Acocunt password\n* $3 - URL to login page of application\n*
$4 - URL to password change page of application",
"new-account-subject": "Email subject",
"new-password": "Input label, followed by text box.\n{{Identical|New
password}}",
diff --git a/data/templates/admin/campaign.html
b/data/templates/admin/campaign.html
new file mode 100644
index 0000000..5d7d92a
--- /dev/null
+++ b/data/templates/admin/campaign.html
@@ -0,0 +1,55 @@
+{% extends "admin/base.html" %}
+
+{% set errors = flash.form_errors|default([]) %}
+{% if flash.form_defaults|default(false) %}
+{% set campaign = flash.form_defaults %}
+{% endif %}
+
+{% block subtitle %}{{ 'nav-campaigns'|message }}{% endblock %}
+{% block content %}
+{% spaceless %}
+<ol class="breadcrumb">
+ <li>{{ 'nav-admin'|message }}</li>
+ <li><a href="{{ urlFor( 'admin_campaigns' ) }}">{{ 'nav-campaigns'|message
}}</a></li>
+ <li>{{ id }}</li>
+</ol>
+
+<form class="form-horizontal" method="post" action="{{ urlFor(
'admin_campaign_post' ) }}">
+ <input type="hidden" name="{{ csrf_param }}" value="{{ csrf_token }}" />
+ <input type="hidden" name="id" value="{{ id }}"/>
+
+ <div class="form-group {{ 'name' in errors ? 'has-error' }}">
+ <h4>Start a new campaign.</h4>
+ <label for="name" class="col-sm-2 control-label">
+ {{ 'admin-campaign-new'|message }}
+ </label>
+ <div class="col-sm-10">
+ <input type="text" class="form-control" name="name" id="name"
placeholder="Must be unique" value="{{ campaign.name }}" required="required">
+ </div>
+ </div>
+
+ <div class="form-group {{ 'start_date' in errors ? 'has-error' }}">
+ <label for="start_date" class="col-sm-2 control-label">
+ {{ 'admin-campaign-start-date'|message }}
+ </label>
+ <div class="col-sm-10">
+ <input type="date" class="form-control" name="start_date"
id="start_date" placeholder="YYYY-MM-DD HH:MM:SS (UTC only)" value="{{
campaign.start_date }}" required="required">
+ </div>
+ </div>
+
+ <div class="form-group {{ 'end_date' in errors ? 'has-error' }}">
+ <label for="end_date" class="col-sm-2 control-label">
+ {{ 'admin-campaign-end-date'|message }}
+ </label>
+ <div class="col-sm-10">
+ <input type="date" class="form-control" name="end_date" id="end_date"
placeholder="YYYY-MM-DD HH:MM:SS (UTC only)" value="{{ campaign.end_date }}"
required="required">
+ </div>
+ </div>
+
+ <div class="col-sm-10 col-sm-offset-2">
+ <input type="submit" class="btn btn-default" id="save" name="save"
value="{{ 'admin-campaign-save'|message }}"/>
+ </div>
+
+{% endspaceless %}
+{% endblock content %}
+
diff --git a/data/templates/admin/campaigns.html
b/data/templates/admin/campaigns.html
new file mode 100644
index 0000000..fdd6e05
--- /dev/null
+++ b/data/templates/admin/campaigns.html
@@ -0,0 +1,98 @@
+{% extends "admin/base.html" %}
+{% set route = app.router.getCurrentRoute.getName %}
+{% set ctx = _context %}
+
+{% macro showBool( val ) %}
+{{ val ? 'admin-users-yes'|message : 'admin-users-no'|message }}
+{% endmacro %}
+
+{% macro sortHeader( label, column, ctx, class ) %}
+{% set sorted = ctx.s == column %}
+{% if sorted %}
+ {% set o = ctx.o == 'desc' ? 'desc' : 'asc' %}
+ {% set nextO = o == 'asc' ? 'desc' : 'asc' %}
+{% else %}
+ {% set nextO = 'asc' %}
+{% endif %}
+<th><a class="sortable {{ sorted ? "sorted-#{o}" : 'unsorted' }} {{
class|default( '' ) }}" href="{{ urlFor( ctx.route ) }}?{{ qsMerge( {
's':column, 'o':nextO } ) }}">{{ label|message }}</a></th>
+{% endmacro %}
+
+{% block subtitle %}{{ 'nav-campaigns'|message }}{% endblock %}
+{% block content %}
+{% spaceless %}
+<ol class="breadcrumb">
+ <li>{{ 'nav-admin'|message }}</li>
+ <li>{{ 'nav-campaigns'|message }}</li>
+</ol>
+
+<form class="form-inline" method="get" action="{{ urlFor( route ) }}"
role="form">
+ <input type="hidden" name="p" value="0">
+ <div class="form-group">
+ <label class="sr-only" for="name">{{ 'admin-campaigns-name'|message
}}</label>
+ <input type="text" id="name" name="name" class="form-control"
placeholder="{{ 'admin-campaigns-name'|message }}" value="{{ name }}">
+ </div>
+
+ <div class="form-group">
+ <button type="submit" class="btn btn-sm btn-primary">
+ <i class="glyphicon glyphicon-search"></i>
+ {{ 'admin-campaigns-form-go'|message }}
+ </button>
+ </div>
+
+ {% if isadmin|default(false) %}
+ <div class="form-group">
+ <a class="btn btn-default" href="{{ urlFor( 'admin_campaign', { 'id':'new'
} ) }}">
+ <i class="glyphicon glyphicon-plus"></i>
+ {{ 'admin-campaigns-add'|message }}
+ </a>
+ </div>
+ {% endif %}
+</form>
+
+<p></p>
+
+<table class="table table-striped table-hover table-condensed
table-responsive">
+ <tr>
+ {{ _self.sortHeader( 'admin-campaigns-id', 'id', ctx, 'text-right' ) }}
+ {{ _self.sortHeader( 'admin-campaigns-name', 'name', ctx ) }}
+ {{ _self.sortHeader( 'admin-campaigns-start', 'start', ctx ) }}
+ {{ _self.sortHeader( 'admin-campaigns-end', 'end', ctx ) }}
+ </tr>
+ {% for row in records %}
+ <tr class="{{ cycle( [ 'oddrow', 'evenrow' ], loop.index ) }}">
+ <td class="text-right">{{ row.id }}</td>
+ <td><a href="{{ urlFor( 'admin_campaign', { 'id':row.id} ) }}">{{ row.name
}}</a></td>
+ <td>{{ row.start_date }}</td>
+ <td>{{ row.end_date }}</td>
+ </tr>
+ {% else %}
+ <tr><td colspan="8">{{ 'no-results'|message }}</td></tr>
+ {% endfor %}
+</table>
+
+<div class="row">
+ <div class="col-md-3">
+ <p class="text-right">{{ 'page-of-pages'|message( p + 1, pages ) }}</p>
+ </div>
+ <div class="col-md-9">
+ <ul class="pagination">
+ {% if p > 0 %}
+ <li><a href="{{ urlFor( route ) }}?{{ qsMerge( { 'p':(p - 1) } ) }}"
id="prev">«</a></li>
+ {% else %}
+ <li class="disabled"><span>«</span></li>
+ {% endif %}
+ {% if left > 0 %}<li class="disabled"><span>…</span></li>{% endif
%}
+ {% for i in left .. right %}
+ <li class="{{ i == p ? 'active' }}"><a href="{{ urlFor( route ) }}?{{
qsMerge( { 'p':i } ) }}" id="prev">{{ i + 1 }}</a></li>
+ {% endfor %}
+ {% if right < pages - 1 %}<li
class="disabled"><span>…</span></li>{% endif %}
+ {% if p + 1 < pages %}
+ <li><a href="{{ urlFor( route ) }}?{{ qsMerge( { 'p':(p + 1) } ) }}"
>»</a></li>
+ {% else %}
+ <li class="disabled"><span>»</span></li>
+ {% endif %}
+ </ul>
+ </div>
+</div>
+{% endspaceless %}
+{% endblock content %}
diff --git a/data/templates/nav_user.html b/data/templates/nav_user.html
index 3875e2f..4f7a260 100644
--- a/data/templates/nav_user.html
+++ b/data/templates/nav_user.html
@@ -30,6 +30,8 @@
<ul class="dropdown-menu">
<li><a href="{{ urlFor( 'admin_users' ) }}">{{ 'nav-users'|message
}}</a></li>
<li><a href="{{ urlFor( 'admin_user', { 'id':'new' } ) }}">{{
'admin-users-add'|message }}</a></li>
+ <li><a href="{{ urlFor( 'admin_campaigns' ) }}">{{
'admin-campaign-manage'|message }}</a></li>
+ <li><a href="{{ urlFor( 'admin_campaign', { 'id':'new' } ) }}">{{
'admin-campaign-add'|message }}</a></li>
</ul>
</li>
{% endif %}
diff --git a/src/App.php b/src/App.php
index a9e91f3..0181ce4 100644
--- a/src/App.php
+++ b/src/App.php
@@ -183,6 +183,15 @@
);
} );
+ $container->singleton( 'campaignsDao', function ( $c ) {
+ $uid = $c->authManager->getUserId();
+ return new \Wikimedia\IEGReview\Dao\Campaigns(
+ $c->settings['db.dsn'],
+ $c->settings['db.user'],
$c->settings['db.pass'],
+ $uid, $c->log
+ );
+ } );
+
$container->singleton( 'authManager', function ( $c ) {
return new \Wikimedia\IEGReview\AuthManager(
$c->usersDao );
} );
@@ -535,6 +544,24 @@
$page->setMailer( $slim->mailer );
$page();
} )->name( 'admin_user_post' );
+
+ $slim->get( 'campaigns', function () use (
$slim ) {
+ $page = new
Controllers\Admin\Campaigns( $slim );
+ $page->setDao( $slim->campaignsDao );
+ $page();
+ } )->name( 'admin_campaigns' );
+
+ $slim->get( 'campaign/:id', function ( $id )
use ( $slim ) {
+ $page = new Controllers\Admin\Campaign(
$slim );
+ $page->setDao( $slim->campaignsDao );
+ $page( $id );
+ } )->name( 'admin_campaign' );
+
+ $slim->post( 'campaign.post', function () use (
$slim ) {
+ $page = new Controllers\Admin\Campaign(
$slim );
+ $page->setDao( $slim->campaignsDao );
+ $page();
+ } )->name( 'admin_campaign_post' );
} );
$slim->notFound( function () use ( $slim, $middleware ) {
diff --git a/src/Controllers/Admin/Campaign.php
b/src/Controllers/Admin/Campaign.php
new file mode 100644
index 0000000..5bb04b6
--- /dev/null
+++ b/src/Controllers/Admin/Campaign.php
@@ -0,0 +1,103 @@
+<?php
+/**
+ * @section LICENSE
+ * This file is part of Wikimedia IEG Grant Review application.
+ *
+ * Wikimedia IEG Grant Review application is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * Wikimedia IEG Grant Review application is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with Wikimedia IEG Grant Review application. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @copyright © 2015 Niharika Kohli, Wikimedia Foundation and contributors.
+ */
+
+namespace Wikimedia\IEGReview\Controllers\Admin;
+
+use Wikimedia\IEGReview\Controller;
+use Wikimedia\IEGReview\Password;
+
+/**
+ * Add a new campaign.
+ *
+ * @author Niharika Kohli <[email protected]>
+ * @copyright © 2014 Niharika Kohli, Wikimedia Foundation and contributors.
+ */
+class Campaign extends Controller {
+
+ protected function handleGet( $id ) {
+ if ( $id === 'new' ) {
+ $campaign = array(
+ 'name' => '',
+ 'start_date' => date( 'Y-m-d H:i:s' ),
+ 'end_date' => date( 'Y-m-d H:i:s' ),
+ );
+
+ } else {
+ $campaign = $this->dao->getCampaign( $id );
+ }
+ $this->view->set( 'id', $id );
+ $this->view->set( 'campaign', $campaign );
+ $this->render( 'admin/campaign.html' );
+ }
+
+
+ protected function handlePost() {
+ $id = $this->request->post( 'id' );
+
+ $this->form->expectString( 'name', array( 'required' => true )
);
+ // TODO: expectDate instead of expectString
+ $this->form->expectString( 'start_date', array( 'required' =>
'true' ) );
+ $this->form->expectString( 'end_date', array( 'required' =>
true ) );
+
+ if ( $this->form->validate() ) {
+ $params = array(
+ 'name' => $this->form->get( 'name' ),
+ 'start_date' => $this->form->get( 'start_date'
),
+ 'end_date' => $this->form->get( 'end_date' ),
+ );
+
+ if ( $id == 'new' ) {
+ // This is a temporary fix to make the *just
started* campaign active
+ // and bypass the actual start and end date
+ // to be fixed in a subsequent patch when
actual logic for using
+ // start and end dates is implemented
+ $params['status'] = 1;
+
+ $newCampaign = $this->dao->addCampaign( $params
);
+ if ( $newCampaign !== false ) {
+ $this->flash( 'info',
+ $this->i18nContext->message(
'admin-campaign-create-success' )
+ );
+ $id = $newCampaign;
+ } else {
+ $this->flash( 'error',
+
$this->i18nContext->message('admin-campaign-create-fail' )
+ );
+ }
+ } else {
+ if ( $this->dao->updateCampaign( $params, $id )
) {
+ $this->flash( 'info',
+
$this->i18nContext->message('admin-campaign-update-success' )
+ );
+ } else {
+ $this->flash( 'error',
+
$this->i18nContext->message('admin-campaign-update-fail' )
+ );
+ }
+ }
+
+ $this->redirect( $this->urlFor( 'admin_campaign', array( 'id'
=> $id ) ) );
+ }
+
+}
+}
diff --git a/src/Controllers/Admin/Campaigns.php
b/src/Controllers/Admin/Campaigns.php
new file mode 100644
index 0000000..a21d7b4
--- /dev/null
+++ b/src/Controllers/Admin/Campaigns.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * @section LICENSE
+ * This file is part of Wikimedia IEG Grant Review application.
+ *
+ * Wikimedia IEG Grant Review application is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * Wikimedia IEG Grant Review application is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with Wikimedia IEG Grant Review application. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @copyright © 2015 Niharika Kohli, Wikimedia Foundation and contributors.
+ */
+
+namespace Wikimedia\IEGReview\Controllers\Admin;
+
+use Wikimedia\IEGReview\Controller;
+use Wikimedia\IEGReview\Password;
+
+/**
+ * View/edit a campaign.
+ *
+ * @author Niharika Kohli <[email protected]>
+ * @copyright © 2014 Niharika Kohli, Wikimedia Foundation and contributors.
+ */
+class Campaigns extends Controller {
+
+ protected function handleGet() {
+ $this->form->expectString( 'name' );
+ $this->form->expectInt( 'items',
+ array( 'min_range' => 1, 'max_range' => 250, 'default'
=> 50 )
+ );
+ $this->form->expectInt( 'p', array( 'min_range' => 0, 'default'
=> 0 ) );
+ $this->form->expectString( 's', array( 'default' => 'id' ) );
+ $this->form->expectInArray( 'o', array( 'asc', 'desc' ),
+ array( 'default' => 'asc' )
+ );
+ $this->form->validate( $_GET );
+
+ $this->view->set( 'name', $this->form->get( 'name' ) );
+ $this->view->set( 'items', $this->form->get( 'items' ) );
+ $this->view->set( 'p', $this->form->get( 'p' ) );
+ $this->view->set( 's', $this->form->get( 's' ) );
+ $this->view->set( 'o', $this->form->get( 'o' ) );
+
+ $params = array(
+ 'name' => $this->form->get( 'name' ),
+ 'sort' => $this->form->get( 's' ),
+ 'order' => $this->form->get( 'o' ),
+ 'items' => $this->form->get( 'items' ),
+ 'page' => $this->form->get( 'p' ),
+ );
+
+ $ret = $this->dao->search( $params );
+ $this->view->set( 'records', $ret->rows );
+ $this->view->set( 'found', $ret->found );
+
+ // pagination information
+ list( $pageCount, $first, $last ) = $this->pagination(
+ $ret->found, $this->form->get( 'p' ), $this->form->get(
'items' ) );
+ $this->view->set( 'pages' , $pageCount );
+ $this->view->set( 'left', $first );
+ $this->view->set( 'right', $last );
+
+ $this->render( 'admin/campaigns.html' );
+ }
+
+}
diff --git a/src/Controllers/Admin/User.php b/src/Controllers/Admin/User.php
index 07b8242..8329883 100644
--- a/src/Controllers/Admin/User.php
+++ b/src/Controllers/Admin/User.php
@@ -50,7 +50,7 @@
} else {
$user = $this->dao->getUserInfo( $id );
}
-
+
$this->view->set( 'id', $id );
$this->view->set( 'u', $user );
$this->render( 'admin/user.html' );
diff --git a/src/Dao/Campaigns.php b/src/Dao/Campaigns.php
index 9c5f778..dc1d08a 100644
--- a/src/Dao/Campaigns.php
+++ b/src/Dao/Campaigns.php
@@ -57,7 +57,6 @@
);
}
-
/*
* @param int $id ID of campaign whose data is to be fetched
*/
@@ -185,6 +184,5 @@
);
return $this->fetchAllWithFound( $sql, $crit );
}
-
}
diff --git a/src/Dao/Proposals.php b/src/Dao/Proposals.php
index fb19528..7ab15ef 100644
--- a/src/Dao/Proposals.php
+++ b/src/Dao/Proposals.php
@@ -72,6 +72,17 @@
}
/*
+ * @param int $id ID of campaign to fetch
+ */
+ public function getProposal( $id ) {
+ return $this->fetch(
+ 'SELECT * FROM proposals WHERE id = ?',
+ array( $id )
+ );
+ }
+
+
+ /*
* @return Array $campaigns campaign data for all campaigns
*/
public function getCampaigns() {
@@ -83,13 +94,11 @@
return $campaigns;
}
- public function getProposal( $id ) {
- return $this->fetch(
- 'SELECT * FROM proposals WHERE id = ?',
- array( $id )
- );
- }
+ /*
+ * @param int $id ID of campaign to update
+ * @param array $data Camapign data
+ */
public function updateProposal( $id, $data ) {
$fields = array(
'title', 'description', 'url', 'amount', 'theme',
'notes',
diff --git a/src/Dao/Reports.php b/src/Dao/Reports.php
index f127693..59a6294 100644
--- a/src/Dao/Reports.php
+++ b/src/Dao/Reports.php
@@ -246,4 +246,4 @@
return $this->fetchAllWithFound( $sql, $crit );
}
-}
\ No newline at end of file
+}
--
To view, visit https://gerrit.wikimedia.org/r/188045
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ie69d855e32b7256aa3ceb38ebf559a677f894c88
Gerrit-PatchSet: 12
Gerrit-Project: wikimedia/iegreview
Gerrit-Branch: master
Gerrit-Owner: Niharika29 <[email protected]>
Gerrit-Reviewer: BryanDavis <[email protected]>
Gerrit-Reviewer: Niharika29 <[email protected]>
Gerrit-Reviewer: Siebrand <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits