core-bundle/src/Resources/contao/widgets/PageSelector.php
public function generate()
	{
		$this->import(BackendUser::class, 'User');

		/** @var AttributeBagInterface $objSessionBag */
		$objSessionBag = System::getContainer()->get('session')->getBag('contao_backend');

		// Store the keyword
		if (Input::post('FORM_SUBMIT') == 'item_selector')
		{
			$strKeyword = ltrim(Input::postRaw('keyword'), '*');

			// Make sure the regular expression is valid
			if ($strKeyword != '')
			{
				try
				{
					$this->Database->prepare("SELECT * FROM tl_page WHERE title REGEXP ?")
								   ->limit(1)
								   ->execute($strKeyword);
				}
				catch (\Exception $e)
				{
					$strKeyword = '';
				}
			}

			$objSessionBag->set('page_selector_search', $strKeyword);
			$this->reload();
		}

		$tree = '';
		$this->getPathNodes();
		$for = $objSessionBag->get('page_selector_search');
		$arrFound = array();

		// Search for a specific page
		if ($for != '')
		{
			// Wrap in a try catch block in case the regular expression is invalid (see #7743)
			try
			{
				$strPattern = "CAST(title AS CHAR) REGEXP ?";

				if (substr(Config::get('dbCollation'), -3) == '_ci')
				{
					$strPattern = "LOWER(CAST(title AS CHAR)) REGEXP LOWER(?)";
				}

				$objRoot = $this->Database->prepare("SELECT id FROM tl_page WHERE $strPattern GROUP BY id")
										  ->execute($for);

				if ($objRoot->numRows < 1)
				{
					$GLOBALS['TL_DCA']['tl_page']['list']['sorting']['root'] = array(0);
				}
				else
				{
					$arrIds = array();

					// Respect existing limitations
					if (\is_array($this->rootNodes))
					{
						while ($objRoot->next())
						{
							// Predefined node set (see #3563)
							if (\count(array_intersect($this->rootNodes, $this->Database->getParentRecords($objRoot->id, 'tl_page'))) > 0)
							{
								$arrFound[] = $objRoot->id;
								$arrIds[] = $objRoot->id;
							}
						}
					}
					elseif ($this->User->isAdmin)
					{
						// Show all pages to admins
						while ($objRoot->next())
						{
							$arrFound[] = $objRoot->id;
							$arrIds[] = $objRoot->id;
						}
					}
					else
					{
						while ($objRoot->next())
						{
							// Show only mounted pages to regular users
							if (\count(array_intersect($this->User->pagemounts, $this->Database->getParentRecords($objRoot->id, 'tl_page'))) > 0)
							{
								$arrFound[] = $objRoot->id;
								$arrIds[] = $objRoot->id;
							}
						}
					}

					$GLOBALS['TL_DCA']['tl_page']['list']['sorting']['root'] = array_unique($arrIds);
				}
			}
			catch (\Exception $e) {}
		}

		$strNode = $objSessionBag->get('tl_page_picker');

		// Unset the node if it is not within the predefined node set (see #5899)
		if ($strNode > 0 && \is_array($this->rootNodes))
		{
			if (!\in_array($strNode, $this->Database->getChildRecords($this->rootNodes, 'tl_page')))
			{
				$objSessionBag->remove('tl_page_picker');
			}
		}

		// Add the breadcrumb menu
		if (Input::get('do') != 'page')
		{
			Backend::addPagesBreadcrumb('tl_page_picker');
		}

		// Root nodes (breadcrumb menu)
		if (!empty($GLOBALS['TL_DCA']['tl_page']['list']['sorting']['root']))
		{
			$root = $GLOBALS['TL_DCA']['tl_page']['list']['sorting']['root'];

			// Allow only those roots that are allowed in root nodes
			if (\is_array($this->rootNodes))
			{
				$root = array_intersect(array_merge($this->rootNodes, $this->Database->getChildRecords($this->rootNodes, 'tl_page')), $root);

				if (empty($root))
				{
					$root = $this->rootNodes;

					// Hide the breadcrumb
					$GLOBALS['TL_DCA']['tl_page']['list']['sorting']['breadcrumb'] = '';
				}
			}

			$nodes = $this->eliminateNestedPages($root);

			foreach ($nodes as $node)
			{
				$tree .= $this->renderPagetree($node, -20, false, false, $arrFound);
			}
		}

		// Predefined node set (see #3563)
		elseif (\is_array($this->rootNodes))
		{
			$nodes = $this->eliminateNestedPages($this->rootNodes);

			foreach ($nodes as $node)
			{
				$tree .= $this->renderPagetree($node, -20, false, false, $arrFound);
			}
		}

		// Show all pages to admins
		elseif ($this->User->isAdmin)
		{
			$objPage = $this->Database->prepare("SELECT id FROM tl_page WHERE pid=? ORDER BY sorting")
									  ->execute(0);

			while ($objPage->next())
			{
				$tree .= $this->renderPagetree($objPage->id, -20, false, false, $arrFound);
			}
		}

		// Show only mounted pages to regular users
		else
		{
			$nodes = $this->eliminateNestedPages($this->User->pagemounts);

			foreach ($nodes as $node)
			{
				$tree .= $this->renderPagetree($node, -20, false, false, $arrFound);
			}
		}

		// Select all checkboxes
		if ($this->fieldType == 'checkbox')
		{
			$strReset = "\n" . '    <li class="tl_folder"><div class="tl_left">&nbsp;</div> <div class="tl_right"><label for="check_all_' . $this->strId . '" class="tl_change_selected">' . $GLOBALS['TL_LANG']['MSC']['selectAll'] . '</label> <input type="checkbox" id="check_all_' . $this->strId . '" class="tl_tree_checkbox" value="" onclick="Backend.toggleCheckboxGroup(this,\'' . $this->strName . '\')"></div><div style="clear:both"></div></li>';
		}
		// Reset radio button selection
		else
		{
			$strReset = "\n" . '    <li class="tl_folder"><div class="tl_left">&nbsp;</div> <div class="tl_right"><label for="reset_' . $this->strId . '" class="tl_change_selected">' . $GLOBALS['TL_LANG']['MSC']['resetSelected'] . '</label> <input type="radio" name="' . $this->strName . '" id="reset_' . $this->strName . '" class="tl_tree_radio" value="" onfocus="Backend.getScrollOffset()"></div><div style="clear:both"></div></li>';
		}

		// Return the tree
		return '<ul class="tl_listing tree_view picker_selector'.(($this->strClass != '') ? ' ' . $this->strClass : '').'" id="'.$this->strId.'" data-callback="reloadPagetree" data-inserttag="link_url">
    <li class="tl_folder_top"><div class="tl_left">'.Image::getHtml($GLOBALS['TL_DCA']['tl_page']['list']['sorting']['icon'] ?: 'pagemounts.svg').' '.$GLOBALS['TL_LANG']['MOD']['page'][0].'</div> <div class="tl_right">&nbsp;</div><div style="clear:both"></div></li><li class="parent" id="'.$this->strId.'_parent"><ul>'.$tree.$strReset.'
  </ul></li></ul>';
	}
