/** * @return Location[] */ public function getParsedLocationsFromLinkedIn() { $channel = $this->channelWizard->getChannel(); $profile = $this->channelWizard->get('profile'); $locations = []; $locationName = $profile->displayName; if (!empty($profile->username)) { $locationName .= ' (' . $profile->username . ')'; } // Get the location module for the user stream. $locationModuleUser = $this->locationService->getLocationModule('campaignchain/location-linkedin', 'campaignchain-linkedin-user'); // Create the location instance for the user stream. $locationUser = new Location(); $locationUser->setIdentifier($profile->identifier); $locationUser->setName($locationName); $locationUser->setLocationModule($locationModuleUser); if (!$profile->photoURL || strlen($profile->photoURL) == 0) { $locationUser->setImage($this->assetsHelper->getUrl('/bundles/campaignchainchannellinkedin/ghost_person.png')); } else { $locationUser->setImage($profile->photoURL); } $locationUser->setChannel($channel); $locationModuleUser->addLocation($locationUser); $locations[$profile->identifier] = $locationUser; $tokens = $this->channelWizard->get('tokens'); /** @var Token $userToken */ $userToken = array_values($tokens)[0]; $connection = $this->client->getConnectionByToken($userToken); $companies = $connection->getCompanies(); //there is only a user page if (empty($companies)) { return $locations; } // Get the location module for the page stream. $locationModulePage = $this->locationService->getLocationModule('campaignchain/location-linkedin', 'campaignchain-linkedin-page'); $wizardPages = []; foreach ($companies as $company) { $newToken = new Token(); $newToken->setAccessToken($userToken->getAccessToken()); $newToken->setApplication($userToken->getApplication()); $newToken->setTokenSecret($userToken->getTokenSecret()); $tokens[$company['id']] = $newToken; $this->channelWizard->set('tokens', $tokens); $companyData = $connection->getCompanyProfile($company['id']); $locationPage = new Location(); $locationPage->setChannel($channel); $locationPage->setName($companyData['name']); $locationPage->setIdentifier($companyData['id']); if (isset($companyData['squareLogoUrl'])) { $locationPage->setImage($companyData['squareLogoUrl']); } else { $locationPage->setImage($this->assetsHelper->getUrl('/bundles/campaignchainchannellinkedin/ghost_person.png')); } $locationPage->setLocationModule($locationModulePage); $locationModulePage->addLocation($locationPage); $locations[$companyData['id']] = $locationPage; $wizardPages[$companyData['id']] = $companyData; } $this->channelWizard->set('pagesData', $wizardPages); return $locations; }
/** * 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 addLocationAction(Request $request) { $wizard = $this->get('campaignchain.core.channel.wizard'); $channel = $wizard->getChannel(); $profile = $wizard->get('profile'); $locations = []; $locationName = $profile->displayName; $username = $profile->username; if (!empty($username)) { $locationName .= ' (' . $username . ')'; } // Get the location module for the user stream. $locationService = $this->get('campaignchain.core.location'); $locationModuleUser = $locationService->getLocationModule('campaignchain/location-facebook', 'campaignchain-facebook-user'); // Create the location instance for the user stream. $locationUser = new Location(); $locationUser->setChannel($channel); $locationUser->setName($locationName); $locationUser->setIdentifier($profile->identifier); $locationUser->setImage($profile->photoURL); $locationUser->setLocationModule($locationModuleUser); $locationModuleUser->addLocation($locationUser); $locations[$profile->identifier] = $locationUser; // Connect to Facebook to retrieve pages related to the user. $tokens = $wizard->get('tokens'); $client = $this->container->get('campaignchain.channel.facebook.rest.client'); $connection = $client->connect($tokens[$profile->identifier]->getAccessToken()); if ($connection) { // TODO: Check whether user has manage_pages permission with /me/permissions // check if the user owns Facebook pages $response = $connection->api('/me/accounts'); $pagesData = $response['data']; if (is_array($pagesData) && count($pagesData)) { // TODO: Should we check whether the Facebook page has actually been published (through is_published), because if not, then posting to it won't make sense? Same with can_post and perms from /me/accounts? // Get the location module for the page stream. $locationModulePage = $locationService->getLocationModule('campaignchain/location-facebook', 'campaignchain-facebook-page'); // User owns pages, so let's build the form and ask him whether to create channels for each of them // with the respective channel name foreach ($pagesData as $pageData) { // Save the token in the Wizard. $tokens = $wizard->get('tokens'); $newToken = new Token(); $newToken->setAccessToken($pageData['access_token']); $application = $tokens[$wizard->get('facebook_user_id')]->getApplication(); $newToken->setApplication($application); $tokens[$pageData['id']] = $newToken; $wizard->set('tokens', $tokens); // Get the page picture $pageConnection = $client->connect($pageData['access_token']); $pagePicture = $pageConnection->api('/' . $pageData['id'] . '/picture', 'GET', ['redirect' => false, 'type' => 'large']); $pageData['picture_url'] = $pagePicture['data']['url']; // Create the location instance for the page stream. $locationPage = new Location(); $locationPage->setChannel($channel); $locationPage->setName($pageData['name']); $locationPage->setIdentifier($pageData['id']); $locationPage->setImage($pageData['picture_url']); $locationPage->setLocationModule($locationModulePage); $locationModulePage->addLocation($locationPage); $locations[$pageData['id']] = $locationPage; $wizardPages[$pageData['id']] = $pageData; } $wizard->set('pagesData', $wizardPages); } } $data = []; $form = $this->createFormBuilder($data); foreach ($locations as $identifier => $location) { // Has the page already been added as a location? $repository = $this->getDoctrine()->getRepository('CampaignChainCoreBundle:Location'); $pageExists = $repository->findOneBy(['identifier' => $identifier, 'locationModule' => $location->getLocationModule()]); // Compose the checkbox form field. $form->add($identifier, CheckboxType::class, ['label' => '<img class="campaignchain-location-image-input-prepend" src="' . $location->getImage() . '"> ' . $location->getName(), 'required' => false, 'data' => true, 'mapped' => false, 'disabled' => $pageExists, 'attr' => ['align_with_widget' => true]]); // If a location has already been added before, remove it from this process. // TODO: Also assign existing locations to the new FB user. if ($pageExists) { unset($locations[$identifier]); } } $form = $form->getForm(); $form->handleRequest($request); if ($form->isValid()) { // Find out which locations should be added, i.e. which respective checkbox is active. foreach ($locations as $identifier => $location) { if (!$form->get($identifier)->getData()) { unset($locations[$identifier]); $wizard->removeLocation($identifier); } } // If there's at least one location to be added, then have the user configure it. if (is_array($locations) && count($locations)) { $wizard->setLocations($locations); return $this->redirectToRoute('campaignchain_channel_facebook_location_configure', ['step' => 0]); } else { $this->addFlash('warning', 'No new location has been added.'); return $this->redirectToRoute('campaignchain_core_location'); } } return $this->render('CampaignChainCoreBundle:Base:new.html.twig', ['page_title' => 'Add Facebook Locations', 'form' => $form->createView()]); }