Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
moodle
moodle
Commits
a96faa49
Commit
a96faa49
authored
May 16, 2017
by
sam marshall
Browse files
MDL-58957 Global search: Add block support to search manager
parent
557554f9
Changes
6
Hide whitespace changes
Inline
Side-by-side
blocks/upgrade.txt
View file @
a96faa49
...
...
@@ -6,6 +6,9 @@ information provided here is intended especially for developers.
* The block_instances table now contains fields timecreated and timemodified. If third-party code
creates or updates these rows (without using the standard API), it should be modified to set
these fields as appropriate.
* Blocks can now be included in Moodle global search, with some limitations (at present, the search
works only for blocks located directly on course pages or site home page). See the HTML block for
an example.
=== 3.3 ===
...
...
search/classes/base.php
View file @
a96faa49
...
...
@@ -270,7 +270,7 @@ abstract class base {
* Can the current user see the document.
*
* @param int $id The internal search area entity id.
* @return
bool True if the user can see it, false otherwise
* @return
int manager:ACCESS_xx constant
*/
abstract
public
function
check_access
(
$id
);
...
...
search/classes/base_block.php
0 → 100644
View file @
a96faa49
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle 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.
//
// Moodle 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 Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Search area base class for blocks.
*
* Note: Only blocks within courses are supported.
*
* @package core_search
* @copyright 2017 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace
core_search
;
defined
(
'MOODLE_INTERNAL'
)
||
die
();
/**
* Search area base class for blocks.
*
* Note: Only blocks within courses are supported.
*
* @package core_search
* @copyright 2017 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract
class
base_block
extends
base
{
/** @var string Cache name used for block instances */
const
CACHE_INSTANCES
=
'base_block_instances'
;
/**
* The context levels the search area is working on.
*
* This can be overwriten by the search area if it works at multiple
* levels.
*
* @var array
*/
protected
static
$levels
=
[
CONTEXT_BLOCK
];
/**
* Gets the block name only.
*
* @return string Block name e.g. 'html'
*/
public
function
get_block_name
()
{
// Remove 'block_' text.
return
substr
(
$this
->
get_component_name
(),
6
);
}
/**
* Returns restrictions on which block_instances rows to return. By default, excludes rows
* that have empty configdata.
*
* @return string SQL restriction (or multiple restrictions joined by AND), empty if none
*/
protected
function
get_indexing_restrictions
()
{
return
"bi.configdata != ''"
;
}
/**
* Gets recordset of all records modified since given time.
*
* See base class for detailed requirements. This implementation includes the key fields
* from block_instances.
*
* This can be overridden to do something totally different if the block's data is stored in
* other tables.
*
* If there are certain instances of the block which should not be included in the search index
* then you can override get_indexing_restrictions; by default this excludes rows with empty
* configdata.
*
* @param int $modifiedfrom Modified from time (>= this)
*/
public
function
get_recordset_by_timestamp
(
$modifiedfrom
=
0
)
{
global
$DB
;
$restrictions
=
$this
->
get_indexing_restrictions
();
if
(
$restrictions
)
{
$restrictions
=
'AND '
.
$restrictions
;
}
// Query for all entries in block_instances for this type of block, which were modified
// since the given date. Also find the course or module where the block is located.
// (Although this query supports both module and course context, currently only two page
// types are supported, which will both be at course context. The module support is present
// in case of extension to other page types later.)
return
$DB
->
get_recordset_sql
(
"
SELECT bi.id, bi.timemodified, bi.timecreated, bi.configdata,
c.id AS courseid, x.id AS contextid
FROM
{
block_instances
}
bi
JOIN
{
context
}
x ON x.instanceid = bi.id AND x.contextlevel = ?
JOIN
{
context
}
parent ON parent.id = bi.parentcontextid
LEFT JOIN
{
course_modules
}
cm ON cm.id = parent.instanceid AND parent.contextlevel = ?
JOIN
{
course
}
c ON c.id = cm.course
OR (c.id = parent.instanceid AND parent.contextlevel = ?)
WHERE bi.timemodified >= ?
AND bi.blockname = ?
AND (parent.contextlevel = ? AND (bi.pagetypepattern LIKE 'course-view-%'
OR bi.pagetypepattern IN ('site-index', 'course-*', '*')))
$restrictions
ORDER BY bi.timemodified ASC"
,
[
CONTEXT_BLOCK
,
CONTEXT_MODULE
,
CONTEXT_COURSE
,
$modifiedfrom
,
$this
->
get_block_name
(),
CONTEXT_COURSE
]);
}
public
function
get_doc_url
(
\
core_search\document
$doc
)
{
// Load block instance and find cmid if there is one.
$blockinstanceid
=
preg_replace
(
'~^.*-~'
,
''
,
$doc
->
get
(
'id'
));
$instance
=
$this
->
get_block_instance
(
$blockinstanceid
);
$courseid
=
$doc
->
get
(
'courseid'
);
$anchor
=
'inst'
.
$blockinstanceid
;
// Check if the block is at course or module level.
if
(
$instance
->
cmid
)
{
// No module-level page types are supported at present so the search system won't return
// them. But let's put some example code here to indicate how it could work.
debugging
(
'Unexpected module-level page type for block '
.
$blockinstanceid
.
': '
.
$instance
->
pagetypepattern
,
DEBUG_DEVELOPER
);
$modinfo
=
get_fast_modinfo
(
$courseid
);
$cm
=
$modinfo
->
get_cm
(
$instance
->
cmid
);
return
new
\
moodle_url
(
$cm
->
url
,
null
,
$anchor
);
}
else
{
// The block is at course level. Let's check the page type, although in practice we
// currently only support the course main page.
if
(
$instance
->
pagetypepattern
===
'*'
||
$instance
->
pagetypepattern
===
'course-*'
||
preg_match
(
'~^course-view-(.*)$~'
,
$instance
->
pagetypepattern
))
{
return
new
\
moodle_url
(
'/course/view.php'
,
[
'id'
=>
$courseid
],
$anchor
);
}
else
if
(
$instance
->
pagetypepattern
===
'site-index'
)
{
return
new
\
moodle_url
(
'/'
,
[],
$anchor
);
}
else
{
debugging
(
'Unexpected page type for block '
.
$blockinstanceid
.
': '
.
$instance
->
pagetypepattern
,
DEBUG_DEVELOPER
);
return
new
\
moodle_url
(
'/course/view.php'
,
[
'id'
=>
$courseid
],
$anchor
);
}
}
}
public
function
get_context_url
(
\
core_search\document
$doc
)
{
return
$this
->
get_doc_url
(
$doc
);
}
/**
* Checks access for a document in this search area.
*
* If you override this function for a block, you should call this base class version first
* as it will check that the block is still visible to users in a supported location.
*
* @param int $id Document id
* @return int manager:ACCESS_xx constant
*/
public
function
check_access
(
$id
)
{
$instance
=
$this
->
get_block_instance
(
$id
,
IGNORE_MISSING
);
if
(
!
$instance
)
{
// This generally won't happen because if the block has been deleted then we won't have
// included its context in the search area list, but just in case.
return
manager
::
ACCESS_DELETED
;
}
// Check block has not been moved to an unsupported area since it was indexed. (At the
// moment, only blocks within site and course context are supported, also only certain
// page types.)
if
(
!
$instance
->
courseid
||
!
self
::
is_supported_page_type_at_course_context
(
$instance
->
pagetypepattern
))
{
return
manager
::
ACCESS_DELETED
;
}
// Note we do not need to check if the block was hidden or if the user has access to the
// context, because those checks are included in the list of search contexts user can access
// that is calculated in manager.php every time they do a query.
return
manager
::
ACCESS_GRANTED
;
}
/**
* Checks if a page type is supported for blocks when at course (or also site) context. This
* function should be consistent with the SQL in get_recordset_by_timestamp.
*
* @param string $pagetype Page type
* @return bool True if supported
*/
protected
static
function
is_supported_page_type_at_course_context
(
$pagetype
)
{
if
(
in_array
(
$pagetype
,
[
'site-index'
,
'course-*'
,
'*'
]))
{
return
true
;
}
if
(
preg_match
(
'~^course-view-~'
,
$pagetype
))
{
return
true
;
}
return
false
;
}
/**
* Gets a block instance with given id.
*
* Returns the fields id, pagetypepattern, subpagepattern from block_instances and also the
* cmid (if parent context is an activity module).
*
* @param int $id ID of block instance
* @param int $strictness MUST_EXIST or IGNORE_MISSING
* @return false|mixed Block instance data (may be false if strictness is IGNORE_MISSING)
*/
protected
function
get_block_instance
(
$id
,
$strictness
=
MUST_EXIST
)
{
global
$DB
;
$cache
=
\
cache
::
make_from_params
(
\
cache_store
::
MODE_REQUEST
,
'core_search'
,
self
::
CACHE_INSTANCES
,
[],
[
'simplekeys'
=>
true
]);
$id
=
(
int
)
$id
;
$instance
=
$cache
->
get
(
$id
);
if
(
!
$instance
)
{
$instance
=
$DB
->
get_record_sql
(
"
SELECT bi.id, bi.pagetypepattern, bi.subpagepattern,
c.id AS courseid, cm.id AS cmid
FROM
{
block_instances
}
bi
JOIN
{
context
}
parent ON parent.id = bi.parentcontextid
LEFT JOIN
{
course
}
c ON c.id = parent.instanceid AND parent.contextlevel = ?
LEFT JOIN
{
course_modules
}
cm ON cm.id = parent.instanceid AND parent.contextlevel = ?
WHERE bi.id = ?"
,
[
CONTEXT_COURSE
,
CONTEXT_MODULE
,
$id
],
$strictness
);
$cache
->
set
(
$id
,
$instance
);
}
return
$instance
;
}
/**
* Clears static cache. This function can be removed (with calls to it in the test script
* replaced with cache_helper::purge_all) if MDL-59427 is fixed.
*/
public
static
function
clear_static
()
{
\
cache
::
make_from_params
(
\
cache_store
::
MODE_REQUEST
,
'core_search'
,
self
::
CACHE_INSTANCES
,
[],
[
'simplekeys'
=>
true
])
->
purge
();
}
}
search/classes/manager.php
View file @
a96faa49
...
...
@@ -294,6 +294,8 @@ class manager {
static
::
$enabledsearchareas
=
null
;
static
::
$allsearchareas
=
null
;
static
::
$instance
=
null
;
base_block
::
clear_static
();
}
/**
...
...
@@ -331,7 +333,7 @@ class manager {
* @return bool|array Indexed by area identifier (component + area name). Returns true if the user can see everything.
*/
protected
function
get_areas_user_accesses
(
$limitcourseids
=
false
)
{
global
$
CFG
,
$USER
;
global
$
DB
,
$USER
;
// All results for admins. Eventually we could add a new capability for managers.
if
(
is_siteadmin
())
{
...
...
@@ -380,19 +382,23 @@ class manager {
$courses
[
SITEID
]
=
get_course
(
SITEID
);
}
// Keep a list of included course context ids (needed for the block calculation below).
$coursecontextids
=
[];
foreach
(
$courses
as
$course
)
{
if
(
!
empty
(
$limitcourseids
)
&&
!
in_array
(
$course
->
id
,
$limitcourseids
))
{
// Skip non-included courses.
continue
;
}
$coursecontext
=
\
context_course
::
instance
(
$course
->
id
);
$coursecontextids
[]
=
$coursecontext
->
id
;
// Info about the course modules.
$modinfo
=
get_fast_modinfo
(
$course
);
if
(
!
empty
(
$areasbylevel
[
CONTEXT_COURSE
]))
{
// Add the course contexts the user can view.
$coursecontext
=
\
context_course
::
instance
(
$course
->
id
);
foreach
(
$areasbylevel
[
CONTEXT_COURSE
]
as
$areaid
=>
$searchclass
)
{
if
(
$course
->
visible
||
has_capability
(
'moodle/course:viewhiddencourses'
,
$coursecontext
))
{
$areascontexts
[
$areaid
][
$coursecontext
->
id
]
=
$coursecontext
->
id
;
...
...
@@ -418,6 +424,63 @@ class manager {
}
}
// Add all supported block contexts, in a single query for performance.
if
(
!
empty
(
$areasbylevel
[
CONTEXT_BLOCK
]))
{
// Get list of all block types we care about.
$blocklist
=
[];
foreach
(
$areasbylevel
[
CONTEXT_BLOCK
]
as
$areaid
=>
$searchclass
)
{
$blocklist
[
$searchclass
->
get_block_name
()]
=
true
;
}
list
(
$blocknamesql
,
$blocknameparams
)
=
$DB
->
get_in_or_equal
(
array_keys
(
$blocklist
));
// Get list of course contexts.
list
(
$contextsql
,
$contextparams
)
=
$DB
->
get_in_or_equal
(
$coursecontextids
);
// Query all blocks that are within an included course, and are set to be visible, and
// in a supported page type (basically just course view). This query could be
// extended (or a second query added) to support blocks that are within a module
// context as well, and we could add more page types if required.
$blockrecs
=
$DB
->
get_records_sql
(
"
SELECT x.*, bi.blockname AS blockname, bi.id AS blockinstanceid
FROM
{
block_instances
}
bi
JOIN
{
context
}
x ON x.instanceid = bi.id AND x.contextlevel = ?
LEFT JOIN
{
block_positions
}
bp ON bp.blockinstanceid = bi.id
AND bp.contextid = bi.parentcontextid
AND bp.pagetype LIKE 'course-view-%'
AND bp.subpage = ''
AND bp.visible = 0
WHERE bi.parentcontextid
$contextsql
AND bi.blockname
$blocknamesql
AND bi.subpagepattern IS NULL
AND (bi.pagetypepattern = 'site-index'
OR bi.pagetypepattern LIKE 'course-view-%'
OR bi.pagetypepattern = 'course-*'
OR bi.pagetypepattern = '*')
AND bp.id IS NULL"
,
array_merge
([
CONTEXT_BLOCK
],
$contextparams
,
$blocknameparams
));
$blockcontextsbyname
=
[];
foreach
(
$blockrecs
as
$blockrec
)
{
if
(
empty
(
$blockcontextsbyname
[
$blockrec
->
blockname
]))
{
$blockcontextsbyname
[
$blockrec
->
blockname
]
=
[];
}
\
context_helper
::
preload_from_record
(
$blockrec
);
$blockcontextsbyname
[
$blockrec
->
blockname
][]
=
\
context_block
::
instance
(
$blockrec
->
blockinstanceid
);
}
// Add the block contexts the user can view.
foreach
(
$areasbylevel
[
CONTEXT_BLOCK
]
as
$areaid
=>
$searchclass
)
{
if
(
empty
(
$blockcontextsbyname
[
$searchclass
->
get_block_name
()]))
{
continue
;
}
foreach
(
$blockcontextsbyname
[
$searchclass
->
get_block_name
()]
as
$context
)
{
if
(
has_capability
(
'moodle/block:view'
,
$context
))
{
$areascontexts
[
$areaid
][
$context
->
id
]
=
$context
->
id
;
}
}
}
}
return
$areascontexts
;
}
...
...
search/tests/base_block_test.php
0 → 100644
View file @
a96faa49
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle 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.
//
// Moodle 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 Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for the base_block class.
*
* @package core_search
* @copyright 2017 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined
(
'MOODLE_INTERNAL'
)
||
die
();
require_once
(
__DIR__
.
'/fixtures/testable_core_search.php'
);
require_once
(
__DIR__
.
'/fixtures/mock_block_area.php'
);
/**
* Unit tests for the base_block class.
*
* @package core_search
* @copyright 2017 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class
base_block_testcase
extends
advanced_testcase
{
/**
* Tests getting the name out of the class name.
*/
public
function
test_get_block_name
()
{
$area
=
new
\
block_mockblock\search\area
();
$this
->
assertEquals
(
'mockblock'
,
$area
->
get_block_name
());
}
/**
* Tests getting the recordset.
*/
public
function
test_get_recordset_by_timestamp
()
{
global
$DB
;
$this
->
resetAfterTest
();
// Create course and activity module.
$generator
=
$this
->
getDataGenerator
();
$course
=
$generator
->
create_course
();
$coursecontext
=
\
context_course
::
instance
(
$course
->
id
);
$page
=
$generator
->
create_module
(
'page'
,
[
'course'
=>
$course
->
id
]);
$pagecontext
=
\
context_module
::
instance
(
$page
->
cmid
);
// Add blocks by hacking table (because it's not a real block type).
// 1. Block on course page.
$configdata
=
base64_encode
(
serialize
(
new
\
stdClass
()));
$instance
=
(
object
)[
'blockname'
=>
'mockblock'
,
'parentcontextid'
=>
$coursecontext
->
id
,
'showinsubcontexts'
=>
0
,
'pagetypepattern'
=>
'course-view-*'
,
'defaultweight'
=>
0
,
'timecreated'
=>
1
,
'timemodified'
=>
1
,
'configdata'
=>
$configdata
];
$block1id
=
$DB
->
insert_record
(
'block_instances'
,
$instance
);
$block1context
=
\
context_block
::
instance
(
$block1id
);
// 2. Block on activity page.
$instance
->
parentcontextid
=
$pagecontext
->
id
;
$instance
->
pagetypepattern
=
'mod-page-view'
;
$instance
->
timemodified
=
2
;
$block2id
=
$DB
->
insert_record
(
'block_instances'
,
$instance
);
\
context_block
::
instance
(
$block2id
);
// 3. Block on site context.
$sitecourse
=
get_site
();
$sitecontext
=
\
context_course
::
instance
(
$sitecourse
->
id
);
$instance
->
parentcontextid
=
$sitecontext
->
id
;
$instance
->
pagetypepattern
=
'site-index'
;
$instance
->
timemodified
=
3
;
$block3id
=
$DB
->
insert_record
(
'block_instances'
,
$instance
);
$block3context
=
\
context_block
::
instance
(
$block3id
);
// 4. Block on course page but no data.
$instance
->
parentcontextid
=
$coursecontext
->
id
;
$instance
->
pagetypepattern
=
'course-view-*'
;
unset
(
$instance
->
configdata
);
$instance
->
timemodified
=
4
;
$block4id
=
$DB
->
insert_record
(
'block_instances'
,
$instance
);
\
context_block
::
instance
(
$block4id
);
// 5. Block on course page but not this block.
$instance
->
blockname
=
'mockotherblock'
;
$instance
->
configdata
=
$configdata
;
$instance
->
timemodified
=
5
;
$block5id
=
$DB
->
insert_record
(
'block_instances'
,
$instance
);
\
context_block
::
instance
(
$block5id
);
// 6. Block on course page with '*' page type.
$instance
->
blockname
=
'mockblock'
;
$instance
->
pagetypepattern
=
'*'
;
$instance
->
timemodified
=
6
;
$block6id
=
$DB
->
insert_record
(
'block_instances'
,
$instance
);
\
context_block
::
instance
(
$block6id
);
// 7. Block on course page with 'course-*' page type.
$instance
->
pagetypepattern
=
'course-*'
;
$instance
->
timemodified
=
7
;
$block7id
=
$DB
->
insert_record
(
'block_instances'
,
$instance
);
\
context_block
::
instance
(
$block7id
);
// Get all the blocks.
$area
=
new
block_mockblock\search\area
();
$rs
=
$area
->
get_recordset_by_timestamp
();
$results
=
[];
foreach
(
$rs
as
$rec
)
{
$results
[]
=
$rec
;
}
$rs
->
close
();
// Only blocks 1, 3, 6, and 7 should be returned. Check all the fields for the first two.
$this
->
assertCount
(
4
,
$results
);
$this
->
assertEquals
(
$block1id
,
$results
[
0
]
->
id
);
$this
->
assertEquals
(
1
,
$results
[
0
]
->
timemodified
);
$this
->
assertEquals
(
1
,
$results
[
0
]
->
timecreated
);
$this
->
assertEquals
(
$configdata
,
$results
[
0
]
->
configdata
);
$this
->
assertEquals
(
$course
->
id
,
$results
[
0
]
->
courseid
);
$this
->
assertEquals
(
$block1context
->
id
,
$results
[
0
]
->
contextid
);
$this
->
assertEquals
(
$block3id
,
$results
[
1
]
->
id
);
$this
->
assertEquals
(
3
,
$results
[
1
]
->
timemodified
);
$this
->
assertEquals
(
1
,
$results
[
1
]
->
timecreated
);
$this
->
assertEquals
(
$configdata
,
$results
[
1
]
->
configdata
);
$this
->
assertEquals
(
$sitecourse
->
id
,
$results
[
1
]
->
courseid
);
$this
->
assertEquals
(
$block3context
->
id
,
$results
[
1
]
->
contextid
);
// For the later ones, just check it got the right ones!
$this
->
assertEquals
(
$block6id
,
$results
[
2
]
->
id
);
$this
->
assertEquals
(
$block7id
,
$results
[
3
]
->
id
);
// Repeat with a time restriction.
$rs
=
$area
->
get_recordset_by_timestamp
(
2
);
$results
=
[];
foreach
(
$rs
as
$rec
)
{
$results
[]
=
$rec
;
}
$rs
->
close
();
// Only block 3, 6, and 7 are returned.
$this
->
assertCount
(
3
,
$results
);
$this
->
assertEquals
(
$block3id
,
$results
[
0
]
->
id
);
$this
->
assertEquals
(
$block6id
,
$results
[
1
]
->
id
);
$this
->
assertEquals
(
$block7id
,
$results
[
2
]
->
id
);
}
/**
* Tests the get_doc_url function.
*/
public
function
test_get_doc_url
()
{
global
$DB
;
$this
->
resetAfterTest
();
// Create course and activity module.
$generator
=
$this
->
getDataGenerator
();
$course
=
$generator
->
create_course
();
$coursecontext
=
\
context_course
::
instance
(
$course
->
id
);
$page
=
$generator
->
create_module
(
'page'
,
[
'course'
=>
$course
->
id
]);
$pagecontext
=
\
context_module
::
instance
(
$page
->
cmid
);
// Create block on course page.
$configdata
=
base64_encode
(
serialize
(
new
\
stdClass
()));
$instance
=
(
object
)[
'blockname'
=>
'mockblock'
,
'parentcontextid'
=>
$coursecontext
->
id
,
'showinsubcontexts'
=>
0
,
'pagetypepattern'
=>
'course-view-*'
,
'defaultweight'
=>
0
,
'timecreated'
=>
1
,
'timemodified'
=>
1
,
'configdata'
=>
$configdata
];
$blockid
=
$DB
->
insert_record
(
'block_instances'
,
$instance
);
// Get document URL.
$area
=
new
block_mockblock\search\area
();
$doc
=
$this
->
get_doc
(
$course
->
id
,
$blockid
);
$expected
=
new
moodle_url
(
'/course/view.php'
,
[
'id'
=>
$course
->
id
],
'inst'
.
$blockid
);
$this
->
assertEquals
(
$expected
,
$area
->
get_doc_url
(
$doc
));
$this
->
assertEquals
(
$expected
,
$area
->
get_context_url
(
$doc
));
// Repeat with block on site page.
$sitecourse
=
get_site
();
$sitecontext
=
\
context_course
::
instance
(
$sitecourse
->
id
);
$instance
->
pagetypepattern
=
'site-index'
;
$instance
->
parentcontextid
=
$sitecontext
->
id
;
$block2id
=
$DB
->
insert_record
(
'block_instances'
,
$instance
);
// Get document URL.
$doc2
=
$this
->
get_doc
(
$course
->
id
,
$block2id
);
$expected
=
new
moodle_url
(
'/'
,
[],
'inst'
.
$block2id
);
$this
->
assertEquals
(
$expected
,
$area
->
get_doc_url
(
$doc2
));
$this
->
assertEquals
(
$expected
,
$area
->
get_context_url
(
$doc2
));
// Repeat with block on module page (this cannot happen yet because the search query will
// only include course context blocks, but let's check it works for the future).
$instance
->
pagetypepattern
=
'mod-page-view'
;
$instance
->
parentcontextid
=
$pagecontext
->
id
;
$block3id
=
$DB
->
insert_record
(
'block_instances'
,
$instance
);
// Get and check document URL, ignoring debugging message for unsupported page type.
$debugmessage
=
'Unexpected module-level page type for block '
.
$block3id
.
': mod-page-view'
;
$doc3
=
$this
->
get_doc
(
$course
->
id
,
$block3id
);
$this
->
assertDebuggingCalledCount
(
2
,
[
$debugmessage
,
$debugmessage
]);
$expected
=
new
moodle_url
(
'/mod/page/view.php'
,
[
'id'
=>
$page
->
cmid
],
'inst'
.
$block3id
);
$this
->
assertEquals
(
$expected
,
$area
->
get_doc_url
(
$doc3
));
$this
->
assertDebuggingCalled
(
$debugmessage
);
$this
->
assertEquals
(
$expected
,
$area
->
get_context_url
(
$doc3
));
$this
->
assertDebuggingCalled
(
$debugmessage
);
// Repeat with another block on course page but '*' pages.
$instance
->
pagetypepattern
=
'*'
;
$instance
->
parentcontextid
=
$coursecontext
->
id
;
$block4id
=
$DB
->
insert_record
(
'block_instances'
,
$instance
);
// Get document URL.
$doc
=
$this
->
get_doc
(
$course
->
id
,
$block4id
);
$expected
=
new
moodle_url
(
'/course/view.php'
,
[
'id'
=>
$course
->
id
],
'inst'
.
$block4id
);
$this
->
assertEquals
(
$expected
,
$area
->
get_doc_url
(
$doc
));
$this
->
assertEquals
(
$expected
,
$area
->
get_context_url
(
$doc
));
// And same thing but 'course-*' pages.
$instance
->
pagetypepattern
=
'course-*'
;
$block5id
=
$DB
->
insert_record
(
'block_instances'
,
$instance
);
// Get document URL.
$doc
=
$this
->
get_doc
(
$course
->
id
,
$block5id
);
$expected
=
new
moodle_url
(
'/course/view.php'
,
[
'id'
=>
$course
->
id
],
'inst'
.
$block5id
);
$this
->
assertEquals
(
$expected
,
$area
->
get_doc_url
(
$doc
));
$this
->
assertEquals
(
$expected
,
$area
->
get_context_url
(
$doc
));
}
/**
* Tests the check_access function.