Skip to content

Commit 87513eb

Browse files
authored
Merge pull request #85 from VSEphpbb/issue/75
Add implemented phpBB version
2 parents 0d0a44c + 54d9eac commit 87513eb

10 files changed

Lines changed: 216 additions & 33 deletions

File tree

controller/idea_controller.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,23 @@ public function ticket()
202202
return false;
203203
}
204204

205+
/**
206+
* Implemented action (sets an idea's implemented phpBB version)
207+
*
208+
* @return bool True if set, false if not
209+
* @access public
210+
*/
211+
public function implemented()
212+
{
213+
if ($this->is_mod() && check_link_hash($this->get_hash(), "implemented_{$this->data['idea_id']}"))
214+
{
215+
$version = $this->request->variable('implemented', '');
216+
return $this->ideas->set_implemented($this->data['idea_id'], $version);
217+
}
218+
219+
return false;
220+
}
221+
205222
/**
206223
* Title action (sets an idea's title)
207224
*

event/listener.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ public function show_idea($event)
219219
'IDEA_DUPLICATE' => $idea['duplicate_id'],
220220
'IDEA_RFC' => $idea['rfc_link'],
221221
'IDEA_TICKET' => $idea['ticket_id'],
222+
'IDEA_IMPLEMENTED' => $idea['implemented_version'],
222223

223224
'U_IDEA_DUPLICATE' => $this->link_helper->get_idea_link((int) $idea['duplicate_id']),
224225

@@ -229,6 +230,7 @@ public function show_idea($event)
229230
'U_CHANGE_STATUS' => $this->link_helper->get_idea_link($idea['idea_id'], 'status', true),
230231
'U_EDIT_DUPLICATE' => $this->link_helper->get_idea_link($idea['idea_id'], 'duplicate', true),
231232
'U_EDIT_RFC' => $this->link_helper->get_idea_link($idea['idea_id'], 'rfc', true),
233+
'U_EDIT_IMPLEMENTED'=> $this->link_helper->get_idea_link($idea['idea_id'], 'implemented', true),
232234
'U_EDIT_TICKET' => $this->link_helper->get_idea_link($idea['idea_id'], 'ticket', true),
233235
'U_REMOVE_VOTE' => $this->link_helper->get_idea_link($idea['idea_id'], 'removevote', true),
234236
'U_IDEA_VOTE' => $this->link_helper->get_idea_link($idea['idea_id'], 'vote', true),

factory/ideas.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,31 @@ public function set_ticket($idea_id, $ticket)
351351
return true;
352352
}
353353

354+
/**
355+
* Sets the implemented version of an idea.
356+
*
357+
* @param int $idea_id ID of the idea to be updated.
358+
* @param string $version Version of phpBB the idea was implemented in.
359+
*
360+
* @return bool True if set, false if invalid.
361+
*/
362+
public function set_implemented($idea_id, $version)
363+
{
364+
$match = '/^\d\.\d\.\d+(\-\w+)?$/';
365+
if ($version && !preg_match($match, $version))
366+
{
367+
return false;
368+
}
369+
370+
$sql_ary = array(
371+
'implemented_version' => $version, // string is escaped by build_array()
372+
);
373+
374+
$this->update_idea_data($sql_ary, $idea_id, $this->table_ideas);
375+
376+
return true;
377+
}
378+
354379
/**
355380
* Sets the title of an idea.
356381
*

language/en/common.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@
4343
'IDEAS_TITLE' => 'phpBB Ideas',
4444
'IDEAS_NOT_AVAILABLE' => 'Ideas is not available at this time.',
4545
'IMPLEMENTED' => 'Implemented',
46+
'IMPLEMENTED_ERROR' => 'Must be a valid phpBB version number.',
4647
'IMPLEMENTED_IDEAS' => 'Recently Implemented Ideas',
48+
'IMPLEMENTED_VERSION' => 'phpBB version',
4749
'IN_PROGRESS' => 'In Progress',
4850
'INVALID' => 'Invalid',
4951
'INVALID_VOTE' => 'Invalid vote; the number you entered was invalid.',
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
/**
3+
*
4+
* Ideas extension for the phpBB Forum Software package.
5+
*
6+
* @copyright (c) phpBB Limited <https://www.phpbb.com>
7+
* @license GNU General Public License, version 2 (GPL-2.0)
8+
*
9+
*/
10+
11+
namespace phpbb\ideas\migrations;
12+
13+
class m8_implemented_version extends \phpbb\db\migration\migration
14+
{
15+
public function effectively_installed()
16+
{
17+
return $this->db_tools->sql_column_exists($this->table_prefix . 'ideas_ideas', 'implemented_version');
18+
}
19+
20+
static public function depends_on()
21+
{
22+
return array(
23+
'\phpbb\ideas\migrations\m1_initial_schema',
24+
'\phpbb\ideas\migrations\m4_update_statuses',
25+
'\phpbb\ideas\migrations\m6_migrate_old_tables',
26+
'\phpbb\ideas\migrations\m7_drop_old_tables',
27+
);
28+
}
29+
30+
public function update_schema()
31+
{
32+
return array(
33+
'add_columns' => array(
34+
$this->table_prefix . 'ideas_ideas' => array(
35+
'implemented_version' => array('VCHAR', ''),
36+
),
37+
),
38+
);
39+
}
40+
41+
public function revert_schema()
42+
{
43+
return array(
44+
'drop_columns' => array(
45+
$this->table_prefix . 'ideas_ideas' => array(
46+
'implemented_version',
47+
),
48+
),
49+
);
50+
}
51+
}

