Skip to content

Commit ff8bfa0

Browse files
committed
Implement the autotitle functionality via native PHP DOM
1 parent 540023b commit ff8bfa0

File tree

2 files changed

+158
-0
lines changed

2 files changed

+158
-0
lines changed

classes/autotitle.php

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
// This file is part of Moodle - https://moodle.org/
3+
//
4+
// Moodle is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// Moodle is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
16+
17+
namespace block_course_contents;
18+
19+
/**
20+
* Provides section autotitle functionality for the Course contents block
21+
*
22+
* @copyright 2021 David Mudrák <david@moodle.com>
23+
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24+
*/
25+
class autotitle {
26+
27+
/**
28+
* Extract suitable title from the HTML section summary text
29+
*
30+
* @param string $summary
31+
* @return string
32+
*/
33+
public static function extract_title(string $summary): string {
34+
35+
$summary = trim($summary);
36+
37+
if ($summary === '') {
38+
return '';
39+
}
40+
41+
$dom = new \DOMDocument();
42+
$dom->loadHTML($summary);
43+
44+
return static::find_first_nonempty_text_node_value($dom);
45+
}
46+
47+
/**
48+
* Find the first non-empty text node value in the DOM tree.
49+
*
50+
* Recursively traverse through the DOMNode and its child nodes to seek for the
51+
* first text node with non-empty value.
52+
*
53+
* @param \DOMNode $node
54+
* @return string
55+
*/
56+
public static function find_first_nonempty_text_node_value(\DOMNode $node): string {
57+
58+
if ($node->nodeType == XML_TEXT_NODE) {
59+
$text = trim($node->textContent);
60+
61+
if ($text !== '') {
62+
return $text;
63+
}
64+
}
65+
66+
$text = '';
67+
68+
foreach ($node->childNodes as $child) {
69+
$text = static::find_first_nonempty_text_node_value($child);
70+
71+
if ($text !== '') {
72+
break;
73+
}
74+
}
75+
76+
return $text;
77+
}
78+
}

tests/block_course_contents_test.php

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
// This file is part of Moodle - https://moodle.org/
3+
//
4+
// Moodle is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// Moodle is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
16+
17+
namespace block_course_contents;
18+
19+
/**
20+
* The autotitle feature test.
21+
*
22+
* @package block_course_contents
23+
* @copyright 2021 David Mudrák <david@moodle.com>
24+
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25+
*/
26+
class autotitle_test extends \advanced_testcase {
27+
28+
/**
29+
* Test extracting suitable title from the summary HTML text.
30+
*
31+
* @dataProvider extract_title_data
32+
* @param string $summary
33+
* @param string $title
34+
*/
35+
public function test_extract_title(string $summary, string $title) {
36+
$this->assertEquals($title, autotitle::extract_title($summary));
37+
}
38+
39+
/**
40+
* Provides data for {@see self::test_extract_title()}.
41+
*
42+
* @return array
43+
*/
44+
public function extract_title_data(): array {
45+
return [
46+
'Plain text' => [
47+
'summary' => 'Welcome to this course!',
48+
'title' => 'Welcome to this course!',
49+
],
50+
'Heading' => [
51+
'summary' => '<h3>Welcome!</h3><p>In this course, you will learn a lot.</p>',
52+
'title' => 'Welcome!',
53+
],
54+
'Bold' => [
55+
'summary' => '<p><b>Welcome!</b> In this course, you will learn a lot.</p>',
56+
'title' => 'Welcome!',
57+
],
58+
'First non-empty' => [
59+
'summary' => '<p class="test"><strong> </strong><i></i></p><p></p><br /><p class="test">Hello</p>',
60+
'title' => 'Hello',
61+
],
62+
'Siblings' => [
63+
'summary' => '<div><span>First</span><span>Two</span></div>',
64+
'title' => 'First',
65+
],
66+
'No actual text content, just HTML' => [
67+
'summary' => "<br />\n\t<p>\n</p>",
68+
'title' => '',
69+
],
70+
'Empty string' => [
71+
'summary' => '',
72+
'title' => '',
73+
],
74+
'Break lines' => [
75+
'summary' => 'Hello <br> students',
76+
'title' => 'Hello',
77+
],
78+
];
79+
}
80+
}

0 commit comments

Comments
 (0)