Esempio n. 1
0
 /**
  * Finds a Location by the URL and automatically creates the Location if it
  * does not exist and if the respective Location module supports auto
  * generation of Locations.
  **
  * @param $url
  * @param $operation Operation
  * @return bool|Location|null|object
  */
 public function findLocationByUrl($url, $operation, $alias = null)
 {
     $url = ParserUtil::sanitizeUrl($url);
     /*
      * If not a Location, then see if the URL is inside a connected
      * Channel's top-level Locations. To do so, check if one of these
      * criteria apply:
      * - The Location URL matches the beginning of the CTA URL
      * - The Location identifier is included in the CTA URL as well
      *   as the domain
      */
     if (ParserUtil::urlExists($url)) {
         $urlParts = parse_url($url);
         if ($urlParts['scheme'] == 'http') {
             $urlAltScheme = str_replace('http://', 'https://', $url);
         } elseif ($urlParts['scheme'] == 'https') {
             $urlAltScheme = str_replace('https://', 'http://', $url);
         }
         $repository = $this->em->getRepository('CampaignChainCoreBundle:Location');
         $query = $repository->createQueryBuilder('location')->where("(:url LIKE CONCAT('%', location.url, '%')) OR " . "(:url_alt_scheme LIKE CONCAT('%', location.url, '%')) OR " . "(" . "location.identifier IS NOT NULL AND " . ":url LIKE CONCAT('%', location.identifier, '%') AND " . "location.url LIKE :host" . ")")->andWhere('location.parent IS NULL')->setParameter('url', $url)->setParameter('url_alt_scheme', $urlAltScheme)->setParameter('host', $urlParts['host'] . '%')->getQuery();
         /** @var Location $matchingLocation */
         $matchingLocation = $query->getOneOrNullResult();
         if ($matchingLocation) {
             /*
              * Create a new Location based on the tracking alias
              * within the matching Location's Channel.
              *
              * If no tracking alias was provided, we take the
              * default LocationModule to create a new Location.
              */
             if (!$alias) {
                 // Done if the URL is exactly the same in the matching Location.
                 if ($matchingLocation->getUrl() == $url || $matchingLocation->getUrl() == $urlAltScheme) {
                     return $matchingLocation;
                 }
                 // Let's move on to create a new Location with the default module.
                 $locationService = $this->container->get('campaignchain.core.location');
                 /** @var LocationModule $locationModule */
                 $locationModule = $locationService->getLocationModule(self::DEFAULT_LOCATION_BUNDLE_NAME, self::DEFAULT_LOCATION_MODULE_IDENTIFIER);
                 if (!$locationModule) {
                     throw new \Exception('No Location module found for bundle "' . $matchingLocation->getChannel()->getBundle()->getName() . ' and module ' . $matchingLocation->getChannel()->getChannelModule()->getIdentifier() . '"');
                 }
             } else {
                 /*
                  * Get the Location module within the matching Location's
                  * Channel and with the given tracking alias.
                  */
                 /** @var LocationModule $locationModule */
                 $locationModule = $this->getLocationModuleByTrackingAlias($matchingLocation->getChannel()->getChannelModule(), $alias);
                 // Done if the matching Location also matches the alias and URL.
                 if ($matchingLocation->getLocationModule() == $locationModule && ($matchingLocation->getUrl() == $url || $matchingLocation->getUrl() == $urlAltScheme)) {
                     return $matchingLocation;
                 }
                 /*
                  * See if there is already another Location that matches the
                  * aliase's Location module and the URL.
                  */
                 $repository = $this->em->getRepository('CampaignChainCoreBundle:Location');
                 $query = $repository->createQueryBuilder('location')->where('location.locationModule = :locationModule')->andWhere('(location.url = :url OR location.url = :url_alt_scheme')->setParameter('locationModule', $locationModule)->setParameter('url', $url)->setParameter('url_alt_scheme', $urlAltScheme)->getQuery();
                 /** @var Location $location */
                 $location = $query->getOneOrNullResult();
                 // We found an existing Location, we're done.
                 if ($location) {
                     return $location;
                 }
                 if (!$locationModule) {
                     throw new \Exception('Cannot map tracking alias "' . $alias . '" to a "' . 'Location module that belongs to Channel module "' . $matchingLocation->getChannel()->getBundle()->getName() . '/' . $matchingLocation->getChannel()->getChannelModule()->getIdentifier() . '"');
                 }
             }
             /*
              * If the matching Location provides auto-generation of Locations,
              * then let's create a new child Location.
              */
             $ctaServiceName = $locationModule->getServices()['job_cta'];
             if ($ctaServiceName) {
                 // Create the new Location
                 $location = new Location();
                 $location->setUrl($url);
                 $location->setOperation($operation);
                 $location->setChannel($matchingLocation->getChannel());
                 $location->setParent($matchingLocation);
                 // Update the Location module to be the current
                 // one.
                 $location->setLocationModule($locationModule);
                 // Let the module's service process the new
                 // Location.
                 $ctaService = $this->container->get($ctaServiceName);
                 return $ctaService->execute($location);
             } else {
                 throw new \Exception('No CTA Job service defined for Location module ' . 'of bundle "' . $locationModule->getBundle()->getName() . '" ' . 'and module "' . $locationModule->getIdentifier() . '"');
             }
         } else {
             return false;
         }
     }
     throw new \Exception('The URL ' . $url . ' does not exist.');
 }
 public function createActivity(Activity $activity, Form $form)
 {
     // Apply context of Activity.
     if (!$activity->getCampaign()) {
         $activity->setCampaign($this->campaign);
     } elseif (!$this->campaign) {
         $this->campaign = $activity->getCampaign();
     }
     if (!$activity->getChannel()) {
         $activity->setChannel($this->channel);
     } elseif (!$this->channel) {
         $this->channel = $activity->getChannel();
     }
     if (!$activity->getLocation()) {
         $activity->setLocation($this->location);
     } elseif (!$this->location) {
         $this->location = $activity->getLocation();
     }
     // The Module's content.
     $content = null;
     // If Activity module is not set, then do it.
     if (!$activity->getActivityModule()) {
         $moduleService = $this->get('campaignchain.core.module');
         $activity->setActivityModule($moduleService->getModule($this->activityBundleName, $this->activityModuleIdentifier));
     }
     // Does the Activity module relate to at least one Channel module?
     $hasChannel = $activity->getActivityModule()->getChannelModules()->count();
     // The Module's content.
     $content = null;
     $operation = new Operation();
     if ($this->parameters['equals_operation']) {
         if ($hasChannel) {
             if (!$activity->getChannel()) {
                 $activity->setChannel($this->channel);
             } elseif (!$this->channel) {
                 $this->channel = $activity->getChannel();
             }
             if (!$activity->getLocation()) {
                 $activity->setLocation($this->location);
             } elseif (!$this->location) {
                 $this->location = $activity->getLocation();
             }
         }
         // Allow the module to change some data based on its custom input.
         if ($form->has($this->contentModuleFormName)) {
             $this->handler->postFormSubmitNewEvent($activity, $form->get($this->contentModuleFormName)->getData());
             // Allow a module's handler to modify the Activity data.
             $activity = $this->handler->processActivity($activity, $form->get($this->contentModuleFormName)->getData());
         }
         // Get the operation module.
         $operationService = $this->get('campaignchain.core.operation');
         $operation = $operationService->newOperationByActivity($activity, $this->contentBundleName, $this->contentModuleIdentifier);
         // Will the Operation create a Location, i.e. the Operation
         // will be accessible through a URL after publishing?
         if ($operation->getOperationModule()->ownsLocation()) {
             // Get the location module.
             $locationService = $this->get('campaignchain.core.location');
             $locationModule = $locationService->getLocationModule($this->locationBundleName, $this->locationModuleIdentifier);
             $contentLocation = new Location();
             $contentLocation->setLocationModule($locationModule);
             $contentLocation->setParent($activity->getLocation());
             $contentLocation->setName($activity->getName());
             $contentLocation->setStatus(Medium::STATUS_UNPUBLISHED);
             $contentLocation->setOperation($operation);
             $operation->addLocation($contentLocation);
             if ($form->has($this->contentModuleFormName)) {
                 // Allow a module's handler to modify the Operation's Location.
                 $contentLocation = $this->handler->processContentLocation($contentLocation, $form->get($this->contentModuleFormName)->getData());
             }
         }
         if ($form->has($this->contentModuleFormName)) {
             // Process the Operation's content.
             $content = $this->handler->processContent($operation, $form->get($this->contentModuleFormName)->getData());
         }
         if ($content) {
             // Link the Operation details with the operation.
             $content->setOperation($operation);
         }
     } elseif (count($this->parameters['operations']) > 1) {
         $content = $this->handler->processMultiOperationMultiContent($activity, $form, $this->parameters['operations']);
     }
     $em = $this->getDoctrine()->getManager();
     // Make sure that data stays intact by using transactions.
     try {
         $em->getConnection()->beginTransaction();
         $em->persist($activity);
         if (!$content) {
             $content = $this->handler->processSingleContentMultiOperation($activity, $form);
         }
         if ($content) {
             $em->persist($content);
         }
         // We need the activity ID for storing the hooks. Hence we must
         // flush here.
         $em->flush();
         $hookService = $this->get('campaignchain.core.hook');
         /** @var Activity $activity */
         $activity = $hookService->processHooks($this->parameters['bundle_name'], $this->parameters['module_identifier'], $activity, $form, true);
         // Check if the content can be executed.
         if (isset($this->validators['operations']) && $content) {
             $isExecutable = $this->validators['operations'][0]->isExecutableByLocation($content, $activity->getStartDate());
             if (!$isExecutable['status']) {
                 throw new \Exception($isExecutable['message']);
             }
             $activity->setMustValidate($this->validators['operations'][0]->mustValidate($content, $activity->getStartDate()));
         }
         $em->flush();
         $em->getConnection()->commit();
     } catch (\Exception $e) {
         $em->getConnection()->rollback();
         throw $e;
     }
     // The module tries to execute the job immediately.
     $this->handler->postPersistNewEvent($operation, $form, $content);
     return $activity;
 }