public function generate()
	{
		$this->import(BackendUser::class, 'User');

		/** @var AttributeBagInterface $objSessionBag */
		$objSessionBag = System::getContainer()->get('session')->getBag('contao_backend');

		// Store the keyword
		if (Input::post('FORM_SUBMIT') == 'item_selector')
		{
			$strKeyword = ltrim(Input::postRaw('keyword'), '*');

			// Make sure the regular expression is valid
			if ($strKeyword != '')
			{
				try
				{
					$this->Database->prepare("SELECT * FROM tl_page WHERE title REGEXP ?")
								   ->limit(1)
								   ->execute($strKeyword);
				}
				catch (\Exception $e)
				{
					$strKeyword = '';
				}
			}

			$objSessionBag->set('page_selector_search', $strKeyword);
			$this->reload();
		}

		$tree = '';
		$this->getPathNodes();
		$for = $objSessionBag->get('page_selector_search');
		$arrFound = array();

		// Search for a specific page
		if ($for != '')
		{
			// Wrap in a try catch block in case the regular expression is invalid (see #7743)
			try
			{
				$strPattern = "CAST(title AS CHAR) REGEXP ?";

				if (substr(Config::get('dbCollation'), -3) == '_ci')
				{
					$strPattern = "LOWER(CAST(title AS CHAR)) REGEXP LOWER(?)";
				}

				$objRoot = $this->Database->prepare("SELECT id FROM tl_page WHERE $strPattern GROUP BY id")
										  ->execute($for);

				if ($objRoot->numRows < 1)
				{
					$GLOBALS['TL_DCA']['tl_page']['list']['sorting']['root'] = array(0);
				}
				else
				{
					$arrIds = array();

					// Respect existing limitations
					if (\is_array($this->rootNodes))
					{
						while ($objRoot->next())
						{
							// Predefined node set (see #3563)
							if (\count(array_intersect($this->rootNodes, $this->Database->getParentRecords($objRoot->id, 'tl_page'))) > 0)
							{
								$arrFound[] = $objRoot->id;
								$arrIds[] = $objRoot->id;
							}
						}
					}
					elseif ($this->User->isAdmin)
					{
						// Show all pages to admins
						while ($objRoot->next())
						{
							$arrFound[] = $objRoot->id;
							$arrIds[] = $objRoot->id;
						}
					}
					else
					{
						while ($objRoot->next())
						{
							// Show only mounted pages to regular users
							if (\count(array_intersect($this->User->pagemounts, $this->Database->getParentRecords($objRoot->id, 'tl_page'))) > 0)
							{
								$arrFound[] = $objRoot->id;
								$arrIds[] = $objRoot->id;
							}
						}
					}

					$GLOBALS['TL_DCA']['tl_page']['list']['sorting']['root'] = array_unique($arrIds);
				}
			}
			catch (\Exception $e) {}
		}

		$strNode = $objSessionBag->get('tl_page_picker');

		// Unset the node if it is not within the predefined node set (see #5899)
		if ($strNode > 0 && \is_array($this->rootNodes))
		{
			if (!\in_array($strNode, $this->Database->getChildRecords($this->rootNodes, 'tl_page')))
			{
				$objSessionBag->remove('tl_page_picker');
			}
		}

		// Add the breadcrumb menu
		if (Input::get('do') != 'page')
		{
			Backend::addPagesBreadcrumb('tl_page_picker');
		}

		// Root nodes (breadcrumb menu)
		if (!empty($GLOBALS['TL_DCA']['tl_page']['list']['sorting']['root']))
		{
			$root = $GLOBALS['TL_DCA']['tl_page']['list']['sorting']['root'];

			// Allow only those roots that are allowed in root nodes
			if (\is_array($this->rootNodes))
			{
				$root = array_intersect(array_merge($this->rootNodes, $this->Database->getChildRecords($this->rootNodes, 'tl_page')), $root);

				if (empty($root))
				{
					$root = $this->rootNodes;

					// Hide the breadcrumb
					$GLOBALS['TL_DCA']['tl_page']['list']['sorting']['breadcrumb'] = '';
				}
			}

			$nodes = $this->eliminateNestedPages($root);

			foreach ($nodes as $node)
			{
				$tree .= $this->renderPagetree($node, -20, false, false, $arrFound);
			}
		}

		// Predefined node set (see #3563)
		elseif (\is_array($this->rootNodes))
		{
			$nodes = $this->eliminateNestedPages($this->rootNodes);

			foreach ($nodes as $node)
			{
				$tree .= $this->renderPagetree($node, -20, false, false, $arrFound);
			}
		}

		// Show all pages to admins
		elseif ($this->User->isAdmin)
		{
			$objPage = $this->Database->prepare("SELECT id FROM tl_page WHERE pid=? ORDER BY sorting")
									  ->execute(0);

			while ($objPage->next())
			{
				$tree .= $this->renderPagetree($objPage->id, -20, false, false, $arrFound);
			}
		}

		// Show only mounted pages to regular users
		else
		{
			$nodes = $this->eliminateNestedPages($this->User->pagemounts);

			foreach ($nodes as $node)
			{
				$tree .= $this->renderPagetree($node, -20, false, false, $arrFound);
			}
		}

		// Select all checkboxes
		if ($this->fieldType == 'checkbox')
		{
			$strReset = "\n" . '    <li class="tl_folder"><div class="tl_left">&nbsp;</div> <div class="tl_right"><label for="check_all_' . $this->strId . '" class="tl_change_selected">' . $GLOBALS['TL_LANG']['MSC']['selectAll'] . '</label> <input type="checkbox" id="check_all_' . $this->strId . '" class="tl_tree_checkbox" value="" onclick="Backend.toggleCheckboxGroup(this,\'' . $this->strName . '\')"></div><div style="clear:both"></div></li>';
		}
		// Reset radio button selection
		else
		{
			$strReset = "\n" . '    <li class="tl_folder"><div class="tl_left">&nbsp;</div> <div class="tl_right"><label for="reset_' . $this->strId . '" class="tl_change_selected">' . $GLOBALS['TL_LANG']['MSC']['resetSelected'] . '</label> <input type="radio" name="' . $this->strName . '" id="reset_' . $this->strName . '" class="tl_tree_radio" value="" onfocus="Backend.getScrollOffset()"></div><div style="clear:both"></div></li>';
		}

		// Return the tree
		return '<ul class="tl_listing tree_view picker_selector'.(($this->strClass != '') ? ' ' . $this->strClass : '').'" id="'.$this->strId.'" data-callback="reloadPagetree" data-inserttag="link_url">
    <li class="tl_folder_top"><div class="tl_left">'.Image::getHtml($GLOBALS['TL_DCA']['tl_page']['list']['sorting']['icon'] ?: 'pagemounts.svg').' '.$GLOBALS['TL_LANG']['MOD']['page'][0].'</div> <div class="tl_right">&nbsp;</div><div style="clear:both"></div></li><li class="parent" id="'.$this->strId.'_parent"><ul>'.$tree.$strReset.'
  </ul></li></ul>';
	}
Generate the widget and return it as string

@return string