styles/prosilver/template/idea_body.html

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,25 @@
7575
</dd>
7676
{% endif %}
7777
{% if IDEA_DUPLICATE or S_IS_MOD %}
78-
<dt class="duplicatetoggle idealabel"{% if IDEA_STATUS_ID != 4 %} style="display:none"{% endif %}>{{ lang('DUPLICATE') ~ lang('COLON') }}</dt>
79-
<dd class="duplicatetoggle" {% if IDEA_STATUS_ID != 4 %}style="display:none"{% endif %}>
78+
<dt class="duplicatetoggle idealabel"{% if IDEA_STATUS_ID != STATUS_ARY.DUPLICATE %} style="display:none"{% endif %}>{{ lang('DUPLICATE') ~ lang('COLON') }}</dt>
79+
<dd class="duplicatetoggle" {% if IDEA_STATUS_ID != STATUS_ARY.DUPLICATE %}style="display:none"{% endif %}>
8080
<a id="duplicatelink" class="ideamodbtn" data-link="{{ U_IDEA_DUPLICATE }}" data-l-msg="{{ lang('IDEA_NUM') }}" {% if IDEA_DUPLICATE %}href="{{ U_IDEA_DUPLICATE }}">{{ lang('IDEA_NUM') }}{{ IDEA_DUPLICATE }}{% else %}style="display:none">{% endif %}</a>
8181
{% if S_IS_MOD %}
8282
<a href="{{ U_EDIT_DUPLICATE }}" id="duplicateedit" data-l-add="{{ lang('ADD') }}" data-l-edit="{{ lang('EDIT') }}">{% if IDEA_DUPLICATE %}<i class="fa fa-fw fa-pencil"></i>{{ lang('EDIT') }}{% else %}<i class="fa fa-fw fa-plus-circle"></i>{{ lang('ADD') }}{% endif %}</a>
8383
<input type="text" id="duplicateeditinput" class="ideainput"{% if IDEA_DUPLICATE %} value="{{ IDEA_DUPLICATE }}"{% endif %} placeholder="###" data-l-err="{{ lang('ERROR') }}" data-l-msg="{{ lang('TICKET_ERROR_DUP') }}" />
8484
{% endif %}
8585
</dd>
8686
{% endif %}
87+
{% if IDEA_IMPLEMENTED or S_IS_MOD %}
88+
<dt class="implementedtoggle idealabel"{% if IDEA_STATUS_ID != STATUS_ARY.IMPLEMENTED %} style="display:none"{% endif %}>{{ lang('IMPLEMENTED_VERSION') ~ lang('COLON') }}</dt>
89+
<dd class="implementedtoggle" {% if IDEA_STATUS_ID != STATUS_ARY.IMPLEMENTED %}style="display:none"{% endif %}>
90+
<span id="implementedversion"{% if not IDEA_IMPLEMENTED %} style="display:none;"{% endif %}>{{ IDEA_IMPLEMENTED }}</span>
91+
{% if S_IS_MOD %}
92+
<a href="{{ U_EDIT_IMPLEMENTED }}" id="implementededit" data-l-add="{{ lang('ADD') }}" data-l-edit="{{ lang('EDIT') }}">{% if IDEA_IMPLEMENTED %}<i class="fa fa-fw fa-pencil"></i>{{ lang('EDIT') }}{% else %}<i class="fa fa-fw fa-plus-circle"></i>{{ lang('ADD') }}{% endif %}</a>
93+
<input type="text" id="implementededitinput" class="ideainput"{% if IDEA_IMPLEMENTED %} value="{{ IDEA_IMPLEMENTED }}"{% endif %} placeholder="3.x.x" data-l-err="{{ lang('ERROR') }}" data-l-msg="{{ lang('IMPLEMENTED_ERROR') }}" />
94+
{% endif %}
95+
</dd>
96+
{% endif %}
8797
</dl>
8898
</div>
8999
</div>

