From 36d9892b110d44643c80c7c15cee466236aec102 Mon Sep 17 00:00:00 2001 From: Taras Machyshyn Date: Thu, 6 Feb 2014 10:36:57 +0200 Subject: [PATCH] added cron job manager for service jobs and scheduler jobs --- application/Espo/Core/Application.php | 5 +- application/Espo/Core/Container.php | 9 + application/Espo/Core/Cron/ScheduledJob.php | 89 ++++++++ application/Espo/Core/Cron/Service.php | 47 +++++ application/Espo/Core/CronManager.php | 193 ++++++++++++++++++ application/Espo/Core/EntryPointManager.php | 51 +---- application/Espo/Core/Jobs/Base.php | 45 ++++ .../Espo/Core/Utils/File/ClassMerger.php | 108 ++++++++++ .../Espo/Core/defaults/systemConfig.php | 6 + application/Espo/Entities/Job.php | 8 + application/Espo/Jobs/CheckInboundEmails.php | 17 ++ .../Resources/metadata/entityDefs/Job.json | 51 +++++ .../Espo/Resources/metadata/scopes/Job.json | 7 + application/Espo/Services/Job.php | 69 +++++++ application/Espo/Services/ScheduledJob.php | 63 ++++++ testAuth.php | 2 +- tests/Espo/Core/CronManagerTest.php | 98 +++++++++ tests/Espo/Core/EntryPointManagerTest.php | 19 +- .../Espo/Core/Utils/File/ClassMergerTest.php | 107 ++++++++++ .../EntryPoints/Espo/EntryPoints/Download.php | 3 +- .../EntryPoints/cache/entryPoints.php | 7 + 21 files changed, 938 insertions(+), 66 deletions(-) create mode 100644 application/Espo/Core/Cron/ScheduledJob.php create mode 100644 application/Espo/Core/Cron/Service.php create mode 100644 application/Espo/Core/CronManager.php create mode 100644 application/Espo/Core/Jobs/Base.php create mode 100644 application/Espo/Core/Utils/File/ClassMerger.php create mode 100644 application/Espo/Entities/Job.php create mode 100644 application/Espo/Jobs/CheckInboundEmails.php create mode 100644 application/Espo/Resources/metadata/entityDefs/Job.json create mode 100644 application/Espo/Resources/metadata/scopes/Job.json create mode 100644 application/Espo/Services/Job.php create mode 100644 application/Espo/Services/ScheduledJob.php create mode 100644 tests/Espo/Core/CronManagerTest.php create mode 100644 tests/Espo/Core/Utils/File/ClassMergerTest.php create mode 100644 tests/testData/EntryPoints/cache/entryPoints.php diff --git a/application/Espo/Core/Application.php b/application/Espo/Core/Application.php index 087e32ec4a..d812a7ad09 100644 --- a/application/Espo/Core/Application.php +++ b/application/Espo/Core/Application.php @@ -101,7 +101,10 @@ class Application { $auth = $this->getAuth(); $auth->useNoAuth(); - // TODO cron manager + + $cronManager = new \Espo\Core\CronManager($this->container); + + $cronManager->run(); } protected function routeHooks() diff --git a/application/Espo/Core/Container.php b/application/Espo/Core/Container.php index 0a78b30dbd..f08058661e 100644 --- a/application/Espo/Core/Container.php +++ b/application/Espo/Core/Container.php @@ -175,6 +175,15 @@ class Container $this->get('entityManager') ); } + + private function loadClassMerger() + { + return new \Espo\Core\Utils\File\ClassMerger( + $this->get('fileManager'), + $this->get('config'), + $this->get('metadata') + ); + } public function setUser($user) { diff --git a/application/Espo/Core/Cron/ScheduledJob.php b/application/Espo/Core/Cron/ScheduledJob.php new file mode 100644 index 0000000000..a463229438 --- /dev/null +++ b/application/Espo/Core/Cron/ScheduledJob.php @@ -0,0 +1,89 @@ + 'application/Espo/Jobs', + 'modulePath' => 'application/Espo/Modules/{*}/Jobs', + 'customPath' => 'application/Espo/Custom/Jobs', + ); + + + public function __construct(\Espo\Core\Container $container) + { + $this->container = $container; + } + + protected function getContainer() + { + return $this->container; + } + + protected function getEntityManager() + { + return $this->container->get('entityManager'); + } + + + + + public function run(array $job) + { + $jobName = $job['method']; + + $className = $this->getClassName($jobName); + if ($className === false) { + throw new NotFound(); + } + + $jobClass = new $className($this->container); + $method = $this->allowedMethod; + + $jobClass->$method(); + } + + + protected function getClassName($name) + { + $name = Util::normilizeClassName($name); + + if (!isset($this->data)) { + $this->init(); + } + + $name = ucfirst($name); + if (isset($this->data[$name])) { + return $this->data[$name]; + } + + return false; + } + + /** + * Load scheduler classes. It loads from ...Jobs, ex. \Espo\Jobs + * @return null + */ + protected function init() + { + $classMerger = $this->getContainer()->get('classMerger'); + $classMerger->setAllowedMethods( array($this->allowedMethod) ); + $this->data = $classMerger->getData($this->cacheFile, $this->paths); + } + +} \ No newline at end of file diff --git a/application/Espo/Core/Cron/Service.php b/application/Espo/Core/Cron/Service.php new file mode 100644 index 0000000000..33699d132d --- /dev/null +++ b/application/Espo/Core/Cron/Service.php @@ -0,0 +1,47 @@ +serviceFactory = $serviceFactory; + } + + protected function getServiceFactory() + { + return $this->serviceFactory; + } + + + + public function run($job) + { + $serviceName = $job['service_name']; + + if (!$this->getServiceFactory()->checkExists($serviceName)) { + throw new NotFound(); + } + + $service = $this->getServiceFactory()->create($serviceName); + $serviceMethod = $job['method']; + + if (!method_exists($service, $serviceMethod)) { + throw new NotFound(); + } + + $data = $job['data']; + if (Json::isJSON($data)) { + $data = Json::decode($data, true); + } + + $service->$serviceMethod($data); + } + +} \ No newline at end of file diff --git a/application/Espo/Core/CronManager.php b/application/Espo/Core/CronManager.php new file mode 100644 index 0000000000..98e96b1501 --- /dev/null +++ b/application/Espo/Core/CronManager.php @@ -0,0 +1,193 @@ +container = $container; + + $this->config = $this->container->get('config'); + $this->fileManager = $this->container->get('fileManager'); + + $this->scheduledJobCron = new \Espo\Core\Cron\ScheduledJob( $this->container ); + $this->serviceCron = new \Espo\Core\Cron\Service( $this->container->get('serviceFactory') ); + + $this->jobFactory = $this->container->get('serviceFactory')->create('job'); + $this->scheduledJobFactory = $this->container->get('serviceFactory')->create('scheduledJob'); + } + + protected function getContainer() + { + return $this->container; + } + + protected function getConfig() + { + return $this->config; + } + + protected function getFileManager() + { + return $this->fileManager; + } + + protected function getJobFactory() + { + return $this->jobFactory; + } + + protected function getScheduledJobFactory() + { + return $this->scheduledJobFactory; + } + + protected function getScheduledJobCron() + { + return $this->scheduledJobCron; + } + + protected function getServiceCron() + { + return $this->serviceCron; + } + + + protected function getLastRunTime() + { + $lastRunTime = $this->getFileManager()->getContent($this->lastRunTime); + if (!is_int($lastRunTime)) { + $lastRunTime = time() - (intval($this->getConfig()->get('cron.minExecutionTime')) + 60); + } + + return $lastRunTime; + } + + protected function setLastRunTime($time) + { + return $this->getFileManager()->setContentPHP($time, $this->lastRunTime); + } + + protected function checkLastRunTime() + { + $currentTime = time(); + $lastRunTime = $this->getLastRunTime(); + $minTime = $this->getConfig()->get('cron.minExecutionTime'); + + if ($currentTime > ($lastRunTime + $minTime) ) { + return true; + } + + return false; + } + + + public function run() + { + if (!$this->checkLastRunTime()) { + $GLOBALS['log']->add('INFO', 'Cron Manager: Stop cron running, too frequency execution'); + return; //stop cron running, too frequency execution + } + + $this->setLastRunTime(time()); + + //Check scheduled jobs and create related jobs + $this->createJobsFromScheduledJobs(); + + + $pendingJobs = $this->getJobFactory()->getPendingJobs(); + + foreach ($pendingJobs as $job) { + + $this->getJobFactory()->updateEntity($job['id'], array( + 'status' => 'Running', + )); + + $isSuccess = true; + + try { + if (!empty($job['scheduled_job_id'])) { + $this->getScheduledJobCron()->run($job); + } else { + $this->getServiceCron()->run($job); + } + } catch (\Exception $e) { + $isSuccess = false; + $GLOBALS['log']->add('INFO', 'Failed job running, job ['.$job['id'].']. Error Details: '.$e->getMessage()); + } + + $status = $isSuccess ? 'Success' : 'Failed'; + + $this->getJobFactory()->updateEntity($job['id'], array( + 'status' => $status, + )); + + //set status in the schedulerJobLog + if (!empty($job['scheduled_job_id'])) { + $this->getScheduledJobFactory()->addLogRecord($job['scheduled_job_id'], $status); + } + } + + } + + /** + * Check scheduled jobs and create related jobs + * @return array List of created Jobs + */ + protected function createJobsFromScheduledJobs() + { + $activeScheduledJobs = $this->getScheduledJobFactory()->getActiveJobs(); + + $createdJobs = array(); + foreach ($activeScheduledJobs as $scheduledJob) { + + $scheduling = $scheduledJob['scheduling']; + + $cronExpression = \Cron\CronExpression::factory($scheduling); + + try { + //$nextDate = $cronExpression->getNextRunDate()->format('Y-m-d H:i:s'); + $prevDate = $cronExpression->getPreviousRunDate()->format('Y-m-d H:i:s'); + } catch (\Exception $e) { + $GLOBALS['log']->add('Exception', 'ScheduledJob ['.$scheduledJob['id'].']: CronExpression - Impossible CRON expression ['.$scheduling.']'); + continue; + } + + if ($cronExpression->isDue()) { + $prevDate = date('Y-m-d H:i:00'); + } + + $existsJob = $this->getJobFactory()->getJobByScheduledJob($scheduledJob['id'], $prevDate); + + if (!isset($existsJob) || empty($existsJob)) { + //create a job + $data = array( + 'name' => $scheduledJob['name'], + 'status' => 'Pending', + 'scheduledJobId' => $scheduledJob['id'], + 'executeTime' => $prevDate, + 'method' => $scheduledJob['job'], + ); + $createdJobs[] = $this->getJobFactory()->createEntity($data); + } + } + + return $createdJobs; + } + + +} \ No newline at end of file diff --git a/application/Espo/Core/EntryPointManager.php b/application/Espo/Core/EntryPointManager.php index ce08c3ce8b..0c411f2a7e 100644 --- a/application/Espo/Core/EntryPointManager.php +++ b/application/Espo/Core/EntryPointManager.php @@ -16,7 +16,7 @@ class EntryPointManager protected $cacheFile = 'data/cache/application/entryPoints.php'; - protected $allowMethods = array( + protected $allowedMethods = array( 'run', ); @@ -85,50 +85,11 @@ class EntryPointManager protected function init() { - $config = $this->getContainer()->get('config'); - - if (file_exists($this->cacheFile) && $config->get('useCache')) { - $this->data = $this->getFileManager()->getContent($this->cacheFile); - } else { - $this->data = $this->getClassNameHash(array($this->paths['corePath'], $this->paths['customPath']) ); - foreach ($this->getContainer()->get('metadata')->getModuleList() as $moduleName) { - $path = str_replace('{*}', $moduleName, $this->paths['modulePath']); - - $this->data = array_merge($this->data, $this->getClassNameHash(array($path))); - } - if ($config->get('useCache')) { - $result = $this->getFileManager()->setContentPHP($this->data, $this->cacheFile); - if ($result == false) { - throw new \Espo\Core\Exceptions\Error(); - } - } - } - } - - // TODO delegate to another class - protected function getClassNameHash(array $dirs) - { - $data = array(); - foreach ($dirs as $dir) { - if (file_exists($dir)) { - $fileList = $this->getFileManager()->getFileList($dir, false, '\.php$', 'file'); - foreach ($fileList as $file) { - $filePath = Util::concatPath($dir, $file); - $className = Util::getClassName($filePath); - $fileName = $this->getFileManager()->getFileName($filePath); - $fileName = ucfirst($fileName); - - foreach ($this->allowMethods as $methodName) { - if (method_exists($className, $methodName)) { - $data[$fileName] = $className; - } - } - - } - } - } - return $data; - } + $classMerger = $this->getContainer()->get('classMerger'); + $classMerger->setAllowedMethods($this->allowedMethods); + $this->data = $classMerger->getData($this->cacheFile, $this->paths); + } + } diff --git a/application/Espo/Core/Jobs/Base.php b/application/Espo/Core/Jobs/Base.php new file mode 100644 index 0000000000..c91828f3ef --- /dev/null +++ b/application/Espo/Core/Jobs/Base.php @@ -0,0 +1,45 @@ +container; + } + + protected function getEntityManager() + { + return $this->getContainer()->get('entityManager'); + } + + protected function getServiceFactory() + { + return $this->getContainer()->get('serviceFactory'); + } + + protected function getConfig() + { + return $this->getContainer()->get('config'); + } + + protected function getMetadata() + { + return $this->getContainer()->get('metadata'); + } + + public function __construct(Container $container) + { + $this->container = $container; + } + + abstract public function run(); + +} + diff --git a/application/Espo/Core/Utils/File/ClassMerger.php b/application/Espo/Core/Utils/File/ClassMerger.php new file mode 100644 index 0000000000..2fd35edd92 --- /dev/null +++ b/application/Espo/Core/Utils/File/ClassMerger.php @@ -0,0 +1,108 @@ +fileManager = $fileManager; + $this->config = $config; + $this->metadata = $metadata; + } + + protected function getFileManager() + { + return $this->fileManager; + } + + protected function getConfig() + { + return $this->config; + } + + protected function getMetadata() + { + return $this->metadata; + } + + public function setAllowedMethods(array $methods) + { + $this->allowedMethods = $methods; + } + + + + /** + * Return path data of classes + * @param string $cacheFile full path for a cache file, ex. data/cache/application/entryPoints.php + * @param array $paths in format array( + * 'corePath' => '', + * 'modulePath' => '', + * 'customPath' => '', + * ); + * @return array + */ + public function getData($cacheFile, array $paths) + { + $data = null; + + if (file_exists($cacheFile) && $this->getConfig()->get('useCache')) { + $data = $this->getFileManager()->getContent($cacheFile); + } else { + $data = $this->getClassNameHash(array($paths['corePath'], $paths['customPath']) ); + foreach ($this->getMetadata()->getModuleList() as $moduleName) { + $path = str_replace('{*}', $moduleName, $paths['modulePath']); + + $data = array_merge($data, $this->getClassNameHash(array($path))); + } + if ($this->getConfig()->get('useCache')) { + $result = $this->getFileManager()->setContentPHP($data, $cacheFile); + if ($result == false) { + throw new \Espo\Core\Exceptions\Error(); + } + } + } + + return $data; + } + + + protected function getClassNameHash(array $dirs) + { + $data = array(); + foreach ($dirs as $dir) { + if (file_exists($dir)) { + $fileList = $this->getFileManager()->getFileList($dir, false, '\.php$', 'file'); + foreach ($fileList as $file) { + $filePath = Util::concatPath($dir, $file); + $className = Util::getClassName($filePath); + $fileName = $this->getFileManager()->getFileName($filePath); + $fileName = ucfirst($fileName); + + foreach ($this->allowedMethods as $methodName) { + if (method_exists($className, $methodName)) { + $data[$fileName] = $className; + } + } + + } + } + } + return $data; + } +} \ No newline at end of file diff --git a/application/Espo/Core/defaults/systemConfig.php b/application/Espo/Core/defaults/systemConfig.php index 2a7a91891a..fab331356d 100644 --- a/application/Espo/Core/defaults/systemConfig.php +++ b/application/Espo/Core/defaults/systemConfig.php @@ -37,6 +37,12 @@ return array ( 'dateFormat' => 'MM/DD/YYYY', 'timeFormat' => 'HH:mm', + 'cron' => array( + 'maxJobNumber' => 15, /*Max number of jobs per one execution*/ + 'jobPeriod' => 7800, /*Period for jobs, ex. if cron executed at 15:35, it will execute all pending jobs for times from 14:05 to 15:35*/ + 'minExecutionTime' => 50, /*to avoid too frequency execution*/ + ), + 'systemUser' => array( 'id' => 'system', 'userName' => 'system', diff --git a/application/Espo/Entities/Job.php b/application/Espo/Entities/Job.php new file mode 100644 index 0000000000..1d3bb5dfe8 --- /dev/null +++ b/application/Espo/Entities/Job.php @@ -0,0 +1,8 @@ +getConfig()->get('cron'); + + $currentTime = time(); + $periodTime = $currentTime - intval($jobConfigs['jobPeriod']); + $limit = empty($jobConfigs['maxJobNumber']) ? '' : 'LIMIT '.$jobConfigs['maxJobNumber']; + + $query = "SELECT * FROM job WHERE + `status` = 'Pending' + AND execute_time BETWEEN '".date('Y-m-d H:i:s', $periodTime)."' AND '".date('Y-m-d H:i:s', $currentTime)."' + ORDER BY execute_time DESC ".$limit; + + $pdo = $this->getEntityManager()->getPDO(); + $sth = $pdo->prepare($query); + $sth->execute(); + + $rows = $sth->fetchAll(PDO::FETCH_ASSOC); + + $list = array(); + foreach ($rows as $row) { + $list[] = $row; + } + + return $list; + } + + public function getJobByScheduledJob($scheduledJobId, $date) + { + $query = "SELECT * FROM job WHERE + scheduled_job_id = '".$scheduledJobId."' + AND execute_time = '".$date."' + LIMIT 1"; + + $pdo = $this->getEntityManager()->getPDO(); + $sth = $pdo->prepare($query); + $sth->execute(); + + $scheduledJob = $sth->fetchAll(PDO::FETCH_ASSOC); + + return $scheduledJob; + } + + + + //todo remove, used for tests + public function testMethod($data) + { + + } + + //todo remove, used for tests + public function testFailed($data) + { + throw new \Espo\Core\Exceptions\Error(); + } + + +} + diff --git a/application/Espo/Services/ScheduledJob.php b/application/Espo/Services/ScheduledJob.php new file mode 100644 index 0000000000..f1cc5a4bc2 --- /dev/null +++ b/application/Espo/Services/ScheduledJob.php @@ -0,0 +1,63 @@ +getEntityManager()->getPDO(); + $sth = $pdo->prepare($query); + $sth->execute(); + + $rows = $sth->fetchAll(PDO::FETCH_ASSOC); + + $list = array(); + foreach ($rows as $row) { + $list[] = $row; + } + + return $list; + } + + /** + * Add record to ScheduledJobLogRecord about executed job + * @param string $scheduledJobId + * @param string $status + * + * @return string Id of created ScheduledJobLogRecord + */ + public function addLogRecord($scheduledJobId, $status) + { + $lastRun = date('Y-m-d H:i:s'); + + $entityManager = $this->getEntityManager(); + + $scheduledJob = $entityManager->getEntity('ScheduledJob', $scheduledJobId); + $scheduledJob->set('lastRun', $lastRun); + $entityManager->saveEntity($scheduledJob); + + $scheduledJobLog = $entityManager->getEntity('ScheduledJobLogRecord'); + $scheduledJobLog->set(array( + 'scheduledJobId' => $scheduledJobId, + 'name' => $scheduledJob->get('name'), + 'status' => $status, + 'executionTime' => $lastRun, + )); + $scheduledJobLogId = $entityManager->saveEntity($scheduledJobLog); + //$entityManager->getRepository('ScheduledJobLogRecord')->relate($scheduledJobLog, 'scheduledJob', $scheduledJob); + + return $scheduledJobLogId; + } + + + +} + diff --git a/testAuth.php b/testAuth.php index 90ff1e09dc..a4da9ea1e0 100644 --- a/testAuth.php +++ b/testAuth.php @@ -33,7 +33,7 @@ class Auth extends \Slim\Middleware if (!empty($routes[0])) { $routeConditions = $routes[0]->getConditions(); if (isset($routeConditions['auth']) && $routeConditions['auth'] === false) { - //$this->container->setUser(new \Espo\Entities\User()); + $this->container->setUser($this->entityManager->getRepository('User')); $this->next->call(); return; } diff --git a/tests/Espo/Core/CronManagerTest.php b/tests/Espo/Core/CronManagerTest.php new file mode 100644 index 0000000000..e47e193ddb --- /dev/null +++ b/tests/Espo/Core/CronManagerTest.php @@ -0,0 +1,98 @@ +objects['container'] = $this->getMockBuilder('\Espo\Core\Container')->disableOriginalConstructor()->getMock(); + + $this->objects['serviceFactory'] = $this->getMockBuilder('\Espo\Core\ServiceFactory')->disableOriginalConstructor()->getMock(); + $this->objects['config'] = $this->getMockBuilder('\Espo\Core\Utils\Config')->disableOriginalConstructor()->getMock(); + $this->objects['fileManager'] = $this->getMockBuilder('\Espo\Core\Utils\File\Manager')->disableOriginalConstructor()->getMock(); + + + $map = array( + array('config', $this->objects['config']), + array('fileManager', $this->objects['fileManager']), + array('serviceFactory', $this->objects['serviceFactory']), + ); + + $this->objects['container'] + ->expects($this->any()) + ->method('get') + ->will($this->returnValueMap($map)); + + $this->object = new \Espo\Core\CronManager( $this->objects['container'] ); + + $this->reflection = new ReflectionHelper($this->object); + } + + protected function tearDown() + { + $this->object = NULL; + } + + + function testCheckLastRunTimeFileDoesnotExist() + { + $this->objects['fileManager'] + ->expects($this->once()) + ->method('getContent') + ->will($this->returnValue(false)); + + $this->objects['config'] + ->expects($this->exactly(2)) + ->method('get') + ->will($this->returnValue(50)); + + $this->assertTrue( $this->reflection->invokeMethod('checkLastRunTime', array()) ); + } + + + function testCheckLastRunTime() + { + $this->objects['fileManager'] + ->expects($this->once()) + ->method('getContent') + ->will($this->returnValue(time()-60)); + + $this->objects['config'] + ->expects($this->once()) + ->method('get') + ->will($this->returnValue(50)); + + $this->assertTrue( $this->reflection->invokeMethod('checkLastRunTime', array()) ); + } + + + function testCheckLastRunTimeTooFrequency() + { + $this->objects['fileManager'] + ->expects($this->once()) + ->method('getContent') + ->will($this->returnValue(time()-49)); + + $this->objects['config'] + ->expects($this->once()) + ->method('get') + ->will($this->returnValue(50)); + + $this->assertFalse( $this->reflection->invokeMethod('checkLastRunTime', array()) ); + } + + + +} + +?> diff --git a/tests/Espo/Core/EntryPointManagerTest.php b/tests/Espo/Core/EntryPointManagerTest.php index a35967a2ba..847cb06b9f 100644 --- a/tests/Espo/Core/EntryPointManagerTest.php +++ b/tests/Espo/Core/EntryPointManagerTest.php @@ -28,11 +28,7 @@ class EntryPointManagerTest extends \PHPUnit_Framework_TestCase $this->reflection->setProperty('paths', array( 'corePath' => 'tests/testData/EntryPoints/Espo/EntryPoints', 'modulePath' => 'tests/testData/EntryPoints/Espo/Modules/Crm/EntryPoints', - )); - $this->reflection->setProperty('customPaths', array( - 'corePath' => '', - 'modulePath' => '', - )); + )); } protected function tearDown() @@ -40,24 +36,13 @@ class EntryPointManagerTest extends \PHPUnit_Framework_TestCase $this->object = NULL; } - - function testGetData() - { - $result = array( - 'Download' => '\tests\testData\EntryPoints\Espo\EntryPoints\Download', - 'Test' => '\tests\testData\EntryPoints\Espo\EntryPoints\Test', - 'InModule' => '\tests\testData\EntryPoints\Espo\Modules\Crm\EntryPoints\InModule' - ); - $this->assertEquals( $result, $this->reflection->invokeMethod('getData', array($this->reflection->getProperty('paths'))) ); - } - function testGet() { $this->reflection->setProperty('data', array( 'Test' => '\tests\testData\EntryPoints\Espo\EntryPoints\Test', )); - $this->assertEquals('\tests\testData\EntryPoints\Espo\EntryPoints\Test', $this->reflection->invokeMethod('get', array('test')) ); + $this->assertEquals('\tests\testData\EntryPoints\Espo\EntryPoints\Test', $this->reflection->invokeMethod('getClassName', array('test')) ); } diff --git a/tests/Espo/Core/Utils/File/ClassMergerTest.php b/tests/Espo/Core/Utils/File/ClassMergerTest.php new file mode 100644 index 0000000000..4411383474 --- /dev/null +++ b/tests/Espo/Core/Utils/File/ClassMergerTest.php @@ -0,0 +1,107 @@ +objects['fileManager'] = new \Espo\Core\Utils\File\Manager( (object) array()); + $this->objects['config'] = $this->getMockBuilder('\Espo\Core\Utils\Config')->disableOriginalConstructor()->getMock(); + $this->objects['metadata'] = $this->getMockBuilder('\Espo\Core\Utils\Metadata')->disableOriginalConstructor()->getMock(); + + $this->object = new \Espo\Core\Utils\File\ClassMerger($this->objects['fileManager'], $this->objects['config'], $this->objects['metadata']); + + $this->reflection = new ReflectionHelper($this->object); + } + + protected function tearDown() + { + $this->object = NULL; + } + + + function testGetClassNameHash() + { + $paths = array( + 'tests/testData/EntryPoints/Espo/EntryPoints', + 'tests/testData/EntryPoints/Espo/Modules/Crm/EntryPoints', + ); + + $result = array( + 'Download' => '\tests\testData\EntryPoints\Espo\EntryPoints\Download', + 'Test' => '\tests\testData\EntryPoints\Espo\EntryPoints\Test', + 'InModule' => '\tests\testData\EntryPoints\Espo\Modules\Crm\EntryPoints\InModule' + ); + $this->assertEquals( $result, $this->reflection->invokeMethod('getClassNameHash', array($paths)) ); + } + + + function testGetDataWithCache() + { + $this->objects['config'] + ->expects($this->once()) + ->method('get') + ->will($this->returnValue(true)); + + $cacheFile = 'tests/testData/EntryPoints/cache/entryPoints.php'; + $paths = array( + 'corePath' => 'tests/testData/EntryPoints/Espo/EntryPoints', + 'modulePath' => 'tests/testData/EntryPoints/Espo/Modules/{*}/EntryPoints', + 'customPath' => 'tests/testData/EntryPoints/Espo/Custom/EntryPoints', + ); + + $result = array ( + 'Download' => '\\tests\\testData\\EntryPoints\\Espo\\EntryPoints\\Download', + ); + + $this->assertEquals( $result, $this->reflection->invokeMethod('getData', array($cacheFile, $paths)) ); + } + + function testGetDataWithNoCache() + { + $this->objects['config'] + ->expects($this->exactly(2)) + ->method('get') + ->will($this->returnValue(false)); + + $this->objects['metadata'] + ->expects($this->once()) + ->method('getModuleList') + ->will($this->returnValue( + array( + 'Crm', + ) + )); + + $cacheFile = 'tests/testData/EntryPoints/cache/entryPoints.php'; + $paths = array( + 'corePath' => 'tests/testData/EntryPoints/Espo/EntryPoints', + 'modulePath' => 'tests/testData/EntryPoints/Espo/Modules/{*}/EntryPoints', + 'customPath' => 'tests/testData/EntryPoints/Espo/Custom/EntryPoints', + ); + + $result = array( + 'Download' => '\tests\testData\EntryPoints\Espo\EntryPoints\Download', + 'Test' => '\tests\testData\EntryPoints\Espo\EntryPoints\Test', + 'InModule' => '\tests\testData\EntryPoints\Espo\Modules\Crm\EntryPoints\InModule' + ); + + $this->assertEquals( $result, $this->reflection->invokeMethod('getData', array($cacheFile, $paths)) ); + } + + + +} + +?> diff --git a/tests/testData/EntryPoints/Espo/EntryPoints/Download.php b/tests/testData/EntryPoints/Espo/EntryPoints/Download.php index ea9bc53303..e3339eb393 100755 --- a/tests/testData/EntryPoints/Espo/EntryPoints/Download.php +++ b/tests/testData/EntryPoints/Espo/EntryPoints/Download.php @@ -5,8 +5,7 @@ namespace tests\testData\EntryPoints\Espo\EntryPoints; class Download extends \Espo\Core\EntryPoints\Base { - protected $authRequired = true; - + public function run() { diff --git a/tests/testData/EntryPoints/cache/entryPoints.php b/tests/testData/EntryPoints/cache/entryPoints.php new file mode 100644 index 0000000000..38d9e12a10 --- /dev/null +++ b/tests/testData/EntryPoints/cache/entryPoints.php @@ -0,0 +1,7 @@ + '\\tests\\testData\\EntryPoints\\Espo\\EntryPoints\\Download', +); + +?> \ No newline at end of file