public function execute(SymfonyStyle $io = null) { $currentProfiles = $this->em->getRepository('CampaignChainLocationGoogleAnalyticsBundle:Profile')->findAll(); if (empty($currentProfiles)) { $io->text('There is no Profile entity to update'); return true; } foreach ($currentProfiles as $profile) { if (substr($profile->getProfileId(), 0, 2) != 'UA') { continue; } $profile->setPropertyId($profile->getProfileId()); $gaProfileUrl = $profile->getLocation()->getUrl(); $google_base_url = 'https:\\/\\/www.google.com\\/analytics\\/web\\/#report\\/visitors-overview\\/a' . $profile->getAccountId() . 'w\\d+p'; $pattern = '/' . $google_base_url . '(.*)/'; preg_match($pattern, $gaProfileUrl, $matches); if (!empty($matches) && count($matches) == 2) { $profile->setProfileId($matches[1]); $profile->setIdentifier($profile->getProfileId()); } $this->em->persist($profile); } $this->em->flush(); return true; }
/** * @param SymfonyStyle|null $io */ public function updateCode(SymfonyStyle $io = null) { $io->title('CampaignChain Data Update'); if (empty($this->versions)) { $io->warning('No code updater Service found, maybe you didn\'t enable a bundle?'); return; } $io->comment('The following data versions will be updated'); $migratedVersions = array_map(function (DataUpdateVersion $version) { return $version->getVersion(); }, $this->em->getRepository('CampaignChainUpdateBundle:DataUpdateVersion')->findAll()); $updated = false; foreach ($this->versions as $version => $class) { if (in_array($version, $migratedVersions)) { continue; } $io->section('Version ' . $class->getVersion()); $io->listing($class->getDescription()); $io->text('Begin data update'); $result = $class->execute($io); if ($result) { $dbVersion = new DataUpdateVersion(); $dbVersion->setVersion($version); $this->em->persist($dbVersion); $this->em->flush(); $io->text('Data update finished'); } $updated = true; } if (!$updated) { $io->success('All data is up to date.'); } else { $io->success('Every data version has been updated.'); } }
public function updateBitlyAccessToken($access_token) { $activeSystem = $this->getActiveSystem(); $activeSystem->setBitlyAccessToken($access_token); $this->em->persist($activeSystem); $this->em->flush(); }
/** * @param $id */ public function removeOperation($id) { try { $operation = $this->getNewsItemByOperation($id); $this->em->remove($operation); $this->em->flush(); } catch (\Exception $e) { } }
public function execute($id) { /** @var Campaign $campaign */ $campaign = $this->em->getRepository('CampaignChainCoreBundle:Campaign')->find($id); if (!$campaign) { throw new \Exception('No Campaign found with id: ' . $id); } $now = new \DateTime('now'); // The campaign ended. if ($campaign->getStartDate() < $now && $campaign->getEndDate() < $now) { $campaign->setStatus(Action::STATUS_CLOSED); $this->em->flush(); $this->message = 'The campaign "' . $campaign->getName() . '" ' . 'with ID "' . $campaign->getId() . '" ended, ' . 'thus its status was set to "' . Action::STATUS_CLOSED . '"'; } return self::STATUS_OK; }
/** * @param Operation $operation * @return \Symfony\Component\HttpFoundation\Response * @throws \Exception */ public function readAction(Operation $operation) { $newsItem = $this->contentService->getNewsItemByOperation($operation); $activity = $operation->getActivity(); $locationModuleIdentifier = $activity->getLocation()->getLocationModule()->getIdentifier(); $isCompanyPageShare = 'campaignchain-linkedin-page' == $locationModuleIdentifier; $isLive = true; if (!$newsItem->getLinkedinData()) { $connection = $this->restClient->getConnectionByActivity($activity); /* * Below calls to the Linkedin REST API will throw errors if the * Linkedin App has not been approved by Linkedin as part of their * partner program. */ try { if ($isCompanyPageShare) { $response = $connection->getCompanyUpdate($activity, $newsItem); } else { $response = $connection->getUserUpdate($activity, $newsItem); } if (!is_null($response)) { $newsItem->setLinkedinData($response); $this->em->persist($newsItem); $this->em->flush(); } else { $isLive = false; } } catch (\Exception $e) { $isLive = true; } } return $this->templating->renderResponse('CampaignChainOperationLinkedInBundle::read.html.twig', array('page_title' => $activity->getName(), 'news_item' => $newsItem, 'activity' => $activity, 'is_live' => $isLive, 'is_company' => $isCompanyPageShare)); }
/** * Removes the not assigned tokens. * * @param Token[] $tokens */ public function cleanUpUnassignedTokens(array $tokens) { $this->em->clear(); foreach ($tokens as $token) { $token = $this->em->merge($token); $this->em->remove($token); } $this->em->flush(); }
/** * @param string $operationId * @return string * @throws \Exception */ public function execute($operationId) { /** @var NewsItem $newsItem */ $newsItem = $this->em->getRepository('CampaignChainOperationLinkedInBundle:NewsItem')->findOneByOperation($operationId); if (!$newsItem) { throw new \Exception('No news item found for an operation with ID: ' . $operationId); } //have images? $images = $this->em->getRepository('CampaignChainHookImageBundle:Image')->getImagesForOperation($newsItem->getOperation()); // if the message does not contain a url, we need to skip the content block if (is_null($newsItem->getLinkUrl())) { // LinkedIn accepts an image link only if we also provided a submitted URL. if ($images) { throw new \Exception('To include an image, you must also provide a URL in the text message.'); return self::STATUS_WARNING; } $content = ['comment' => $newsItem->getMessage(), 'visibility' => ['code' => 'anyone']]; } else { /* * process urls and add tracking * important: both the urls in the message and submitted url field must be identical */ $newsItem->setLinkUrl($this->ctaService->processCTAs($newsItem->getLinkUrl(), $newsItem->getOperation())->getContent()); $newsItem->setMessage($this->ctaService->processCTAs($newsItem->getMessage(), $newsItem->getOperation())->getContent()); $content = ['comment' => $newsItem->getMessage(), 'content' => ['title' => $newsItem->getLinkTitle(), 'description' => $newsItem->getLinkDescription(), 'submitted-url' => $newsItem->getLinkUrl()], 'visibility' => ['code' => 'anyone']]; if ($images) { //Linkedin can handle only 1 image $content['content']['submitted-image-url'] = $this->cacheManager->getBrowserPath($images[0]->getPath(), "campaignchain_linkedin_news_item"); } } $activity = $newsItem->getOperation()->getActivity(); $locationModuleIdentifier = $activity->getLocation()->getLocationModule()->getIdentifier(); $isCompanyPageShare = 'campaignchain-linkedin-page' == $locationModuleIdentifier; $connection = $this->client->getConnectionByActivity($activity); if ($isCompanyPageShare) { $response = $connection->shareOnCompanyPage($activity, $content); } else { $response = $connection->shareOnUserPage($content); } $newsItem->setUrl($response['updateUrl']); $newsItem->setUpdateKey($response['updateKey']); // Set Operation to closed. $newsItem->getOperation()->setStatus(Action::STATUS_CLOSED); $location = $newsItem->getOperation()->getLocations()[0]; $location->setIdentifier($response['updateKey']); $location->setUrl($response['updateUrl']); $location->setName($newsItem->getOperation()->getName()); $location->setStatus(Medium::STATUS_ACTIVE); // Schedule data collection for report $this->reportShareNewsItem->schedule($newsItem->getOperation()); $this->em->flush(); $this->message = 'The message "' . $newsItem->getMessage() . '" with the ID "' . $newsItem->getUpdateKey() . '" has been posted on LinkedIn. See it on LinkedIn: <a href="' . $newsItem->getUrl() . '">' . $newsItem->getUrl() . '</a>'; return self::STATUS_OK; }
/** * In case of an exception in scheduler console command * the message should be saved into the scheduler entity * * @param ConsoleExceptionEvent $event */ public function onConsoleException(ConsoleExceptionEvent $event) { /** @var SchedulerCommand $command */ $command = $event->getCommand(); if ($command->getName() != 'campaignchain:scheduler') { return; } // if scheduler is null exception happened in early stage // maybe email should be sent if (!$command->getScheduler()) { return; } /** @var Scheduler $scheduler */ $scheduler = $command->getScheduler(); $scheduler->setMessage($event->getException()->getMessage()); $scheduler->setStatus(Scheduler::STATUS_ERROR); $scheduler->setExecutionEnd(new \DateTime()); $this->em->persist($scheduler); $this->em->flush(); $command->getIo()->error($scheduler->getMessage()); $this->logger->critical($scheduler->getMessage()); }
public function execute(SymfonyStyle $io = null) { $existingLocations = $this->em->getRepository('CampaignChainCoreBundle:Location')->findAll(); if (empty($existingLocations)) { $io->text('There is no Location to update'); return true; } $supportedLocationModuleIdentifiers = ['campaignchain-twitter-user' => $this->twitterUserMetrics, 'campaignchain-facebook-page' => $this->facebookPageMetrics]; foreach ($existingLocations as $existingLocation) { if (!in_array($existingLocation->getLocationModule()->getIdentifier(), array_keys($supportedLocationModuleIdentifiers))) { continue; } //do we have already a scheduler? $existingScheduler = $this->em->getRepository('CampaignChainCoreBundle:SchedulerReportLocation')->findOneBy(['location' => $existingLocation]); if ($existingScheduler) { continue; } $service = $supportedLocationModuleIdentifiers[$existingLocation->getLocationModule()->getIdentifier()]; $service->schedule($existingLocation); } $this->em->flush(); return true; }
public function execute() { $connection = $this->em->getConnection(); $statement = $connection->prepare('SELECT * FROM campaignchain_campaign_repeating_instance'); $statement->execute(); $instances = $statement->fetchAll(); try { $this->em->getConnection()->beginTransaction(); foreach ($instances as $instance) { /** @var Campaign $campaignParent */ $campaignParent = $this->em->getRepository('CampaignChainCoreBundle:Campaign')->find($instance['repeatingCampaign_id']); /** @var Campaign $campaignChild */ $campaignChild = $this->em->getRepository('CampaignChainCoreBundle:Campaign')->find($instance['scheduledCampaign_id']); $campaignParent->addChild($campaignChild); $campaignChild->setParent($campaignParent); $this->em->flush(); } $this->em->getConnection()->commit(); } catch (\Exception $e) { $this->em->getConnection()->rollback(); throw $e; } }
protected function testInternet() { $connected = @fsockopen('www.example.com', 80); if ($connected) { fclose($connected); return true; } else { $errMsg = 'No connection to Internet.'; $this->scheduler->setStatus(Scheduler::STATUS_ERROR); $this->scheduler->setMessage($errMsg); $this->em->flush(); $this->logger->error($errMsg); throw new \Exception($errMsg); } }
/** * @param array $files * @param bool $doDrop */ public function load(array $files, $doDrop = true) { try { $this->em->getConnection()->beginTransaction(); $userProcessor = new UserProcessor(realpath(SystemUtil::getRootDir() . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR), $this->userService, $this->mimeTypeGuesser, $this->extensionGuesser); // Create Alice manager and fixture set $this->fixtureManager->addProcessor($userProcessor); $set = $this->fixtureManager->createFixtureSet(); // Add the fixture files foreach ($files as $file) { $set->addFile($file, 'yaml'); } $set->setDoDrop($doDrop); $set->setDoPersist(true); $set->setSeed(1337 + 42); // TODO Keep Module data intact $bundles = $this->em->getRepository("CampaignChain\\CoreBundle\\Entity\\Bundle")->findAll(); $modules = $this->em->getRepository("CampaignChain\\CoreBundle\\Entity\\Module")->findAll(); if ($this->fixtureManager->load($set)) { // TODO: Restore modules data foreach ($bundles as $bundle) { $this->em->persist($bundle); } foreach ($modules as $module) { $this->em->persist($module); } $this->em->flush(); $this->em->getConnection()->commit(); return true; } return false; } catch (\Exception $e) { $this->em->getConnection()->rollback(); $this->setException($e); return false; } }
/** * Store a module's system parameters. */ private function registerModuleSystemParams() { if (!count($this->systemParams)) { return; } /* * If a system entry already exists, then update it. Otherwise, * create a new one. */ $system = $this->systemService->getActiveSystem(); if (!$system) { $system = new System(); $system->setNavigation([]); $this->em->persist($system); } if (!is_array($system->getNavigation())) { $system->setNavigation([]); } foreach ($this->systemParams as $moduleParams) { foreach ($moduleParams as $key => $params) { switch ($key) { case 'navigation': // Does the app override the modules' navigation? if (isset($this->appComposerJson['extra']) && isset($this->appComposerJson['extra']['campaignchain']) && isset($this->appComposerJson['extra']['campaignchain']['navigation'])) { $system->setNavigation($this->appComposerJson['extra']['campaignchain']['navigation']); } else { // Merge existing navigations with new modules' navigation. $navigation = array_merge_recursive($system->getNavigation(), $params); $system->setNavigation($navigation); } break; } } } $this->em->flush(); }
public function execute($operationId) { /** @var Status $status */ $status = $this->em->getRepository('CampaignChainOperationTwitterBundle:Status')->findOneByOperation($operationId); if (!$status) { throw new \Exception('No status message found for an operation with ID: ' . $operationId); } // Check whether the message can be posted in the Location. $isExecutable = $this->validator->isExecutableByLocation($status, $status->getOperation()->getStartDate()); if ($isExecutable['status'] == false) { throw new JobException($isExecutable['message'], ErrorCode::OPERATION_NOT_EXECUTABLE_IN_LOCATION); } /* * If it is a campaign or parent campaign with an interval (e.g. * repeating campaign), we make sure that every URL will be shortened to * avoid a duplicate status message error. */ $options = array(); if ($status->getOperation()->getActivity()->getCampaign()->getInterval() || $status->getOperation()->getActivity()->getCampaign()->getParent() && $status->getOperation()->getActivity()->getCampaign()->getParent()->getInterval()) { $options['shorten_all_unique'] = true; } /* * Process URLs in message and save the new message text, now including * the replaced URLs with the Tracking ID attached for call to action tracking. */ $status->setMessage($this->cta->processCTAs($status->getMessage(), $status->getOperation(), $options)->getContent()); /** @var Client $connection */ $connection = $this->client->connectByActivity($status->getOperation()->getActivity()); $params['status'] = $status->getMessage(); //have images? $images = $this->em->getRepository('CampaignChainHookImageBundle:Image')->getImagesForOperation($status->getOperation()); $mediaIds = []; if ($images) { foreach ($images as $image) { $streamPath = 'gaufrette://images/' . $image->getPath(); $imageRequest = $connection->post('https://upload.twitter.com/1.1/media/upload.json', null, ['media_data' => base64_encode(file_get_contents($streamPath))]); try { $response = $imageRequest->send()->json(); $mediaIds[] = $response['media_id']; } catch (\Exception $e) { } } if ($mediaIds) { $params['media_ids'] = implode(',', $mediaIds); } } /* * @TODO * * If there are URLs in the tweet, they have been shortened. Thus, we'll * pass the expanded URLs as entities in the API call, so that Twitter * can display them when hovering the mouse on a short URL. */ $request = $connection->post('statuses/update.json', null, $params); $response = $request->send()->json(); // TODO // If status code is 403, this means that the same tweet with identical content already exists // This should be checked upon creation of tweet (same with FB!) // Set URL to published status message on Facebook $statusURL = 'https://twitter.com/' . $response['user']['screen_name'] . '/status/' . $response['id_str']; $status->setUrl($statusURL); $status->setIdStr($response['id_str']); // Set Operation to closed. $status->getOperation()->setStatus(Action::STATUS_CLOSED); $location = $status->getOperation()->getLocations()[0]; $location->setIdentifier($response['id_str']); $location->setUrl($statusURL); $location->setName($status->getOperation()->getName()); $location->setStatus(Medium::STATUS_ACTIVE); // Schedule data collection for report $this->report->schedule($status->getOperation()); $this->em->flush(); $this->message = 'The message "' . $response['text'] . '" with the ID "' . $response['id_str'] . '" has been posted on Twitter. See it on Twitter: <a href="' . $statusURL . '">' . $statusURL . '</a>'; return self::STATUS_OK; // } // else { // // Handle errors, if authentication did not work. // // 1) Check if App is installed. // // 2) check if access token is valid and retrieve new access token if necessary. // // Log error, send email, prompt user, ask to check App Key and Secret or to authenticate again // } }
/** * @param string $operationId * @return string * @throws \Exception */ public function execute($operationId) { /** @var StatusBase $status */ $status = $this->em->getRepository('CampaignChainOperationFacebookBundle:StatusBase')->findOneByOperation($operationId); if (!$status) { throw new \Exception('No Facebook status found for an operation with ID: ' . $operationId); } // Check whether the message can be posted in the Location. $isExecutable = $this->validator->isExecutableByLocation($status, $status->getOperation()->getStartDate()); if ($isExecutable['status'] == false) { throw new JobException($isExecutable['message'], ErrorCode::OPERATION_NOT_EXECUTABLE_IN_LOCATION); } /* * If it is a campaign or parent campaign with an interval (e.g. * repeating campaign), we make sure that every URL will be shortened to * avoid a duplicate status message error. */ $options = array(); if ($status->getOperation()->getActivity()->getCampaign()->getInterval() || $status->getOperation()->getActivity()->getCampaign()->getParent() && $status->getOperation()->getActivity()->getCampaign()->getParent()->getInterval()) { $options['shorten_all_unique'] = true; } /* * Process URLs in message and save the new message text, now including * the replaced URLs with the Tracking ID attached for call to action * tracking. */ $status->setMessage($this->cta->processCTAs($status->getMessage(), $status->getOperation(), $options)->getContent()); /** @var \Facebook $connection */ $connection = $this->client->connectByActivity($status->getOperation()->getActivity()); if (!$connection) { throw new JobException('Cannot connect to Facebook REST API for Location "' . $status->getOperation()->getActivity()->getLocation()->getUrl() . '"', ErrorCode::CONNECTION_TO_REST_API_FAILED); } $paramsMsg = array(); /* * If an image was attached, we'll first upload the photo to Facebook * and then use the Facebook object ID of the picture in the message. */ $images = $this->em->getRepository('CampaignChainHookImageBundle:Image')->getImagesForOperation($status->getOperation()); if ($images) { $paramsImg = array(); $paramsImg['caption'] = $status->getMessage(); // Avoid that feed shows "... added a new photo" entry automtically. $paramsImg['no_story'] = 1; //Facebook handles only 1 image $paramsImg['url'] = $this->cacheManager->getBrowserPath($images[0]->getPath(), "campaignchain_facebook_photo"); try { $responseImg = $connection->api('/' . $status->getFacebookLocation()->getIdentifier() . '/photos', 'POST', $paramsImg); $paramsMsg['object_attachment'] = $responseImg['id']; } catch (\Exception $e) { throw new ExternalApiException($e->getMessage() . '. Parameters of REST API call: ' . json_encode($paramsImg), $e->getCode(), $e); } } if ($status instanceof UserStatus) { $privacy = array('value' => $status->getPrivacy()); $paramsMsg['privacy'] = json_encode($privacy); } $paramsMsg['message'] = $status->getMessage(); try { $responseMsg = $connection->api('/' . $status->getFacebookLocation()->getIdentifier() . '/feed', 'POST', $paramsMsg); } catch (\Exception $e) { throw new ExternalApiException($e->getMessage() . '. Parameters of REST API call: ' . json_encode($paramsMsg), $e->getCode(), $e); } $connection->destroySession(); // Set URL to published status message on Facebook $statusURL = 'https://www.facebook.com/' . str_replace('_', '/posts/', $responseMsg['id']); $status->setUrl($statusURL); $status->setPostId($responseMsg['id']); // Set Operation to closed. $status->getOperation()->setStatus(Action::STATUS_CLOSED); $location = $status->getOperation()->getLocations()[0]; $location->setIdentifier($responseMsg['id']); $location->setUrl($statusURL); $location->setName($status->getOperation()->getName()); $location->setStatus(Medium::STATUS_ACTIVE); // Schedule data collection for report $this->report->schedule($status->getOperation()); $this->em->flush(); $this->message = 'The message "' . $paramsMsg['message'] . '" with the ID "' . $responseMsg['id'] . '" has been posted on Facebook'; if ($status instanceof UserStatus) { $this->message .= ' with privacy setting "' . $privacy['value'] . '"'; } $this->message .= '. See it on Facebook: <a href="' . $statusURL . '">' . $statusURL . '</a>'; return self::STATUS_OK; }