styles/prosilver/template/ideas.js

Lines changed: 72 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
rfcEdit: $('#rfcedit'),
2020
rfcEditInput: $('#rfceditinput'),
2121
rfcLink: $('#rfclink'),
22+
implementedEdit: $('#implementededit'),
23+
implementedEditInput: $('#implementededitinput'),
24+
implementedVersion: $('#implementedversion'),
25+
implementedToggle: $('.implementedtoggle'),
2226
removeVote: $('.removevote'),
2327
status: $('#status'),
2428
successVoted: $('.successvoted'),
@@ -126,11 +130,8 @@
126130
.removeClass()
127131
.addClass('status-badge status-' + $this.find(':selected').val());
128132

129-
if (idea_is_duplicate()) {
130-
$obj.duplicateToggle.show();
131-
} else {
132-
$obj.duplicateToggle.hide();
133-
}
133+
$obj.duplicateToggle.toggle(idea_is_duplicate());
134+
$obj.implementedToggle.toggle(idea_is_implemented());
134135
}
135136
});
136137
});
@@ -168,11 +169,7 @@
168169

169170
$this.hide();
170171

171-
$obj.rfcEdit.text(function() {
172-
return value ? $(this).attr('data-l-edit') : $(this).attr('data-l-add');
173-
}).prepend($('<i class="fa fa-fw"></i>').addClass(function() {
174-
return value ? 'fa-pencil' : 'fa-plus-circle';
175-
})).show();
172+
$obj.rfcEdit.toggleAddEdit(value);
176173
}
177174
});
178175
} else if (e.keyCode === keymap.ESC) {
@@ -226,11 +223,7 @@
226223

227224
$this.hide();
228225

229-
$obj.ticketEdit.text(function() {
230-
return value ? $(this).attr('data-l-edit') : $(this).attr('data-l-add');
231-
}).prepend($('<i class="fa fa-fw"></i>').addClass(function() {
232-
return value ? 'fa-pencil' : 'fa-plus-circle';
233-
})).show();
226+
$obj.ticketEdit.toggleAddEdit(value);
234227
}
235228

236229
});
@@ -287,11 +280,7 @@
287280

288281
$this.hide();
289282

290-
$obj.duplicateEdit.text(function() {
291-
return value ? $(this).attr('data-l-edit') : $(this).attr('data-l-add');
292-
}).prepend($('<i class="fa fa-fw"></i>').addClass(function() {
293-
return value ? 'fa-pencil' : 'fa-plus-circle';
294-
})).show();
283+
$obj.duplicateEdit.toggleAddEdit(value);
295284
}
296285
});
297286
} else if (e.keyCode === keymap.ESC) {
@@ -308,6 +297,61 @@
308297
}
309298
});
310299

300+
$obj.implementedEdit.on('click', function(e) {
301+
e.preventDefault();
302+
303+
$obj.implementedEdit.add($obj.implementedVersion).hide();
304+
$obj.implementedEditInput.show().focus();
305+
});
306+
307+
$obj.implementedEditInput.on('keydown', function(e) {
308+
if (e.keyCode === keymap.ENTER) {
309+
e.preventDefault();
310+
e.stopPropagation();
311+
312+
var $this = $(this),
313+
find = /^\d\.\d\.\d+(\-\w+)?$/,
314+
url = $obj.implementedEdit.attr('href'),
315+
value = $this.val();
316+
317+
if (value && !find.test(value)) {
318+
phpbb.alert($this.attr('data-l-err'), $this.attr('data-l-msg'));
319+
return;
320+
}
321+
322+
$.get(url, {implemented: value}, function(res) {
323+
if (res) {
324+
$obj.implementedVersion.text(value);
325+
326+
if (value) {
327+
$obj.implementedVersion.show();
328+
}
329+
330+
$this.hide();
331+
332+
$obj.implementedEdit.toggleAddEdit(value);
333+
}
334+
});
335+
} else if (e.keyCode === keymap.ESC) {
336+
e.preventDefault();
337+
338+
$(this).hide();
339+
$obj.implementedEdit.show();
340+
341+
if ($obj.implementedVersion.text()) {
342+
$obj.implementedVersion.show();
343+
}
344+
}
345+
});
346+
347+
$.fn.toggleAddEdit = function(value) {
348+
$(this).text(function() {
349+
return value ? $(this).attr('data-l-edit') : $(this).attr('data-l-add');
350+
}).prepend($('<i class="fa fa-fw"></i>').addClass(function() {
351+
return value ? 'fa-pencil' : 'fa-plus-circle';
352+
})).show();
353+
};
354+
311355
/**
312356
* Returns true if idea is a duplicate. Bit hacky.
313357
*/
@@ -316,6 +360,14 @@
316360
return href && href.indexOf('status=4') !== -1;
317361
}
318362

