Skip to content

Commit 92cf571

Browse files
committed
Merge branch 'master' into dev/4.0
2 parents 2b88e4f + 5fbffae commit 92cf571

11 files changed

Lines changed: 254 additions & 19 deletions

File tree

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
name: Sync develop branch
2+
3+
on:
4+
push:
5+
branches:
6+
# Keep this in sync with SYNC_SOURCE_BRANCH below.
7+
# GitHub Actions does not allow env values in trigger branch filters.
8+
- master
9+
10+
env:
11+
SYNC_SOURCE_BRANCH: master
12+
SYNC_TARGET_BRANCH: dev/4.0
13+
14+
permissions:
15+
contents: write
16+
17+
concurrency:
18+
group: ${{ github.workflow }}-${{ github.ref }}
19+
cancel-in-progress: false
20+
21+
jobs:
22+
sync-dev-branch:
23+
name: Merge master into dev/4.0 branch
24+
# Keep this named after the GitHub repository.
25+
# GitHub Actions does not allow workflow env values in jobs.<job_id>.if.
26+
if: github.repository == 'phpbb/ideas' && github.event.repository.fork == false
27+
runs-on: ubuntu-latest
28+
29+
steps:
30+
- name: Check out repository
31+
uses: actions/checkout@v6
32+
with:
33+
fetch-depth: 0
34+
35+
- name: Configure Git author
36+
run: |
37+
git config user.name "github-actions[bot]"
38+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
39+
40+
- name: Merge source branch into target branch when clean
41+
run: |
42+
if ! git ls-remote --exit-code --heads origin "${SYNC_TARGET_BRANCH}" > /dev/null 2>&1; then
43+
echo "origin/${SYNC_TARGET_BRANCH} does not exist; skipping."
44+
exit 0
45+
fi
46+
47+
git fetch --no-tags --prune origin "${SYNC_TARGET_BRANCH}"
48+
git checkout -B "${SYNC_TARGET_BRANCH}" "origin/${SYNC_TARGET_BRANCH}"
49+
50+
if git merge --no-edit "$GITHUB_SHA"; then
51+
if [ "$(git rev-list --count "origin/${SYNC_TARGET_BRANCH}..HEAD")" -eq 0 ]; then
52+
echo "${SYNC_TARGET_BRANCH} is already up to date."
53+
exit 0
54+
fi
55+
56+
git push origin "HEAD:${SYNC_TARGET_BRANCH}"
57+
else
58+
echo "${SYNC_SOURCE_BRANCH} could not be merged cleanly into ${SYNC_TARGET_BRANCH}; skipping."
59+
if git rev-parse -q --verify MERGE_HEAD > /dev/null; then
60+
git merge --abort
61+
fi
62+
exit 1
63+
fi

controller/index_controller.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public function index()
5454
'U_VIEW_IN_PROGRESS'=> $this->helper->route('phpbb_ideas_list_controller', ['sort' => ext::SORT_DATE, 'status' => ext::$statuses['IN_PROGRESS']]),
5555
'U_POST_ACTION' => $this->helper->route('phpbb_ideas_post_controller'),
5656
'U_MCP' => ($this->auth->acl_get('m_', $this->config['ideas_forum_id'])) ? append_sid("{$this->root_path}mcp.$this->php_ext", "f={$this->config['ideas_forum_id']}&amp;i=main&amp;mode=forum_view", true, $this->user->session_id) : '',
57+
'STATISTICS' => $this->entity->get_statistics(),
5758
));
5859

5960
// Assign breadcrumb template vars

event/listener.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ public static function getSubscribedEvents()
9191
'core.posting_modify_template_vars' => 'submit_idea_template',
9292
'core.posting_modify_submit_post_before' => 'submit_idea_before',
9393
'core.posting_modify_submit_post_after' => [['submit_idea_after'], ['edit_idea_title']],
94+
'core.mcp_change_poster_after' => 'change_idea_author',
9495
);
9596
}
9697

@@ -390,6 +391,28 @@ public function edit_idea_title($event)
390391
$this->idea->set_title($idea['idea_id'], $event['post_data']['post_subject']);
391392
}
392393

