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();
138 private function resolveViewtype():
string {
139 if ($this->request) {
140 $view = $this->request->getParam(
'view',
'',
false);
141 if ($this->isValidViewtype(
$view) && !empty($this->locations[
$view])) {
147 if ($this->isValidViewtype(
$view) && !empty($this->locations[
$view])) {
162 if ($viewtype ===
'') {
184 $extension = pathinfo($canonical, PATHINFO_EXTENSION);
187 if (str_starts_with($canonical,
'js/')) {
188 $canonical =
substr($canonical, 3);
189 if (!$hasValidFileExtension) {
192 }
else if (str_starts_with($canonical,
'css/')) {
193 $canonical =
substr($canonical, 4);
194 if (!$hasValidFileExtension) {
195 $canonical .=
'.css';
212 $folder =
rtrim($folder,
'/\\');
213 $view_base =
rtrim($view_base,
'/\\');
215 if (!is_dir($folder) || !is_readable($folder)) {
216 $this->
getLogger()->notice(
"Unable to register views from the directory: {$folder}");
221 $dir = new \DirectoryIterator($folder);
222 }
catch (\Exception $e) {
223 $this->
getLogger()->error($e->getMessage());
228 if (!empty($view_base)) {
229 $view_base_new = $view_base .
'/';
233 foreach ($dir as $fileinfo) {
234 if ($fileinfo->isDot()) {
238 $path = $fileinfo->getPathname();
240 if ($fileinfo->isDir()) {
242 $this->autoregisterViews($view_base_new . $fileinfo->getFilename(),
$path,
$viewtype);
247 $view = $view_base_new . $fileinfo->getBasename(
'.php');
248 $this->setViewLocation(
$view, $viewtype,
$path);
263 if (!isset($this->locations[$viewtype][$view])) {
268 if ($this->fileExists(
$path)) {
287 $view = self::canonicalizeViewName($view);
293 $location =
rtrim($location,
'/\\');
295 if ($this->fileExists(
"$location/$viewtype/$view.php")) {
296 $this->setViewLocation($view,
$viewtype,
"$location/$viewtype/$view.php");
297 }
else if ($this->fileExists(
"$location/$viewtype/$view")) {
298 $this->setViewLocation($view,
$viewtype,
"$location/$viewtype/$view");
324 return in_array($viewtype, $this->fallbacks);
340 $view = self::canonicalizeViewName($view);
342 $rendered = $this->renderView($view, $vars,
'',
false);
377 $view = self::canonicalizeViewName($view);
380 if (str_contains($view,
'..')) {
385 if (in_array($view, $extensions_tree)) {
386 $this->
getLogger()->error(
"View $view is detected as an extension of itself. This is not allowed");
391 $extensions_tree[] =
$view;
398 if (!isset($issue_missing_notice)) {
399 $issue_missing_notice =
$viewtype ===
'default';
403 $vars_event_params = [
408 $vars = $this->events->triggerResults(self::VIEW_VARS_HOOK, $view, $vars_event_params,
$vars);
411 if (isset(
$vars[self::OUTPUT_KEY])) {
412 return (
string)
$vars[self::OUTPUT_KEY];
415 $viewlist = $this->getViewList($view);
418 foreach ($viewlist as
$priority => $view_name) {
419 if (
$priority !== self::BASE_VIEW_PRIORITY) {
426 $rendering = $this->renderViewFile($view_name,
$vars,
$viewtype, $issue_missing_notice);
427 if ($rendering !==
false) {
434 $rendering = $this->renderViewFile($view_name,
$vars,
'default', $issue_missing_notice);
435 if ($rendering !==
false) {
447 return (
string) $this->events->triggerResults(self::VIEW_HOOK, $view,
$params,
$content);
459 if (!isset($this->file_exists_cache[$path])) {
460 $this->file_exists_cache[
$path] = file_exists($path);
463 return $this->file_exists_cache[
$path];
476 private function renderViewFile(
string $view, array
$vars,
string $viewtype,
bool $issue_missing_notice):
string|
false {
477 $file = $this->findViewFile($view, $viewtype);
479 if ($issue_missing_notice) {
480 $this->
getLogger()->notice(
"$viewtype/$view view does not exist.");
486 if (pathinfo($file, PATHINFO_EXTENSION) ===
'php') {
493 return ob_get_clean();
494 }
catch (\Exception $e) {
500 return file_get_contents($file);
514 public function viewExists(
string $view,
string $viewtype =
'',
bool $recurse =
true): bool {
515 $view = self::canonicalizeViewName($view);
522 if ($viewtype ===
'' || !$this->isValidViewtype($viewtype)) {
523 $viewtype = $this->getViewtype();
527 $file = $this->findViewFile($view, $viewtype);
534 if ($recurse && isset($this->
extensions[$view])) {
535 foreach ($this->
extensions[$view] as $view_extension) {
537 if ($this->viewExists($view_extension, $viewtype,
false)) {
544 if ($viewtype !=
'default' && $this->doesViewtypeFallback($viewtype)) {
545 return $this->viewExists($view,
'default');
563 $view = self::canonicalizeViewName($view);
564 $view_extension = self::canonicalizeViewName($view_extension);
566 if ($view === $view_extension) {
594 public function unextendView(
string $view,
string $view_extension): bool {
595 $view = self::canonicalizeViewName($view);
596 $view_extension = self::canonicalizeViewName($view_extension);
623 $view = self::canonicalizeViewName($view);
625 $this->simplecache_views[
$view] =
true;
636 $view = self::canonicalizeViewName($view);
637 if (isset($this->simplecache_views[$view])) {
642 $current_viewtype = $this->getViewtype();
643 $viewtypes = [$current_viewtype];
645 if ($this->doesViewtypeFallback($current_viewtype) && $current_viewtype !=
'default') {
646 $viewtypes[] =
'default';
650 foreach ($viewtypes as $viewtype) {
651 $file = $this->findViewFile($view, $viewtype);
653 if ($file && pathinfo($file, PATHINFO_EXTENSION) !==
'php') {
654 $this->simplecache_views[
$view] =
true;
672 $path = Paths::sanitize($path);
673 $view_dir =
"{$path}views/";
676 if (!is_dir($view_dir)) {
681 $handle = opendir($view_dir);
682 if ($handle ===
false) {
683 $this->
getLogger()->notice(
"Unable to register views from the directory: {$view_dir}");
688 while (($view_type = readdir($handle)) !==
false) {
689 $view_type_dir = $view_dir . $view_type;
691 if (!str_starts_with($view_type,
'.') && is_dir($view_type_dir)) {
692 if (!$this->autoregisterViews(
'', $view_type_dir, $view_type)) {
712 foreach ($spec as $viewtype =>
$list) {
719 if (!
preg_match(
'~^([/\\\\]|[a-zA-Z]\:)~', $path)) {
721 $path = Directory\Local::projectRoot()->getPath($path);
724 if (str_ends_with($view,
'/')) {
726 $this->autoregisterViews($view, $path, $viewtype);
728 $this->setViewLocation($view, $viewtype, $path);
742 public function listViews(
string $viewtype =
'default'): array {
743 if (empty($this->locations[$viewtype])) {
747 return array_keys($this->locations[$viewtype]);
756 $overrides = $this->overrides;
759 $data = $this->cache->
load(
'view_overrides');
760 if (is_array(
$data)) {
766 'locations' => $this->locations,
767 'overrides' => $overrides,
769 'simplecache' => $this->simplecache_views,
782 if (!is_array(
$data)) {
786 $this->locations =
$data[
'locations'];
787 $this->cache = $cache;
800 if (empty($this->locations)) {
801 $cache->
delete(
'view_locations');
805 $cache->
save(
'view_locations', [
'locations' => $this->locations]);
808 $cache->
save(
'view_overrides', $this->overrides);
820 private function setViewLocation(
string $view,
string $viewtype,
string $path):
void {
821 $view = self::canonicalizeViewName($view);
822 $path = strtr($path,
'\\',
'/');
824 if (isset($this->locations[$viewtype][$view]) && $path !== $this->locations[$viewtype][$view]) {
832 $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=null, array $extensions_tree=[])
Renders a view.
delete(string $type)
Deletes the contents of a system cache.
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.
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.