363+
/**
364+
* Returns true if idea is implemented. Bit hacky.
365+
*/
366+
function idea_is_implemented() {
367+
var href = $obj.status.prev('a').attr('href');
368+
return href && href.indexOf('status=3') !== -1;
369+
}
370+
319371
function displayVoters(data) {
320372

321373
var upVoters = [],

tests/controller/idea_controller_test.php

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,25 @@ public function controller_test_data()
2323
{
2424
return array(
2525
array(1, '', '', false, null, null, 302), // non-ajax
26-
array(2, 'delete', 'delete', true, true, '{}', 200), // ajax delete success (confirm fail)
27-
array(2, 'delete', 'delete', true, false, 'NO_AUTH_OPERATION', 403), // ajax delete fail
26+
array(2, 'delete', '', true, true, '{}', 200), // ajax delete success (confirm fail)
27+
array(2, 'delete', '', true, false, 'NO_AUTH_OPERATION', 403), // ajax delete fail
2828
array(2, 'delete', 'delete', true, true, 'trigger_error', 200), // ajax delete success (confirm true)
2929
array(3, 'duplicate', 'set_duplicate', true, true, 'true', 200), // ajax set duplicate success
30-
array(3, 'duplicate', 'set_duplicate', true, false, 'false', 200), // ajax set duplicate fail
30+
array(3, 'duplicate', '', true, false, 'false', 200), // ajax set duplicate fail
3131
array(4, 'removevote', 'remove_vote', true, true, 'true', 200), // ajax set title success
32-
array(4, 'removevote', 'remove_vote', true, false, '"You do not have the necessary permissions to complete this operation."', 200), // ajax set title fail
32+
array(4, 'removevote', '', true, false, '"You do not have the necessary permissions to complete this operation."', 200), // ajax set title fail
3333
array(5, 'rfc', 'set_rfc', true, true, 'true', 200), // ajax set rfc success
34-
array(5, 'rfc', 'set_rfc', true, false, 'false', 200), // ajax set rfc fail
35-
array(6, 'status', 'set_status', true, true, 'true', 200), // ajax set status success
36-
array(6, 'status', 'set_status', true, false, 'false', 200), // ajax set status fail
34+
array(5, 'rfc', '', true, false, 'false', 200), // ajax set rfc fail
35+
array(6, 'status', 'change_status', true, true, 'true', 200), // ajax set status success
36+
array(6, 'status', '', true, false, 'false', 200), // ajax set status fail
3737
array(7, 'ticket', 'set_ticket', true, true, 'true', 200), // ajax set ticket success
38-
array(7, 'ticket', 'set_ticket', true, false, 'false', 200), // ajax set ticket fail
38+
array(7, 'ticket', '', true, false, 'false', 200), // ajax set ticket fail
3939
array(8, 'title', 'set_title', true, true, 'true', 200), // ajax set title success
40-
array(8, 'title', 'set_title', true, false, 'false', 200), // ajax set title fail
40+
array(8, 'title', '', true, false, 'false', 200), // ajax set title fail
4141
array(9, 'vote', 'vote', true, true, 'true', 200), // ajax set title success
42-
array(9, 'vote', 'vote', true, false, '"You do not have the necessary permissions to complete this operation."', 200), // ajax set title fail
42+
array(9, 'vote', '', true, false, '"You do not have the necessary permissions to complete this operation."', 200), // ajax set title fail
43+
array(10, 'implemented', 'set_implemented', true, true, 'true', 200), // ajax set implemented success
44+
array(10, 'implemented', '', true, false, 'false', 200), // ajax set implemented fail
4345
);
4446
}
4547

@@ -56,7 +58,7 @@ public function test_controller($idea_id, $mode, $callback, $is_ajax, $authorise
5658
->will($this->returnValue(array('idea_id' => $idea_id, 'idea_author' => 2)));
5759

5860
// mock a result from each method called by the idea controller
59-
$this->ideas->expects($this->any())
61+
$this->ideas->expects(($callback !== '' ? $this->once() : $this->never()))
6062
->method($callback)
6163
->will($this->returnValue($authorised));
6264

0 commit comments

Comments
 (0)