/**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $io = new DrupalStyle($input, $output);
     $modules = $input->getArgument('module');
     if (!$this->lock->acquire('cron', 900.0)) {
         $io->warning($this->trans('commands.cron.execute.messages.lock'));
         return 1;
     }
     if (in_array('all', $modules)) {
         $modules = $this->moduleHandler->getImplementations('cron');
     }
     foreach ($modules as $module) {
         if (!$this->moduleHandler->implementsHook($module, 'cron')) {
             $io->warning(sprintf($this->trans('commands.cron.execute.messages.module-invalid'), $module));
             continue;
         }
         try {
             $io->info(sprintf($this->trans('commands.cron.execute.messages.executing-cron'), $module));
             $this->moduleHandler->invoke($module, 'cron');
         } catch (\Exception $e) {
             watchdog_exception('cron', $e);
             $io->error($e->getMessage());
         }
     }
     $this->state->set('system.cron_last', REQUEST_TIME);
     $this->lock->release('cron');
     $this->chainQueue->addCommand('cache:rebuild', ['cache' => 'all']);
     $io->success($this->trans('commands.cron.execute.messages.success'));
     return 0;
 }
 /**
  * Tests the destruct method.
  *
  * @covers ::destruct
  */
 public function testDestruct()
 {
     $this->libraryDiscoveryParser->expects($this->once())->method('buildByExtension')->with('test')->will($this->returnValue($this->libraryData));
     $lock_key = 'library_info:Drupal\\Core\\Cache\\CacheCollector';
     $this->lock->expects($this->once())->method('acquire')->with($lock_key)->will($this->returnValue(TRUE));
     $this->cache->expects($this->exactly(2))->method('get')->with('library_info')->will($this->returnValue(FALSE));
     $this->cache->expects($this->once())->method('set')->with('library_info', array('test' => $this->libraryData), Cache::PERMANENT, array('library_info'));
     $this->lock->expects($this->once())->method('release')->with($lock_key);
     // This should get data and persist the key.
     $this->libraryDiscoveryCollector->get('test');
     $this->libraryDiscoveryCollector->destruct();
 }
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $io = new DrupalStyle($input, $output);
     try {
         $this->lock->release('cron');
         $io->info($this->trans('commands.cron.release.messages.released'));
     } catch (Exception $e) {
         $io->error($e->getMessage());
         return 1;
     }
     $this->chainQueue->addCommand('cache:rebuild', ['cache' => 'all']);
     return 0;
 }
 /**
  * {@inheritdoc}
  */
 protected function setUp()
 {
     $this->storage = $this->getMock('Drupal\\locale\\StringStorageInterface');
     $this->cache = $this->getMock('Drupal\\Core\\Cache\\CacheBackendInterface');
     $this->lock = $this->getMock('Drupal\\Core\\Lock\\LockBackendInterface');
     $this->lock->expects($this->never())->method($this->anything());
     $this->user = $this->getMock('Drupal\\Core\\Session\\AccountInterface');
     $this->user->expects($this->any())->method('getRoles')->will($this->returnValue(array('anonymous')));
     $this->configFactory = $this->getConfigFactoryStub(array('locale.settings' => array('cache_strings' => FALSE)));
     $this->languageManager = $this->getMock('Drupal\\Core\\Language\\LanguageManagerInterface');
     $container = new ContainerBuilder();
     $container->set('current_user', $this->user);
     \Drupal::setContainer($container);
 }
Example #5
0
 /**
  * {@inheritdoc}
  */
 public function run()
 {
     // Allow execution to continue even if the request gets cancelled.
     @ignore_user_abort(TRUE);
     // Prevent session information from being saved while cron is running.
     $original_session_saving = $this->sessionManager->isEnabled();
     $this->sessionManager->disable();
     // Force the current user to anonymous to ensure consistent permissions on
     // cron runs.
     $original_user = $this->currentUser->getAccount();
     $this->currentUser->setAccount(new AnonymousUserSession());
     // Try to allocate enough time to run all the hook_cron implementations.
     drupal_set_time_limit(240);
     $return = FALSE;
     // Try to acquire cron lock.
     if (!$this->lock->acquire('cron', 240.0)) {
         // Cron is still running normally.
         watchdog('cron', 'Attempting to re-run cron while it is already running.', array(), WATCHDOG_WARNING);
     } else {
         $this->invokeCronHandlers();
         $this->setCronLastTime();
         // Release cron lock.
         $this->lock->release('cron');
         // Return TRUE so other functions can check if it did run successfully
         $return = TRUE;
     }
     // Process cron queues.
     $this->processQueues();
     // Restore the user.
     $this->currentUser->setAccount($original_user);
     if ($original_session_saving) {
         $this->sessionManager->enable();
     }
     return $return;
 }
