vendor/contao/core-bundle/src/Resources/contao/library/Contao/Automator.php line 231

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of Contao.
  4.  *
  5.  * (c) Leo Feyer
  6.  *
  7.  * @license LGPL-3.0-or-later
  8.  */
  9. namespace Contao;
  10. use Contao\CoreBundle\OptIn\OptIn;
  11. use FOS\HttpCacheBundle\CacheManager;
  12. use Symfony\Component\Console\Input\ArgvInput;
  13. use Symfony\Component\Console\Output\NullOutput;
  14. /**
  15.  * Provide methods to run automated jobs.
  16.  *
  17.  * @author Leo Feyer <https://github.com/leofeyer>
  18.  */
  19. class Automator extends System
  20. {
  21.     /**
  22.      * Make the constuctor public
  23.      */
  24.     public function __construct()
  25.     {
  26.         parent::__construct();
  27.     }
  28.     /**
  29.      * Purge the search tables
  30.      */
  31.     public function purgeSearchTables()
  32.     {
  33.         // The search indexer is disabled
  34.         if (!System::getContainer()->has('contao.search.indexer'))
  35.         {
  36.             return;
  37.         }
  38.         $searchIndexer System::getContainer()->get('contao.search.indexer');
  39.         // Clear the index
  40.         $searchIndexer->clear();
  41.         // Add a log entry
  42.         $this->log('Purged the search tables'__METHOD__TL_CRON);
  43.     }
  44.     /**
  45.      * Purge the undo table
  46.      */
  47.     public function purgeUndoTable()
  48.     {
  49.         $objDatabase Database::getInstance();
  50.         // Truncate the table
  51.         $objDatabase->execute("TRUNCATE TABLE tl_undo");
  52.         // Add a log entry
  53.         $this->log('Purged the undo table'__METHOD__TL_CRON);
  54.     }
  55.     /**
  56.      * Purge the version table
  57.      */
  58.     public function purgeVersionTable()
  59.     {
  60.         $objDatabase Database::getInstance();
  61.         // Truncate the table
  62.         $objDatabase->execute("TRUNCATE TABLE tl_version");
  63.         // Add a log entry
  64.         $this->log('Purged the version table'__METHOD__TL_CRON);
  65.     }
  66.     /**
  67.      * Purge the system log
  68.      */
  69.     public function purgeSystemLog()
  70.     {
  71.         $objDatabase Database::getInstance();
  72.         // Truncate the table
  73.         $objDatabase->execute("TRUNCATE TABLE tl_log");
  74.         // Add a log entry
  75.         $this->log('Purged the system log'__METHOD__TL_CRON);
  76.     }
  77.     /**
  78.      * Purge the crawl queue
  79.      */
  80.     public function purgeCrawlQueue()
  81.     {
  82.         $objDatabase Database::getInstance();
  83.         // Truncate the table
  84.         $objDatabase->execute("TRUNCATE TABLE tl_crawl_queue");
  85.         // Add a log entry
  86.         $this->log('Purged the crawl queue'__METHOD__TL_CRON);
  87.     }
  88.     /**
  89.      * Purge the image cache
  90.      */
  91.     public function purgeImageCache()
  92.     {
  93.         $container System::getContainer();
  94.         $strTargetPath StringUtil::stripRootDir($container->getParameter('contao.image.target_dir'));
  95.         $strRootDir $container->getParameter('kernel.project_dir');
  96.         // Walk through the subfolders
  97.         foreach (Folder::scan($strRootDir '/' $strTargetPath) as $dir)
  98.         {
  99.             if (strncmp($dir'.'1) !== 0)
  100.             {
  101.                 $objFolder = new Folder($strTargetPath '/' $dir);
  102.                 $objFolder->purge();
  103.             }
  104.         }
  105.         // Also empty the shared cache so there are no links to deleted images
  106.         $this->purgePageCache();
  107.         // Add a log entry
  108.         $this->log('Purged the image cache'__METHOD__TL_CRON);
  109.     }
  110.     /**
  111.      * Purge the script cache
  112.      */
  113.     public function purgeScriptCache()
  114.     {
  115.         // assets/js and assets/css
  116.         foreach (array('assets/js''assets/css') as $dir)
  117.         {
  118.             // Purge the folder
  119.             $objFolder = new Folder($dir);
  120.             $objFolder->purge();
  121.         }
  122.         // Recreate the internal style sheets
  123.         $this->import(StyleSheets::class, 'StyleSheets');
  124.         $this->StyleSheets->updateStyleSheets();
  125.         // Also empty the shared cache so there are no links to deleted scripts
  126.         $this->purgePageCache();
  127.         // Add a log entry
  128.         $this->log('Purged the script cache'__METHOD__TL_CRON);
  129.     }
  130.     /**
  131.      * Purge the shared cache
  132.      */
  133.     public function purgePageCache()
  134.     {
  135.         $container System::getContainer();
  136.         if (!$container->has('fos_http_cache.cache_manager'))
  137.         {
  138.             $this->log('Cannot purge the shared cache; invalid reverse proxy configuration'__METHOD__TL_ERROR);
  139.             return;
  140.         }
  141.         /** @var CacheManager $cacheManager */
  142.         $cacheManager $container->get('fos_http_cache.cache_manager');
  143.         if (!$cacheManager->supports(CacheManager::CLEAR))
  144.         {
  145.             $this->log('Cannot purge the shared cache; invalid reverse proxy configuration'__METHOD__TL_ERROR);
  146.             return;
  147.         }
  148.         $cacheManager->clearCache();
  149.         // Add a log entry
  150.         $this->log('Purged the shared cache'__METHOD__TL_CRON);
  151.     }
  152.     /**
  153.      * Purge the search cache
  154.      *
  155.      * @deprecated Deprecated since Contao 4.12, to be removed in Contao 5.0.
  156.      */
  157.     public function purgeSearchCache()
  158.     {
  159.         trigger_deprecation('contao/core-bundle''4.12''Using "Contao\Automator::purgeSearchCache()" has been deprecated and will no longer work in Contao 5.0.');
  160.         $strCacheDir StringUtil::stripRootDir(System::getContainer()->getParameter('kernel.cache_dir'));
  161.         $objFolder = new Folder($strCacheDir '/contao/search');
  162.         $objFolder->purge();
  163.         // Add a log entry
  164.         $this->log('Purged the search cache'__METHOD__TL_CRON);
  165.     }
  166.     /**
  167.      * Purge the internal cache
  168.      */
  169.     public function purgeInternalCache()
  170.     {
  171.         $container System::getContainer();
  172.         $clearer $container->get('contao.cache.clear_internal');
  173.         $clearer->clear($container->getParameter('kernel.cache_dir'));
  174.         // Add a log entry
  175.         $this->log('Purged the internal cache'__METHOD__TL_CRON);
  176.     }
  177.     /**
  178.      * Purge the temp folder
  179.      */
  180.     public function purgeTempFolder()
  181.     {
  182.         // Purge the folder
  183.         $objFolder = new Folder('system/tmp');
  184.         $objFolder->purge();
  185.         // Add a log entry
  186.         $this->log('Purged the temp folder'__METHOD__TL_CRON);
  187.     }
  188.     /**
  189.      * Purge registrations that have not been activated within 24 hours
  190.      */
  191.     public function purgeRegistrations()
  192.     {
  193.         $objMember MemberModel::findExpiredRegistrations();
  194.         if ($objMember === null)
  195.         {
  196.             return;
  197.         }
  198.         while ($objMember->next())
  199.         {
  200.             $objMember->delete();
  201.         }
  202.         // Add a log entry
  203.         $this->log('Purged the unactivated member registrations'__METHOD__TL_CRON);
  204.     }
  205.     /**
  206.      * Purge opt-in tokens
  207.      */
  208.     public function purgeOptInTokens()
  209.     {
  210.         /** @var OptIn $optIn */
  211.         $optIn System::getContainer()->get('contao.opt-in');
  212.         $optIn->purgeTokens();
  213.         // Add a log entry
  214.         $this->log('Purged the expired double opt-in tokens'__METHOD__TL_CRON);
  215.     }
  216.     /**
  217.      * Remove old XML files from the share directory
  218.      *
  219.      * @param boolean $blnReturn If true, only return the finds and don't delete
  220.      *
  221.      * @return array An array of old XML files
  222.      */
  223.     public function purgeXmlFiles($blnReturn=false)
  224.     {
  225.         $arrFeeds = array();
  226.         // HOOK: preserve third party feeds
  227.         if (isset($GLOBALS['TL_HOOKS']['removeOldFeeds']) && \is_array($GLOBALS['TL_HOOKS']['removeOldFeeds']))
  228.         {
  229.             foreach ($GLOBALS['TL_HOOKS']['removeOldFeeds'] as $callback)
  230.             {
  231.                 $this->import($callback[0]);
  232.                 $arrFeeds array_merge($arrFeeds$this->{$callback[0]}->{$callback[1]}());
  233.             }
  234.         }
  235.         // Delete the old files
  236.         if (!$blnReturn)
  237.         {
  238.             $shareDir System::getContainer()->getParameter('contao.web_dir') . '/share';
  239.             foreach (Folder::scan($shareDir) as $file)
  240.             {
  241.                 if (is_dir($shareDir '/' $file))
  242.                 {
  243.                     continue; // see #6652
  244.                 }
  245.                 $objFile = new File(StringUtil::stripRootDir($shareDir) . '/' $file);
  246.                 if ($objFile->extension == 'xml' && !\in_array($objFile->filename$arrFeeds))
  247.                 {
  248.                     $objFile->delete();
  249.                 }
  250.             }
  251.         }
  252.         return $arrFeeds;
  253.     }
  254.     /**
  255.      * Invalidate the cached XML sitemaps
  256.      *
  257.      * @param integer $intId The root page ID
  258.      */
  259.     public function generateSitemap($intId=0)
  260.     {
  261.         $container System::getContainer();
  262.         if (!$container->has('fos_http_cache.cache_manager'))
  263.         {
  264.             return;
  265.         }
  266.         /** @var CacheManager $cacheManager */
  267.         $cacheManager $container->get('fos_http_cache.cache_manager');
  268.         $tag 'contao.sitemap';
  269.         if ($intId 0)
  270.         {
  271.             $tag .= '.' $intId;
  272.         }
  273.         $cacheManager->invalidateTags(array($tag));
  274.     }
  275.     /**
  276.      * Regenerate the XML files
  277.      */
  278.     public function generateXmlFiles()
  279.     {
  280.         // Sitemaps
  281.         $this->generateSitemap();
  282.         // HOOK: add custom jobs
  283.         if (isset($GLOBALS['TL_HOOKS']['generateXmlFiles']) && \is_array($GLOBALS['TL_HOOKS']['generateXmlFiles']))
  284.         {
  285.             foreach ($GLOBALS['TL_HOOKS']['generateXmlFiles'] as $callback)
  286.             {
  287.                 $this->import($callback[0]);
  288.                 $this->{$callback[0]}->{$callback[1]}();
  289.             }
  290.         }
  291.         // Also empty the shared cache so there are no links to deleted files
  292.         $this->purgePageCache();
  293.         // Add a log entry
  294.         $this->log('Regenerated the XML files'__METHOD__TL_CRON);
  295.     }
  296.     /**
  297.      * Generate the symlinks in the public folder
  298.      */
  299.     public function generateSymlinks()
  300.     {
  301.         $container System::getContainer();
  302.         $command $container->get('contao.command.symlinks');
  303.         $status $command->run(new ArgvInput(array()), new NullOutput());
  304.         // Add a log entry
  305.         if ($status 0)
  306.         {
  307.             $this->log('The symlinks could not be regenerated'__METHOD__TL_ERROR);
  308.         }
  309.         else
  310.         {
  311.             $this->log('Regenerated the symlinks'__METHOD__TL_CRON);
  312.         }
  313.     }
  314.     /**
  315.      * Generate the internal cache
  316.      */
  317.     public function generateInternalCache()
  318.     {
  319.         $container System::getContainer();
  320.         $warmer $container->get('contao.cache.warm_internal');
  321.         $warmer->warmUp($container->getParameter('kernel.cache_dir'));
  322.         // Add a log entry
  323.         $this->log('Generated the internal cache'__METHOD__TL_CRON);
  324.     }
  325.     /**
  326.      * Rotate the log files
  327.      *
  328.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  329.      *             Use the logger service instead, which rotates its log files automatically.
  330.      */
  331.     public function rotateLogs()
  332.     {
  333.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\Automator::rotateLogs()" has been deprecated and will no longer work in Contao 5.0. Use the logger service instead, which rotates its log files automatically.');
  334.         $projectDir System::getContainer()->getParameter('kernel.project_dir');
  335.         $arrFiles preg_grep('/\.log$/'Folder::scan($projectDir '/system/logs'));
  336.         foreach ($arrFiles as $strFile)
  337.         {
  338.             // Ignore Monolog log files (see #2579)
  339.             if (preg_match('/-\d{4}-\d{2}-\d{2}\.log$/'$strFile))
  340.             {
  341.                 continue;
  342.             }
  343.             $objFile = new File('system/logs/' $strFile '.9');
  344.             // Delete the oldest file
  345.             if ($objFile->exists())
  346.             {
  347.                 $objFile->delete();
  348.             }
  349.             // Rotate the files (e.g. error.log.4 becomes error.log.5)
  350.             for ($i=8$i>0$i--)
  351.             {
  352.                 $strGzName 'system/logs/' $strFile '.' $i;
  353.                 if (file_exists($projectDir '/' $strGzName))
  354.                 {
  355.                     $objFile = new File($strGzName);
  356.                     $objFile->renameTo('system/logs/' $strFile '.' . ($i+1));
  357.                 }
  358.             }
  359.             // Add .1 to the latest file
  360.             $objFile = new File('system/logs/' $strFile);
  361.             $objFile->renameTo('system/logs/' $strFile '.1');
  362.         }
  363.     }
  364. }
  365. class_alias(Automator::class, 'Automator');