22 const VIEW_HOOK =
'view';
23 const VIEW_VARS_HOOK =
'view_vars';
24 const OUTPUT_KEY =
'__view_output';
25 const BASE_VIEW_PRIORITY = 500;
31 protected $file_exists_cache = [];
38 private $locations = [];
45 private $overrides = [];
52 private $simplecache_views = [];
64 private $fallbacks = [];
93 $this->events = $events;
106 $this->viewtype = null;
126 if (!isset($this->viewtype)) {
127 $this->viewtype = $this->resolveViewtype();
140 if (empty($this->locations[
$viewtype])) {
141 $this->viewtype =
'default';
150 private function resolveViewtype():
string {
151 if ($this->request) {
152 $view = $this->request->getParam(
'view',
'',
false);
153 if ($this->isValidViewtype(
$view)) {
159 if ($this->isValidViewtype(
$view)) {
174 if ($viewtype ===
'') {
196 $extension = pathinfo($canonical, PATHINFO_EXTENSION);
199 if (str_starts_with($canonical,
'js/')) {
200 $canonical =
substr($canonical, 3);
201 if (!$hasValidFileExtension) {
204 }
else if (str_starts_with($canonical,
'css/')) {
205 $canonical =
substr($canonical, 4);
206 if (!$hasValidFileExtension) {
207 $canonical .=
'.css';
224 $folder =
rtrim($folder,
'/\\');
225 $view_base =
rtrim($view_base,
'/\\');
227 if (!is_dir($folder) || !is_readable($folder)) {
228 $this->
getLogger()->notice(
"Unable to register views from the directory: {$folder}");
233 $dir = new \DirectoryIterator($folder);
235 $this->
getLogger()->error($e->getMessage());
240 if (!empty($view_base)) {
241 $view_base_new = $view_base .
'/';
245 foreach ($dir as $fileinfo) {
246 if ($fileinfo->isDot()) {
250 $path = $fileinfo->getPathname();
252 if ($fileinfo->isDir()) {
254 $this->autoregisterViews($view_base_new . $fileinfo->getFilename(),
$path,
$viewtype);
259 $view = $view_base_new . $fileinfo->getBasename(
'.php');
260 $this->setViewLocation(
$view, $viewtype,
$path);
275 if (!isset($this->locations[$viewtype][$view])) {
280 if ($this->fileExists(
$path)) {
299 $view = self::canonicalizeViewName($view);
305 $location =
rtrim($location,
'/\\');
307 if ($this->fileExists(
"$location/$viewtype/$view.php")) {
308 $this->setViewLocation($view,
$viewtype,
"$location/$viewtype/$view.php");
309 }
else if ($this->fileExists(
"$location/$viewtype/$view")) {
310 $this->setViewLocation($view,
$viewtype,
"$location/$viewtype/$view");
336 return in_array($viewtype, $this->fallbacks);
352 $view = self::canonicalizeViewName($view);
354 $rendered = $this->renderView($view, $vars,
'',
false);
389 $view = self::canonicalizeViewName($view);
392 if (str_contains($view,
'..')) {
397 if (in_array($view, $extensions_tree)) {
398 $this->
getLogger()->error(
"View $view is detected as an extension of itself. This is not allowed");
403 $extensions_tree[] =
$view;
411 $vars_event_params = [
416 $vars = $this->events->triggerResults(self::VIEW_VARS_HOOK, $view, $vars_event_params,
$vars);
419 if (isset(
$vars[self::OUTPUT_KEY])) {
420 return (
string)
$vars[self::OUTPUT_KEY];
423 $viewlist = $this->getViewList($view);
426 foreach ($viewlist as
$priority => $view_name) {
427 if (
$priority !== self::BASE_VIEW_PRIORITY) {
434 $rendering = $this->renderViewFile($view_name,
$vars,
$viewtype, $issue_missing_notice);
435 if ($rendering !==
false) {
442 $rendering = $this->renderViewFile($view_name,
$vars,
'default', $issue_missing_notice);
443 if ($rendering !==
false) {
455 return (
string) $this->events->triggerResults(self::VIEW_HOOK, $view,
$params,
$content);
467 if (!isset($this->file_exists_cache[$path])) {
468 $this->file_exists_cache[
$path] = file_exists($path);
471 return $this->file_exists_cache[
$path];
484 private function renderViewFile(
string $view, array
$vars,
string $viewtype,
bool $issue_missing_notice):
string|
false {
485 $file = $this->findViewFile($view, $viewtype);
487 if ($issue_missing_notice) {
488 $this->
getLogger()->notice(
"$viewtype/$view view does not exist.");
494 if (pathinfo($file, PATHINFO_EXTENSION) ===
'php') {
501 return ob_get_clean();
508 return file_get_contents($file);
522 public function viewExists(
string $view,
string $viewtype =
'',
bool $recurse =
true): bool {
523 $view = self::canonicalizeViewName($view);
530 if ($viewtype ===
'' || !$this->isValidViewtype($viewtype)) {
531 $viewtype = $this->getViewtype();
535 $file = $this->findViewFile($view, $viewtype);
542 if ($recurse && isset($this->
extensions[$view])) {
543 foreach ($this->
extensions[$view] as $view_extension) {
545 if ($this->viewExists($view_extension, $viewtype,
false)) {
552 if ($viewtype !=
'default' && $this->doesViewtypeFallback($viewtype)) {
553 return $this->viewExists($view,
'default');
571 $view = self::canonicalizeViewName($view);
572 $view_extension = self::canonicalizeViewName($view_extension);
574 if ($view === $view_extension) {
602 public function unextendView(
string $view,
string $view_extension): bool {
603 $view = self::canonicalizeViewName($view);
604 $view_extension = self::canonicalizeViewName($view_extension);
631 $view = self::canonicalizeViewName($view);
633 $this->simplecache_views[
$view] =
true;
644 $view = self::canonicalizeViewName($view);
645 if (isset($this->simplecache_views[$view])) {
650 $current_viewtype = $this->getViewtype();
651 $viewtypes = [$current_viewtype];
653 if ($this->doesViewtypeFallback($current_viewtype) && $current_viewtype !=
'default') {
654 $viewtypes[] =
'default';
658 foreach ($viewtypes as $viewtype) {
659 $file = $this->findViewFile($view, $viewtype);
661 if ($file && pathinfo($file, PATHINFO_EXTENSION) !==
'php') {
662 $this->simplecache_views[
$view] =
true;
680 $path = Paths::sanitize($path);
681 $view_dir =
"{$path}views/";
684 if (!is_dir($view_dir)) {
689 $handle = opendir($view_dir);
690 if ($handle ===
false) {
691 $this->
getLogger()->notice(
"Unable to register views from the directory: {$view_dir}");
696 while (($view_type = readdir($handle)) !==
false) {
697 $view_type_dir = $view_dir . $view_type;
699 if (!str_starts_with($view_type,
'.') && is_dir($view_type_dir)) {
700 if (!$this->autoregisterViews(
'', $view_type_dir, $view_type)) {
720 foreach ($spec as $viewtype =>
$list) {
727 if (!
preg_match(
'~^([/\\\\]|[a-zA-Z]\:)~', $path)) {
729 $path = Directory\Local::projectRoot()->getPath($path);
732 if (str_ends_with($view,
'/')) {
734 $this->autoregisterViews($view, $path, $viewtype);
736 $this->setViewLocation($view, $viewtype, $path);
750 public function listViews(
string $viewtype =
'default'): array {
751 if (empty($this->locations[$viewtype])) {
755 return array_keys($this->locations[$viewtype]);
764 $overrides = $this->overrides;
767 $data = $this->cache->
load(
'view_overrides');
768 if (is_array(
$data)) {
774 'locations' => $this->locations,
775 'overrides' => $overrides,
777 'simplecache' => $this->simplecache_views,
790 if (!is_array(
$data)) {
795 if (empty(
$data[
'version']) ||
$data[
'version'] !==
'2.0') {
799 $this->locations =
$data[
'locations'];
800 $this->cache = $cache;
813 $cache->
save(
'view_locations', [
815 'locations' => $this->locations,
819 $cache->
save(
'view_overrides', $this->overrides);
831 private function setViewLocation(
string $view,
string $viewtype,
string $path):
void {
832 $view = self::canonicalizeViewName($view);
833 $path = strtr($path,
'\\',
'/');
835 if (isset($this->locations[$viewtype][$view]) && $path !== $this->locations[$viewtype][$view]) {
843 $this->isCacheableView($view);
save(string $type, $data, int $expire_after=null)
Saves a system cache.
viewExists(string $view, string $viewtype= '', bool $recurse=true)
Returns whether the specified view exists.
isCacheableView(string $view)
Is the view cacheable.
$params
Saves global plugin settings.
$paths
We handle here two possible locations of composer-generated autoload file.
isValidViewtype(string $viewtype)
Checks if $viewtype is a string suitable for use as a viewtype name.
elgg_get_config(string $name, $default=null)
Get an Elgg configuration value.
listViews(string $viewtype= 'default')
List all views in a viewtype.
cacheConfiguration(SystemCache $cache)
Cache the configuration.
c Accompany it with the information you received as to the offer to distribute corresponding source complete source code means all the source code for all modules it plus any associated interface definition plus the scripts used to control compilation and installation of the executable as a special the source code distributed need not include anything that is normally and so on of the operating system on which the executable unless that component itself accompanies the executable If distribution of executable or object code is made by offering access to copy from a designated then offering equivalent access to copy the source code from the same place counts as distribution of the source even though third parties are not compelled to copy the source along with the object code You may not or distribute the Program except as expressly provided under this License Any attempt otherwise to sublicense or distribute the Program is void
renderDeprecatedView(string $view, array $vars, string $suggestion, string $version)
Display a view with a deprecation notice.
setViewDir(string $view, string $location, string $viewtype= '')
Set an alternative base location for a view.
renderView(string $view, array $vars=[], string $viewtype= '', bool $issue_missing_notice=true, array $extensions_tree=[])
Renders a view.
if(!$entity instanceof\ElggUser) $data
getInspectorData()
Get inspector data.
trait Loggable
Enables adding a logger.
getViewtype()
Get the viewtype.
unextendView(string $view, string $view_extension)
Unextends a view.
mergeViewsSpec(array $spec)
Merge a specification of absolute view paths.
load(string $type)
Retrieve the contents of a system cache.
setViewtype(string $viewtype= '')
Set the viewtype.
if(!empty($avatar)&&!$avatar->isValid()) elseif(empty($avatar)) if(!$owner->saveIconFromUploadedFile('avatar')) if(!elgg_trigger_event('profileiconupdate', $owner->type, $owner)) $view
static canonicalizeViewName(string $alias)
Takes a view name and returns the canonical name for that view.
load(stdClass $row)
Loads attributes from the entities table into the object.
clampViewtypeToPopulatedViews()
If the current viewtype has no views, reset it to "default".
extendView(string $view, string $view_extension, int $priority=501)
Extends a view with another view.
findViewFile(string $view, string $viewtype)
Find the view file.
__construct(EventsService $events, HttpRequest $request)
Constructor.
doesViewtypeFallback(string $viewtype)
Checks if a viewtype falls back to default.
getLogger()
Returns logger.
registerViewtypeFallback(string $viewtype)
Register a viewtype to fall back to a default view if a view isn't found for that viewtype...
getViewList(string $view)
Get the views, including extensions, used to render a view.
configureFromCache(SystemCache $cache)
Configure locations from the cache.
$content
Set robots.txt action.
autoregisterViews(string $view_base, string $folder, string $viewtype)
Auto-registers views from a location.
registerCacheableView(string $view)
Register a view a cacheable.
fileExists(string $path)
Wrapper for file_exists() that caches false results (the stat cache only caches true results)...
registerPluginViews(string $path)
Register a plugin's views.
logDeprecatedMessage(string $message, string $version)
Sends a message about deprecated use of a function, view, etc.