Example #6
0
 /**
  * {@inheritdoc}
  */
 public function rebuild()
 {
     if ($this->building) {
         throw new \RuntimeException('Recursive router rebuild detected.');
     }
     if (!$this->lock->acquire('router_rebuild')) {
         // Wait for another request that is already doing this work.
         // We choose to block here since otherwise the routes might not be
         // available, resulting in a 404.
         $this->lock->wait('router_rebuild');
         return FALSE;
     }
     $this->building = TRUE;
     $collection = new RouteCollection();
     foreach ($this->getRouteDefinitions() as $routes) {
         // The top-level 'routes_callback' is a list of methods in controller
         // syntax, see \Drupal\Core\Controller\ControllerResolver. These methods
         // should return a set of \Symfony\Component\Routing\Route objects, either
         // in an associative array keyed by the route name, which will be iterated
         // over and added to the collection for this provider, or as a new
         // \Symfony\Component\Routing\RouteCollection object, which will be added
         // to the collection.
         if (isset($routes['route_callbacks'])) {
             foreach ($routes['route_callbacks'] as $route_callback) {
                 $callback = $this->controllerResolver->getControllerFromDefinition($route_callback);
                 if ($callback_routes = call_user_func($callback)) {
                     // If a RouteCollection is returned, add the whole collection.
                     if ($callback_routes instanceof RouteCollection) {
                         $collection->addCollection($callback_routes);
                     } else {
                         foreach ($callback_routes as $name => $callback_route) {
                             $collection->add($name, $callback_route);
                         }
                     }
                 }
             }
             unset($routes['route_callbacks']);
         }
         foreach ($routes as $name => $route_info) {
             $route_info += array('defaults' => array(), 'requirements' => array(), 'options' => array());
             $route = new Route($route_info['path'], $route_info['defaults'], $route_info['requirements'], $route_info['options']);
             $collection->add($name, $route);
         }
     }
     // DYNAMIC is supposed to be used to add new routes based upon all the
     // static defined ones.
     $this->dispatcher->dispatch(RoutingEvents::DYNAMIC, new RouteBuildEvent($collection));
     // ALTER is the final step to alter all the existing routes. We cannot stop
     // people from adding new routes here, but we define two separate steps to
     // make it clear.
     $this->dispatcher->dispatch(RoutingEvents::ALTER, new RouteBuildEvent($collection));
     $this->checkProvider->setChecks($collection);
     $this->dumper->addRoutes($collection);
     $this->dumper->dump();
     $this->lock->release('router_rebuild');
     $this->dispatcher->dispatch(RoutingEvents::FINISHED, new Event());
     $this->building = FALSE;
     $this->rebuildNeeded = FALSE;
     return TRUE;
 }
Example #7
0
 /**
  * {@inheritdoc}
  */
 public function run()
 {
     // Allow execution to continue even if the request gets cancelled.
     @ignore_user_abort(TRUE);
     // Force the current user to anonymous to ensure consistent permissions on
     // cron runs.
     $this->accountSwitcher->switchTo(new AnonymousUserSession());
     // Try to allocate enough time to run all the hook_cron implementations.
     drupal_set_time_limit(240);
     $return = FALSE;
     // Try to acquire cron lock.
     if (!$this->lock->acquire('cron', 900.0)) {
         // Cron is still running normally.
         $this->logger->warning('Attempting to re-run cron while it is already running.');
     } else {
         $this->invokeCronHandlers();
         $this->setCronLastTime();
         // Release cron lock.
         $this->lock->release('cron');
         // Return TRUE so other functions can check if it did run successfully
         $return = TRUE;
     }
     // Process cron queues.
     $this->processQueues();
     // Restore the user.
     $this->accountSwitcher->switchBack();
     return $return;
 }
 /**
  * Creates a lock that will persist across requests.
  *
  * @param string $lock_name
  *   The name of the persistent lock to acquire.
  *
  * @return string
  *   The text to display.
  */
 public function lockPersist($lock_name)
 {
     if ($this->persistentLock->acquire($lock_name)) {
         return ['#markup' => 'TRUE: Lock successfully acquired in SystemTestController::lockPersist()'];
     } else {
         return ['#markup' => 'FALSE: Lock not acquired in SystemTestController::lockPersist()'];
     }
 }