394+
/**
395+
* Change an idea's author when the post author is changed
396+
*
397+
* @param \phpbb\event\data $event The event object
398+
* @return void
399+
*/
400+
public function change_idea_author($event)
401+
{
402+
$forum_id = (int) $event['post_info']['forum_id'];
403+
$topic_id = (int) $event['post_info']['topic_id'];
404+
$old_author_id = (int) $event['post_info']['poster_id'];
405+
$new_author_id = (int) $event['userdata']['user_id'];
406+
407+
if ($old_author_id === $new_author_id || !$this->is_ideas_forum($forum_id))
408+
{
409+
return;
410+
}
411+
412+
$idea = $this->idea->get_idea_by_topic_id($topic_id);
413+
$this->idea->set_author($idea['idea_id'], $new_author_id);
414+
}
415+
393416
/**
394417
* Test if we are on the posting page for a new idea
395418
*

factory/idea.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,29 @@ public function get_title($id)
227227
return $idea_title ?: '';
228228
}
229229

230+
/**
231+
* Set the author of an idea
232+
*
233+
* @param int $idea_id
234+
* @param int $user_id
235+
* @return bool True if set, false if invalid.
236+
*/
237+
public function set_author($idea_id, $user_id)
238+
{
239+
if (!$user_id || !is_numeric($user_id))
240+
{
241+
return false;
242+
}
243+
244+
$sql_ary = array(
245+
'idea_author' => (int) $user_id,
246+
);
247+
248+
$this->update_idea_data($sql_ary, $idea_id, $this->table_ideas);
249+
250+
return true;
251+
}
252+
230253
/**
231254
* Submit new idea data to the ideas table
232255
*

factory/ideas.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,4 +296,35 @@ public function get_idea_count()
296296
{
297297
return $this->idea_count ?? 0;
298298
}
299+
300+
/**
301+
* Get statistics - counts of total ideas and of each status type
302+
*
303+
* @return array
304+
*/
305+
public function get_statistics()
306+
{
307+
// the CASE/WHEN SQL approach is better for performance than processing in PHP
308+
$sql = 'SELECT
309+
COUNT(*) as total,
310+
SUM(CASE WHEN idea_status = ' . (int) ext::$statuses['IMPLEMENTED'] . ' THEN 1 ELSE 0 END) as implemented,
311+
SUM(CASE WHEN idea_status = ' . (int) ext::$statuses['IN_PROGRESS'] . ' THEN 1 ELSE 0 END) as in_progress,
312+
SUM(CASE WHEN idea_status = ' . (int) ext::$statuses['DUPLICATE'] . ' THEN 1 ELSE 0 END) as duplicate,
313+
SUM(CASE WHEN idea_status = ' . (int) ext::$statuses['INVALID'] . ' THEN 1 ELSE 0 END) as invalid,
314+
SUM(CASE WHEN idea_status = ' . (int) ext::$statuses['NEW'] . ' THEN 1 ELSE 0 END) as new
315+
FROM ' . $this->table_ideas;
316+
317+
$result = $this->db->sql_query($sql);
318+
$row = $this->db->sql_fetchrow($result);
319+
$this->db->sql_freeresult($result);
320+
321+
return [
322+
'total' => (int) $row['total'],
323+
'implemented' => (int) $row['implemented'],
324+
'in_progress' => (int) $row['in_progress'],
325+
'duplicate' => (int) $row['duplicate'],
326+
'invalid' => (int) $row['invalid'],
327+
'new' => (int) $row['new'],
328+
];
329+
}
299330
}

language/en/common.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
1 => '%s point.',
102102
2 => '%s points.',
103103
],
104+
'TOTAL_POSTED_IDEAS' => 'Total ideas posted',
104105

105106
'UPDATED_VOTE' => 'Successfully updated vote!',
106107

styles/prosilver/template/index_body.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ <h2>{{ lang('IDEAS_TITLE') }}</h2>
4040
{# IN PROGRESS IDEAS #}
4141
{{ _self.ideas_section(lang('IN_PROGRESS_IDEAS'), in_progress_ideas, U_VIEW_IN_PROGRESS, 'clock', lang('VIEW_IN_PROGRESS')) }}
4242

43-
<br><br>
43+
<div class="stat-block statistics">
44+
<h3>{{ lang('STATISTICS') }}</h3>
45+
<p>
46+
{{ lang('TOTAL_POSTED_IDEAS') }} <strong>{{ STATISTICS.total }}</strong> &bull; {{ lang('LIST_IMPLEMENTED') }} <strong>{{ STATISTICS.implemented }}</strong> &bull; {{ lang('LIST_IN_PROGRESS') }} <strong>{{ STATISTICS.in_progress }}</strong>
47+
</p>
48+
</div>
4449

4550
{% include 'overall_footer.html' %}

tests/event/listener_test.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ public function test_getSubscribedEvents()
115115
'core.posting_modify_template_vars',
116116
'core.posting_modify_submit_post_before',
117117
'core.posting_modify_submit_post_after',
118+
'core.mcp_change_poster_after',
118119
), array_keys(\phpbb\ideas\event\listener::getSubscribedEvents()));
119120
}
120121

