File indexing completed on 2024-05-19 06:02:33

0001 <?php
0002 /**
0003  * @author   Krzysztof Suszyński <k.suszynski@mediovski.pl>
0004  * @version  0.2
0005  * @package  php.manager.crontab
0006  *
0007  * Copyright (c) 2012 Krzysztof Suszyński <k.suszynski@mediovski.pl>
0008  *
0009  * Permission is hereby granted, free of charge, to any person obtaining a copy
0010  * of this software and associated documentation files (the "Software"), to deal
0011  * in the Software without restriction, including without limitation the rights
0012  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
0013  * copies of the Software, and to permit persons to whom the Software is
0014  * furnished to do so, subject to the following conditions:
0015  *
0016  * The above copyright notice and this permission notice shall be included in
0017  * all copies or substantial portions of the Software.
0018  *
0019  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0020  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0021  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
0022  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0023  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
0024  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
0025  * THE SOFTWARE.
0026  *
0027  */
0028 
0029 //namespace Crontab\Manager;
0030 
0031 /**
0032  *
0033  */
0034 class Crontab_Manager_CliTool
0035 {
0036     /**
0037      * @var bool
0038      */
0039     protected $_verbose = false;
0040     /**
0041      * @var string|null
0042      */
0043     protected $_sudo = null;
0044     /**
0045      * @var string
0046      */
0047     protected $_targetFile;
0048     /**
0049      * @var array
0050      */
0051     private $_opts;
0052     /**
0053      * @var string|null
0054      */
0055     private $_methodName = null;
0056 
0057     /**
0058      * Constructor
0059      */
0060     public function __construct()
0061     {
0062         $this->_progName = $_SERVER['argv'][0];
0063     }
0064 
0065     /**
0066      * Runs tool from CLI
0067      *
0068      * @return integer
0069      * @static
0070      */
0071     public static function run()
0072     {
0073         $cli = self::_instantinate();
0074         try {
0075             $cli->_parseOpts();
0076             $method = $cli->_dispach();
0077             $out = $method->invoke($cli);
0078             if ($out) {
0079                 $cli->_out($out);
0080             }
0081         } catch (\UnexpectedValueException $optExc) {
0082             $cli->_err("Invalid option: " . $optExc->getMessage() . "\n");
0083             $cli->_err($cli->usage());
0084             return 1;
0085         } catch (\Exception $exc) {
0086             if ($cli->_verbose) {
0087                 $cli->_err($exc . "\n");
0088             } else {
0089                 $cli->_err("Error: " . $exc->getMessage() . "\n");
0090             }
0091             return 2;
0092         }
0093         return 0;
0094     }
0095 
0096     /**
0097      * CliTool factory method
0098      *
0099      * @return CliTool
0100      */
0101     protected static function _instantinate()
0102     {
0103         return new self();
0104     }
0105 
0106     /**
0107      * Enable CRON file action
0108      */
0109     public function enable()
0110     {
0111         $this->_loadClasses();
0112         $manager = $this->_createManager();
0113         if ($this->_sudo) {
0114             $manager->user = $this->_sudo;
0115             $this->_out(sprintf('Using "%s" user\'s crontab with `sudo\' command', $this->_sudo));
0116         }
0117         $manager->enableOrUpdate($this->_targetFile);
0118         $manager->save();
0119 
0120         $this->_out(sprintf('File "%s" merged into crontab', $this->_targetFile));
0121     }
0122 
0123     /**
0124      * Loads classes if they are not present
0125      *
0126      */
0127     private function _loadClasses()
0128     {
0129         if (!class_exists('php\manager\crontab\CrontabManager')) {
0130             require_once __DIR__ . '/CrontabManager.php';
0131         }
0132         if (!class_exists('php\manager\crontab\CronEntry')) {
0133             require_once __DIR__ . '/CronEntry.php';
0134         }
0135     }
0136 
0137     /**
0138      * Crontab_Manager_CrontabManager factory method
0139      *
0140      * @return Crontab_Manager_CrontabManager
0141      */
0142     protected function _createManager()
0143     {
0144         return new Crontab_Manager_CrontabManager();
0145     }
0146 
0147     /**
0148      * Echoes to PHP STDOUT
0149      *
0150      * @param string $message
0151      */
0152     protected function _out($message)
0153     {
0154         fprintf(STDOUT, $message . "\n");
0155     }
0156 
0157     /**
0158      * Enable CRON file action
0159      */
0160     public function disable()
0161     {
0162         $this->_loadClasses();
0163         $manager = $this->_createManager();
0164         if ($this->_sudo) {
0165             $manager->user = $this->_sudo;
0166             $this->_out(sprintf('Using "%s" crontab with `sudo\' command', $this->_sudo));
0167         }
0168         $manager->disable($this->_targetFile);
0169         $manager->save();
0170 
0171         $this->_out(sprintf('File "%s" removed from crontab', $this->_targetFile));
0172     }
0173 
0174     /**
0175      * Usage for cli
0176      *
0177      * @return string
0178      */
0179     public function usage()
0180     {
0181         $usage = "Usage: cronman <--enable|-e FILE,--disable|-d FILE> [--user|-u USER] [--verbose|-v] [--help|-h] [--usage]";
0182         $usage .= "\n\n";
0183         $usage .= "Required params:\n";
0184         $usage .= "   --enable|-e FILE   Enable target FILE to crontab, replace it if already set\n";
0185         $usage .= "   --disable|-d FILE  Disable target FILE from crontab\n";
0186         $usage .= "\n";
0187         $usage .= "Optional params:\n";
0188         $usage .= "   --user|-u USER     For which user to run this program\n";
0189         $usage .= "   --verbose|-v       Display more massages\n";
0190         $usage .= "   --help|-h,--usage  Displays this help\n";
0191 
0192         return $usage;
0193     }
0194 
0195     /**
0196      * Echoes to PHP STDERR
0197      *
0198      * @param string $message
0199      */
0200     protected function _err($message)
0201     {
0202         fprintf(STDERR, $message . "\n");
0203     }
0204 
0205     /**
0206      * Dispaches to an CLI action
0207      *
0208      * @return \ReflectionMethod
0209      */
0210     private function _dispach()
0211     {
0212         $cls = new \ReflectionClass($this);
0213         $method = $cls->getMethod($this->_methodName);
0214         return $method;
0215     }
0216 
0217     /**
0218      * Parse cli opt params
0219      *
0220      * @return CliTool
0221      * @throws \UnexpectedValueException
0222      */
0223     private function _parseOpts()
0224     {
0225         $longOpts = array(
0226             'enable:',
0227             'disable:',
0228             'user:',
0229             'help',
0230             'usage',
0231             'verbose'
0232         );
0233         $opts = getopt('e:d:hvu:', $longOpts);
0234         $this->_opts = $opts;
0235         $this->_verbose = $this->_isSet('verbose', 'v');
0236         if ($this->_isSet('usage') || $this->_isSet('help', 'h')) {
0237             $this->_methodName = 'usage';
0238             return $this;
0239         }
0240         if ($this->_isSet('user', 'u')) {
0241             $this->_sudo = $this->_getOpt('user', 'u');
0242         }
0243         if (
0244             ($this->_isSet('enable', 'e') && $this->_isSet('disable', 'd')) ||
0245             ($this->_isNotSet('enable', 'e') && $this->_isNotSet('disable', 'd'))
0246         ) {
0247             throw new \UnexpectedValueException(
0248                 '--enable|-e or --disable|-d opt is required, but only one of them'
0249             );
0250         }
0251         if ($this->_isSet('enable', 'e')) {
0252             $this->_methodName = 'enable';
0253             $this->_targetFile = $this->_getOpt('enable', 'e');
0254             return $this;
0255         }
0256         if ($this->_isSet('disable', 'd')) {
0257             $this->_methodName = 'disable';
0258             $this->_targetFile = $this->_getOpt('disable', 'd');
0259             return $this;
0260         }
0261 
0262         return $this;
0263     }
0264 
0265     /**
0266      * Checks if opt is set
0267      *
0268      * @param string $name
0269      * @param string|null $alias
0270      * @return bool
0271      */
0272     protected function _isSet($name, $alias = null)
0273     {
0274         return isset($this->_opts[$name]) ||
0275         ($alias && isset($this->_opts[$alias]));
0276     }
0277 
0278     /**
0279      * Gets opt if is set
0280      *
0281      * @param string $name
0282      * @param string|null $alias
0283      * @param mixed|null $default
0284      * @return bool
0285      */
0286     protected function _getOpt($name, $alias = null, $default = null)
0287     {
0288         if ($this->_isSet($name, $alias)) {
0289             if ($this->_isSet($name)) {
0290                 return $this->_opts[$name];
0291             } else {
0292                 return $this->_opts[$alias];
0293             }
0294         }
0295         return $default;
0296     }
0297 
0298     /**
0299      * Checks if opt is not set
0300      *
0301      * @param string $name
0302      * @param string|null $alias
0303      * @return bool
0304      */
0305     protected function _isNotSet($name, $alias = null)
0306     {
0307         return !isset($this->_opts[$name]) &&
0308         !($alias && isset($this->_opts[$alias]));
0309     }
0310 
0311 }
0312 
0313 if (PHP_SAPI == 'cli' && isset($_SERVER['argv'])
0314     && realpath($_SERVER['argv'][0]) == __FILE__
0315 ) {
0316     exit(CliTool::run());
0317 }