Example #9
0
 /**
  * Executes a callback.
  *
  * @param \Drupal\feeds\FeedInterface $feeds_feed
  *   The Feed we are executing a job for.
  * @param \Symfony\Component\HttpFoundation\Request $request
  *   The request object to grab POST params from.
  *
  * @todo Configure a time limit.
  * @todo Really awesome error handling.
  */
 public function execute(FeedInterface $feeds_feed, Request $request)
 {
     $cid = 'feeds_feed:' . $feeds_feed->id();
     if ($token = $request->request->get('token') && ($job = $this->state->get($cid))) {
         if ($job['token'] == $token && ($lock = $this->lockBackend->acquire($cid))) {
             $method = $job['method'];
             $this->state->delete($cid);
             ignore_user_abort(TRUE);
             set_time_limit(0);
             while ($feeds_feed->{$method}() != StateInterface::BATCH_COMPLETE) {
                 // Reset static caches in between runs to avoid memory leaks.
                 drupal_reset_static();
             }
             $this->lockBackend->release($cid);
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function getMails($limit = self::UNLIMITED, $conditions = array())
 {
     $messages = array();
     // Continue to support 'nid' as a condition.
     if (!empty($conditions['nid'])) {
         $conditions['entity_type'] = 'node';
         $conditions['entity_id'] = $conditions['nid'];
         unset($conditions['nid']);
     }
     // Add default status condition if not set.
     if (!isset($conditions['status'])) {
         $conditions['status'] = array(SpoolStorageInterface::STATUS_PENDING, SpoolStorageInterface::STATUS_IN_PROGRESS);
     }
     // Special case for the status condition, the in progress actually only
     // includes spool items whose locking time has expired. So this need to build
     // an OR condition for them.
     $status_or = new Condition('OR');
     $statuses = is_array($conditions['status']) ? $conditions['status'] : array($conditions['status']);
     foreach ($statuses as $status) {
         if ($status == SpoolStorageInterface::STATUS_IN_PROGRESS) {
             $status_or->condition((new Condition('AND'))->condition('status', $status)->condition('s.timestamp', $this->getExpirationTime(), '<'));
         } else {
             $status_or->condition('status', $status);
         }
     }
     unset($conditions['status']);
     $query = $this->connection->select('simplenews_mail_spool', 's')->fields('s')->condition($status_or)->orderBy('s.timestamp', 'ASC');
     // Add conditions.
     foreach ($conditions as $field => $value) {
         $query->condition($field, $value);
     }
     /* BEGIN CRITICAL SECTION */
     // The semaphore ensures that multiple processes get different message ID's,
     // so that duplicate messages are not sent.
     if ($this->lock->acquire('simplenews_acquire_mail')) {
         // Get message id's
         // Allocate messages
         if ($limit > 0) {
             $query->range(0, $limit);
         }
         foreach ($query->execute() as $message) {
             if (Unicode::strlen($message->data)) {
                 $message->data = unserialize($message->data);
             } else {
                 $message->data = simplenews_subscriber_load_by_mail($message->mail);
             }
             $messages[$message->msid] = $message;
         }
         if (count($messages) > 0) {
             // Set the state and the timestamp of the messages
             $this->updateMails(array_keys($messages), array('status' => SpoolStorageInterface::STATUS_IN_PROGRESS));
         }
         $this->lock->release('simplenews_acquire_mail');
     }
     /* END CRITICAL SECTION */
     return new SpoolList($messages);
 }
 /**
  * Deletes data from the store for a given key and releases the lock on it.
  *
  * @param string $key
  *   The key of the data to delete.
  */
 public function delete($key)
 {
     if (!$this->lockBackend->acquire($key)) {
         $this->lockBackend->wait($key);
         if (!$this->lockBackend->acquire($key)) {
             throw new TempStoreException(String::format("Couldn't acquire lock to delete item %key from %collection temporary storage.", array('%key' => $key, '%collection' => $this->storage->getCollectionName())));
         }
     }
     $this->storage->delete($key);
     $this->lockBackend->release($key);
 }
Example #12
0
 /**
  * Tests the deleteIfOwner() method.
  *
  * @covers ::deleteIfOwner()
  */
 public function testDeleteIfOwner()
 {
     $this->lock->expects($this->once())->method('acquire')->with('test_2')->will($this->returnValue(TRUE));
     $this->keyValue->expects($this->at(0))->method('get')->with('test_1')->will($this->returnValue(FALSE));
     $this->keyValue->expects($this->at(1))->method('get')->with('test_2')->will($this->returnValue($this->ownObject));
     $this->keyValue->expects($this->at(2))->method('delete')->with('test_2');
     $this->keyValue->expects($this->at(3))->method('get')->with('test_3')->will($this->returnValue($this->otherObject));
     $this->assertTrue($this->tempStore->deleteIfOwner('test_1'));
     $this->assertTrue($this->tempStore->deleteIfOwner('test_2'));
     $this->assertFalse($this->tempStore->deleteIfOwner('test_3'));
 }
Example #13
0
 /**
  * Tests \Drupal\Core\Routing\RouteBuilder::rebuildIfNeeded() method.
  */
 public function testRebuildIfNeeded()
 {
     $this->lock->expects($this->once())->method('acquire')->with('router_rebuild')->will($this->returnValue(TRUE));
     $this->lock->expects($this->once())->method('release')->with('router_rebuild');
     $this->yamlDiscovery->expects($this->any())->method('findAll')->will($this->returnValue(array()));
     $this->routeBuilder->setRebuildNeeded();
     // This will trigger a successful rebuild.
     $this->assertTrue($this->routeBuilder->rebuildIfNeeded());
     // This will not trigger a rebuild.
     $this->assertFalse($this->routeBuilder->rebuildIfNeeded());
 }
Example #14
0
 /**
  * Deletes data from the store for a given key and releases the lock on it.
  *
  * @param string $key
  *   The key of the data to delete.
  */
 public function delete($key)
 {
     if (!$this->lockBackend->acquire($key)) {
         $this->lockBackend->wait($key);
         if (!$this->lockBackend->acquire($key)) {
             throw new TempStoreException("Couldn't acquire lock to delete item '{$key}' from {$this->storage->getCollectionName()} temporary storage.");
         }
     }
     $this->storage->delete($key);
     $this->lockBackend->release($key);
 }
 /**
  * Perform menu-specific rebuilding.
  */
 protected function menuLinksRebuild()
 {
     if ($this->lock->acquire(__FUNCTION__)) {
         $transaction = db_transaction();
         try {
             // Ensure the menu links are up to date.
             $this->menuLinkManager->rebuild();
             // Ignore any database replicas temporarily.
             db_ignore_replica();
         } catch (\Exception $e) {
             $transaction->rollback();
             watchdog_exception('menu', $e);
         }
         $this->lock->release(__FUNCTION__);
     } else {
         // Wait for another request that is already doing this work.
         // We choose to block here since otherwise the router item may not
         // be available during routing resulting in a 404.
         $this->lock->wait(__FUNCTION__);
     }
 }
 /**
  * Perform menu-specific rebuilding.
  */
 protected function menuLinksRebuild()
 {
     if ($this->lock->acquire(__FUNCTION__)) {
         $transaction = db_transaction();
         try {
             // Ensure the menu links are up to date.
             menu_link_rebuild_defaults();
             // Clear the menu cache.
             menu_cache_clear_all();
             // Track which menu items are expanded.
             _menu_update_expanded_menus();
         } catch (\Exception $e) {
             $transaction->rollback();
             watchdog_exception('menu', $e);
         }
         $this->lock->release(__FUNCTION__);
     } else {
         // Wait for another request that is already doing this work.
         // We choose to block here since otherwise the router item may not
         // be available during routing resulting in a 404.
         $this->lock->wait(__FUNCTION__);
     }
 }
 /**
  * Tests \Drupal\Core\Routing\RouteBuilder::rebuildIfNeeded() method.
  */
 public function testRebuildIfNecessary()
 {
     $this->lock->expects($this->once())->method('acquire')->with('router_rebuild')->will($this->returnValue(TRUE));
     $this->lock->expects($this->once())->method('release')->with('router_rebuild');
     $this->routeBuilderIndicator->expects($this->once())->method('setRebuildNeeded');
     $this->routeBuilderIndicator->expects($this->once())->method('setRebuildDone');
     $this->routeBuilderIndicator->expects($this->exactly(2))->method('isRebuildNeeded')->will($this->onConsecutiveCalls(TRUE, FALSE));
     $this->yamlDiscovery->expects($this->any())->method('findAll')->will($this->returnValue(array()));
     $this->routeBuilder->setRebuildNeeded();
     // This will trigger a successful rebuild.
     $this->assertTrue($this->routeBuilder->rebuildIfNeeded());
     // This will not trigger a rebuild.
     $this->assertFalse($this->routeBuilder->rebuildIfNeeded());
 }
 /**
  * Tests the destruct method.
  *
  * @covers ::destruct
  */
 public function testDestruct()
 {
     $this->activeTheme = $this->getMockBuilder('Drupal\\Core\\Theme\\ActiveTheme')->disableOriginalConstructor()->getMock();
     $this->themeManager->expects($this->once())->method('getActiveTheme')->willReturn($this->activeTheme);
     $this->activeTheme->expects($this->once())->method('getName')->willReturn('kitten_theme');
     $this->libraryDiscoveryCollector = new LibraryDiscoveryCollector($this->cache, $this->lock, $this->libraryDiscoveryParser, $this->themeManager);
     $this->libraryDiscoveryParser->expects($this->once())->method('buildByExtension')->with('test')->willReturn($this->libraryData);
     $lock_key = 'library_info:kitten_theme:Drupal\\Core\\Cache\\CacheCollector';
     $this->lock->expects($this->once())->method('acquire')->with($lock_key)->will($this->returnValue(TRUE));
     $this->cache->expects($this->exactly(2))->method('get')->with('library_info:kitten_theme')->willReturn(FALSE);
     $this->cache->expects($this->once())->method('set')->with('library_info:kitten_theme', array('test' => $this->libraryData), Cache::PERMANENT, ['library_info']);
     $this->lock->expects($this->once())->method('release')->with($lock_key);
     // This should get data and persist the key.
     $this->libraryDiscoveryCollector->get('test');
     $this->libraryDiscoveryCollector->destruct();
 }
 /**
  * Deletes data from the store for a given key and releases the lock on it.
  *
  * @param string $key
  *   The key of the data to delete.
  *
  * @return bool
  *   TRUE if the object was deleted or does not exist, FALSE if it exists but
  *   is not owned by $this->owner.
  */
 public function delete($key)
 {
     $key = $this->createkey($key);
     if (!($object = $this->storage->get($key))) {
         return TRUE;
     } elseif ($object->owner != $this->getOwner()) {
         return FALSE;
     }
     if (!$this->lockBackend->acquire($key)) {
         $this->lockBackend->wait($key);
         if (!$this->lockBackend->acquire($key)) {
             throw new TempStoreException(SafeMarkup::format("Couldn't acquire lock to delete item %key from %collection temporary storage.", array('%key' => $key, '%collection' => $this->storage->getCollectionName())));
         }
     }
     $this->storage->delete($key);
     $this->lockBackend->release($key);
     return TRUE;
 }
Example #20
0
 /**
  * Deletes data from the store for a given key and releases the lock on it.
  *
  * @param string $key
  *   The key of the data to delete.
  *
  * @return bool
  *   TRUE if the object was deleted or does not exist, FALSE if it exists but
  *   is not owned by $this->owner.
  */
 public function delete($key)
 {
     $key = $this->createkey($key);
     if (!($object = $this->storage->get($key))) {
         return TRUE;
     } elseif ($object->owner != $this->getOwner()) {
         return FALSE;
     }
     if (!$this->lockBackend->acquire($key)) {
         $this->lockBackend->wait($key);
         if (!$this->lockBackend->acquire($key)) {
             throw new TempStoreException("Couldn't acquire lock to delete item '{$key}' from '{$this->storage->getCollectionName()}' temporary storage.");
         }
     }
     $this->storage->delete($key);
     $this->lockBackend->release($key);
     return TRUE;
 }
Example #21
0
 /**
  * Writes a value to the persistent cache immediately.
  *
  * @param bool $lock
  *   (optional) Whether to acquire a lock before writing to cache. Defaults to
  *   TRUE.
  */
 protected function updateCache($lock = TRUE)
 {
     $data = array();
     foreach ($this->keysToPersist as $offset => $persist) {
         if ($persist) {
             $data[$offset] = $this->storage[$offset];
         }
     }
     if (empty($data) && empty($this->keysToRemove)) {
         return;
     }
     // Lock cache writes to help avoid stampedes.
     $cid = $this->getCid();
     $lock_name = $this->normalizeLockName($cid . ':' . __CLASS__);
     if (!$lock || $this->lock->acquire($lock_name)) {
         // Set and delete operations invalidate the cache item. Try to also load
         // an eventually invalidated cache entry, only update an invalidated cache
         // entry if the creation date did not change as this could result in an
         // inconsistent cache.
         if ($cache = $this->cache->get($cid, $this->cacheInvalidated)) {
             if ($this->cacheInvalidated && $cache->created != $this->cacheCreated) {
                 // We have invalidated the cache in this request and got a different
                 // cache entry. Do not attempt to overwrite data that might have been
                 // changed in a different request. We'll let the cache rebuild in
                 // later requests.
                 $this->cache->delete($cid);
                 $this->lock->release($lock_name);
                 return;
             }
             $data = array_merge($cache->data, $data);
         }
         // Remove keys marked for deletion.
         foreach ($this->keysToRemove as $delete_key) {
             unset($data[$delete_key]);
         }
         $this->cache->set($cid, $data, Cache::PERMANENT, $this->tags);
         if ($lock) {
             $this->lock->release($lock_name);
         }
     }
     $this->keysToPersist = array();
     $this->keysToRemove = array();
 }
Example #22
0
 /**
  * Tests getCid()
  *
  * @covers ::getCid
  */
 public function testGetCid()
 {
     $data = $this->provider()[1];
     /** @var \Symfony\Component\HttpFoundation\Request $request */
     $request = $data[0];
     /** @var \Symfony\Component\Routing\Route $route */
     $route = $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT);
     $route->setPath('/test/{b}/{a}');
     $request->attributes->get('_raw_variables')->add(['b' => 1, 'a' => 0]);
     $this->requestStack->push($request);
     $this->menuLinkManager->expects($this->any())->method('loadLinksbyRoute')->with('baby_llama')->will($this->returnValue($data[1]));
     $expected_link = $data[3];
     $expected_trail = $data[4];
     $expected_trail_ids = array_combine($expected_trail, $expected_trail);
     $this->menuLinkManager->expects($this->any())->method('getParentIds')->will($this->returnValueMap(array(array($expected_link->getPluginId(), $expected_trail_ids))));
     $this->assertSame($expected_trail_ids, $this->menuActiveTrail->getActiveTrailIds($data[2]));
     $this->cache->expects($this->once())->method('set')->with('active-trail:route:baby_llama:route_parameters:' . serialize(['a' => 0, 'b' => 1]));
     $this->lock->expects($this->any())->method('acquire')->willReturn(TRUE);
     $this->menuActiveTrail->destruct();
 }
Example #23
0
 /**
  * {@inheritdoc}
  */
 public function sendSpool($limit = SpoolStorageInterface::UNLIMITED, array $conditions = array())
 {
     $check_counter = 0;
     // Send pending messages from database cache.
     $spool = $this->spoolStorage->getMails($limit, $conditions);
     if (count($spool) > 0) {
         // Switch to the anonymous user.
         $anonymous_user = new AnonymousUserSession();
         $this->accountSwitcher->switchTo($anonymous_user);
         $count_fail = $count_success = 0;
         $sent = array();
         $this->startTimer();
         while ($mail = $spool->nextMail()) {
             $mail->setKey('node');
             $result = $this->sendMail($mail);
             // Update spool status.
             // This is not optimal for performance but prevents duplicate emails
             // in case of PHP execution time overrun.
             foreach ($spool->getProcessed() as $msid => $row) {
                 $row_result = isset($row->result) ? $row->result : $result;
                 $this->spoolStorage->updateMails(array($msid), $row_result);
                 if ($row_result['status'] == SpoolStorageInterface::STATUS_DONE) {
                     $count_success++;
                     if (!isset($sent[$row->entity_type][$row->entity_id][$row->langcode])) {
                         $sent[$row->entity_type][$row->entity_id][$row->langcode] = 1;
                     } else {
                         $sent[$row->entity_type][$row->entity_id][$row->langcode]++;
                     }
                 }
                 if ($row_result['error']) {
                     $count_fail++;
                 }
             }
             // Check every n emails if we exceed the limit.
             // When PHP maximum execution time is almost elapsed we interrupt
             // sending. The remainder will be sent during the next cron run.
             if (++$check_counter >= static::SEND_CHECK_INTERVAL && ini_get('max_execution_time') > 0) {
                 $check_counter = 0;
                 // Break the sending if a percentage of max execution time was exceeded.
                 $elapsed = $this->getCurrentExecutionTime();
                 if ($elapsed > static::SEND_TIME_LIMIT * ini_get('max_execution_time')) {
                     $this->logger->warning('Sending interrupted: PHP maximum execution time almost exceeded. Remaining newsletters will be sent during the next cron run. If this warning occurs regularly you should reduce the !cron_throttle_setting.', array('!cron_throttle_setting' => \Drupal::l(t('Cron throttle setting'), new Url('simplenews.settings_mail'))));
                     break;
                 }
             }
         }
         // It is possible that all or at the end some results failed to get
         // prepared, report them separately.
         foreach ($spool->getProcessed() as $msid => $row) {
             $row_result = $row->result;
             $this->spoolStorage->updateMails(array($msid), $row_result);
             if ($row_result['status'] == SpoolStorageInterface::STATUS_DONE) {
                 $count_success++;
                 if (isset($row->langcode)) {
                     if (!isset($sent[$row->entity_type][$row->entity_id][$row->langcode])) {
                         $sent[$row->entity_type][$row->entity_id][$row->langcode] = 1;
                     } else {
                         $sent[$row->entity_type][$row->entity_id][$row->langcode]++;
                     }
                 }
             }
             if ($row_result['error']) {
                 $count_fail++;
             }
         }
         // Update subscriber count.
         if ($this->lock->acquire('simplenews_update_sent_count')) {
             foreach ($sent as $entity_type => $ids) {
                 foreach ($ids as $entity_id => $languages) {
                     \Drupal::entityManager()->getStorage($entity_type)->resetCache(array($entity_id));
                     $entity = entity_load($entity_type, $entity_id);
                     foreach ($languages as $langcode => $count) {
                         $translation = $entity->getTranslation($langcode);
                         $translation->simplenews_issue->sent_count = $translation->simplenews_issue->sent_count + $count;
                     }
                     $entity->save();
                 }
             }
             $this->lock->release('simplenews_update_sent_count');
         }
         // Report sent result and elapsed time. On Windows systems getrusage() is
         // not implemented and hence no elapsed time is available.
         if (function_exists('getrusage')) {
             $this->logger->notice('%success emails sent in %sec seconds, %fail failed sending.', array('%success' => $count_success, '%sec' => round($this->getCurrentExecutionTime(), 1), '%fail' => $count_fail));
         } else {
             $this->logger->notice('%success emails sent, %fail failed.', array('%success' => $count_success, '%fail' => $count_fail));
         }
         $this->state->set('simplenews.last_cron', REQUEST_TIME);
         $this->state->set('simplenews.last_sent', $count_success);
         $this->accountSwitcher->switchBack();
         return $count_success;
     }
 }
 /**
  * Generates a derivative, given a style and image path.
  *
  * After generating an image, transfer it to the requesting agent.
  *
  * @param \Symfony\Component\HttpFoundation\Request $request
  *   The request object.
  * @param string $scheme
  *   The file scheme, defaults to 'private'.
  * @param \Drupal\image\ImageStyleInterface $image_style
  *   The image style to deliver.
  *
  * @return \Symfony\Component\HttpFoundation\BinaryFileResponse|\Symfony\Component\HttpFoundation\Response
  *   The transferred file as response or some error response.
  *
  * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
  *   Thrown when the user does not have access to the file.
  * @throws \Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException
  *   Thrown when the file is still being generated.
  */
 public function deliver(Request $request, $scheme, ImageStyleInterface $image_style)
 {
     $target = $request->query->get('file');
     $image_uri = $scheme . '://' . $target;
     // Check that the style is defined, the scheme is valid, and the image
     // derivative token is valid. Sites which require image derivatives to be
     // generated without a token can set the
     // 'image.settings:allow_insecure_derivatives' configuration to TRUE to
     // bypass the latter check, but this will increase the site's vulnerability
     // to denial-of-service attacks. To prevent this variable from leaving the
     // site vulnerable to the most serious attacks, a token is always required
     // when a derivative of a style is requested.
     // The $target variable for a derivative of a style has
     // styles/<style_name>/... as structure, so we check if the $target variable
     // starts with styles/.
     $valid = !empty($image_style) && file_stream_wrapper_valid_scheme($scheme);
     if (!$this->config('image.settings')->get('allow_insecure_derivatives') || strpos(ltrim($target, '\\/'), 'styles/') === 0) {
         $valid &= $request->query->get(IMAGE_DERIVATIVE_TOKEN) === $image_style->getPathToken($image_uri);
     }
     if (!$valid) {
         throw new AccessDeniedHttpException();
     }
     $derivative_uri = $image_style->buildUri($image_uri);
     $headers = array();
     // If using the private scheme, let other modules provide headers and
     // control access to the file.
     if ($scheme == 'private') {
         if (file_exists($derivative_uri)) {
             return parent::download($request, $scheme);
         } else {
             $headers = $this->moduleHandler()->invokeAll('file_download', array($image_uri));
             if (in_array(-1, $headers) || empty($headers)) {
                 throw new AccessDeniedHttpException();
             }
         }
     }
     // Don't try to generate file if source is missing.
     if (!file_exists($image_uri)) {
         // If the image style converted the extension, it has been added to the
         // original file, resulting in filenames like image.png.jpeg. So to find
         // the actual source image, we remove the extension and check if that
         // image exists.
         $path_info = pathinfo($image_uri);
         $converted_image_uri = $path_info['dirname'] . DIRECTORY_SEPARATOR . $path_info['filename'];
         if (!file_exists($converted_image_uri)) {
             $this->logger->notice('Source image at %source_image_path not found while trying to generate derivative image at %derivative_path.', array('%source_image_path' => $image_uri, '%derivative_path' => $derivative_uri));
             return new Response($this->t('Error generating image, missing source file.'), 404);
         } else {
             // The converted file does exist, use it as the source.
             $image_uri = $converted_image_uri;
         }
     }
     // Don't start generating the image if the derivative already exists or if
     // generation is in progress in another thread.
     $lock_name = 'image_style_deliver:' . $image_style->id() . ':' . Crypt::hashBase64($image_uri);
     if (!file_exists($derivative_uri)) {
         $lock_acquired = $this->lock->acquire($lock_name);
         if (!$lock_acquired) {
             // Tell client to retry again in 3 seconds. Currently no browsers are
             // known to support Retry-After.
             throw new ServiceUnavailableHttpException(3, $this->t('Image generation in progress. Try again shortly.'));
         }
     }
     // Try to generate the image, unless another thread just did it while we
     // were acquiring the lock.
     $success = file_exists($derivative_uri) || $image_style->createDerivative($image_uri, $derivative_uri);
     if (!empty($lock_acquired)) {
         $this->lock->release($lock_name);
     }
     if ($success) {
         $image = $this->imageFactory->get($derivative_uri);
         $uri = $image->getSource();
         $headers += array('Content-Type' => $image->getMimeType(), 'Content-Length' => $image->getFileSize());
         // \Drupal\Core\EventSubscriber\FinishResponseSubscriber::onRespond()
         // sets response as not cacheable if the Cache-Control header is not
         // already modified. We pass in FALSE for non-private schemes for the
         // $public parameter to make sure we don't change the headers.
         return new BinaryFileResponse($uri, 200, $headers, $scheme !== 'private');
     } else {
         $this->logger->notice('Unable to generate the derived image located at %path.', array('%path' => $derivative_uri));
         return new Response($this->t('Error generating image.'), 500);
     }
 }
Example #25
0
 /**
  * Determines if a import is already running.
  *
  * @return bool
  *   TRUE if an import is already running, FALSE if not.
  */
 public function alreadyImporting()
 {
     return !$this->lock->lockMayBeAvailable(static::LOCK_NAME);
 }
 /**
  * Generates a derivative, given a style and image path.
  *
  * After generating an image, transfer it to the requesting agent.
  *
  * @param \Symfony\Component\HttpFoundation\Request $request
  *   The request object.
  * @param string $scheme
  *   The file scheme, defaults to 'private'.
  * @param \Drupal\image\ImageStyleInterface $image_style
  *   The image style to deliver.
  *
  * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
  *   Thrown when the user does not have access to the file.
  * @throws \Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException
  *   Thrown when the file is still being generated.
  *
  * @return \Symfony\Component\HttpFoundation\BinaryFileResponse|\Symfony\Component\HttpFoundation\Response
  *   The transferred file as response or some error response.
  */
 public function deliver(Request $request, $scheme, ImageStyleInterface $image_style)
 {
     $target = $request->query->get('file');
     $image_uri = $scheme . '://' . $target;
     // Check that the style is defined, the scheme is valid, and the image
     // derivative token is valid. Sites which require image derivatives to be
     // generated without a token can set the
     // 'image.settings:allow_insecure_derivatives' configuration to TRUE to
     // bypass the latter check, but this will increase the site's vulnerability
     // to denial-of-service attacks.
     $valid = !empty($image_style) && file_stream_wrapper_valid_scheme($scheme);
     if (!$this->config('image.settings')->get('allow_insecure_derivatives')) {
         $valid &= $request->query->get(IMAGE_DERIVATIVE_TOKEN) === $image_style->getPathToken($image_uri);
     }
     if (!$valid) {
         throw new AccessDeniedHttpException();
     }
     $derivative_uri = $image_style->buildUri($image_uri);
     $headers = array();
     // If using the private scheme, let other modules provide headers and
     // control access to the file.
     if ($scheme == 'private') {
         if (file_exists($derivative_uri)) {
             return parent::download($request, $scheme);
         } else {
             $headers = $this->moduleHandler()->invokeAll('file_download', array($image_uri));
             if (in_array(-1, $headers) || empty($headers)) {
                 throw new AccessDeniedHttpException();
             }
         }
     }
     // Don't try to generate file if source is missing.
     if (!file_exists($image_uri)) {
         watchdog('image', 'Source image at %source_image_path not found while trying to generate derivative image at %derivative_path.', array('%source_image_path' => $image_uri, '%derivative_path' => $derivative_uri));
         return new Response($this->t('Error generating image, missing source file.'), 404);
     }
     // Don't start generating the image if the derivative already exists or if
     // generation is in progress in another thread.
     $lock_name = 'image_style_deliver:' . $image_style->id() . ':' . Crypt::hashBase64($image_uri);
     if (!file_exists($derivative_uri)) {
         $lock_acquired = $this->lock->acquire($lock_name);
         if (!$lock_acquired) {
             // Tell client to retry again in 3 seconds. Currently no browsers are
             // known to support Retry-After.
             throw new ServiceUnavailableHttpException(3, $this->t('Image generation in progress. Try again shortly.'));
         }
     }
     // Try to generate the image, unless another thread just did it while we
     // were acquiring the lock.
     $success = file_exists($derivative_uri) || $image_style->createDerivative($image_uri, $derivative_uri);
     if (!empty($lock_acquired)) {
         $this->lock->release($lock_name);
     }
     if ($success) {
         drupal_page_is_cacheable(FALSE);
         $image = $this->imageFactory->get($derivative_uri);
         $uri = $image->getSource();
         $headers += array('Content-Type' => $image->getMimeType(), 'Content-Length' => $image->getFileSize());
         return new BinaryFileResponse($uri, 200, $headers);
     } else {
         watchdog('image', 'Unable to generate the derived image located at %path.', array('%path' => $derivative_uri));
         return new Response($this->t('Error generating image.'), 500);
     }
 }