@@ -674,6 +675,57 @@ public function test_submit_idea($mode, $forum_id, $topic_id, $approved, $succes
674675

675676
$listener->submit_idea_after($event);
676677
}
678+
679+
/**
680+
* Data set for change_idea_author
681+
*
682+
* @return array Array of test data
683+
*/
684+
public function change_idea_author_data()
685+
{
686+
return [
687+
[2, 1, 1, 2, true], // Valid: ideas forum, different authors
688+
[1, 1, 1, 2, false], // Invalid: not ideas forum
689+
[2, 1, 1, 1, false], // Invalid: same author
690+
];
691+
}
692+
693+
/**
694+
* Test the change_idea_author event
695+
*
696+
* @dataProvider change_idea_author_data
697+
*/
698+
public function test_change_idea_author($forum_id, $topic_id, $old_author_id, $new_author_id, $should_update)
699+
{
700+
$listener = $this->get_listener();
701+
702+
$event = new \phpbb\event\data([
703+
'post_info' => [
704+
'forum_id' => $forum_id,
705+
'topic_id' => $topic_id,
706+
'poster_id' => $old_author_id,
707+
],
708+
'userdata' => [
709+
'user_id' => $new_author_id,
710+
],
711+
]);
712+
713+
$idea_data = [
714+
'idea_id' => 1,
715+
'idea_author' => $old_author_id,
716+
];
717+
718+
$this->idea->expects($should_update ? self::once() : self::never())
719+
->method('get_idea_by_topic_id')
720+
->with($topic_id)
721+
->willReturn($idea_data);
722+
723+
$this->idea->expects($should_update ? self::once() : self::never())
724+
->method('set_author')
725+
->with(1, $new_author_id);
726+
727+
$listener->change_idea_author($event);
728+
}
677729
}
678730

679731
/**

tests/functional/viewonline_test.php

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,24 @@
1616
class viewonline_test extends ideas_functional_base
1717
{
1818
/**
19-
* Visit Ideas as user "admin"
19+
* Test viewonline page for admin
2020
*/
21-
public function test_viewonline_visit_ideas()
21+
public function test_viewonline_check_viewonline()
2222
{
23+
// Visit Ideas as user "admin"
2324
$this->login();
24-
$crawler = self::request('GET', "index.php/ideas?sid=$this->sid");
25+
$crawler = self::request('GET', "app.php/ideas?sid=$this->sid");
2526
$this->assertContainsLang('IDEAS_TITLE', $crawler->filter('h2')->text());
26-
}
2727

28-
/**
29-
* Test viewonline page for admin
30-
*
31-
* We use a second function here, so we get a new session and can log in
32-
* without having to log out "admin" first.
33-
*
34-
* @depends test_viewonline_visit_ideas
35-
*/
36-
public function test_viewonline_check_viewonline()
37-
{
38-
// Create user1 and send them to the Viewonline
39-
$this->create_user('user1');
40-
$this->login('user1');
28+
// Create a second user and check who is online from a separate session.
29+
self::$client->restart();
30+
$this->create_user('ideas-viewonline-user1');
31+
$this->login('ideas-viewonline-user1');
32+
// PHP goes faster than DBMS, make sure session data got written to the database.
33+
sleep(1);
4134
$crawler = self::request('GET', "viewonline.php?sid=$this->sid");
4235

43-
// Is admin still viewing Ideas page
36+
// Is admin still viewing Ideas page?
4437
self::assertStringContainsString('admin', $crawler->filter('#page-body table.table1')->text());
4538

4639
$session_entries = $crawler->filter('#page-body table.table1 tr')->count();
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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\tests\ideas;
12+
13+
class get_statistics_test extends ideas_base
14+
{
15+
public function test_get_statistics()
16+
{
17+
$object = $this->get_ideas_object();
18+
19+
$stats = $object->get_statistics();
20+
21+
self::assertEquals(7, $stats['total']);
22+
self::assertEquals(1, $stats['implemented']);
23+
self::assertEquals(1, $stats['in_progress']);
24+
self::assertEquals(0, $stats['duplicate']);
25+
self::assertEquals(0, $stats['invalid']);
26+
self::assertEquals(5, $stats['new']);
27+
}
28+
}

0 commit comments

Comments
 (0)