src/Service/D4SeoService.php line 302

Open in your IDE?
  1. <?php
  2. namespace App\Service;
  3. use Symfony\Contracts\HttpClient\HttpClientInterface;
  4. use Symfony\Component\HttpClient\HttpClient;
  5. use Doctrine\ORM\EntityManagerInterface;
  6. use Doctrine\DBAL\Driver\Connection;
  7. use App\Service\CommonService;
  8. use Psr\Log\LoggerInterface;
  9. use App\Controller\SEOTasksController;
  10. use App\Repository\System\UserRepository;
  11. use App\Repository\Fp\FPTasksRepository;
  12. use App\Repository\Fp\FPRankingsRepository;
  13. use App\Repository\Fp\FPSerpsRepository;
  14. use App\Repository\Seo\LocationsRepository;
  15. use App\Repository\Seo\SEOTasksRepository;
  16. use App\Entity\Fp\FPReports;
  17. use App\Entity\Fp\FPTests;
  18. use App\Entity\Fp\FPTasks;
  19. use App\Entity\Fp\FPRankings;
  20. use App\Entity\Fp\FPSerps;
  21. use App\Entity\Seo\SEOTasks;
  22. use App\Entity\Seo\GPlaces;
  23. use App\Entity\Seo\IntelQueue;
  24. class D4SeoService
  25. {
  26.     protected $client;
  27.     public $logger;
  28.     public $seoinfoLogger;
  29.     private $userRepository;
  30.     
  31.     public function __construct(CommonService $commonServiceHttpClientInterface $clientLoggerInterface $logger,  LoggerInterface $seoinfoLogger,
  32.             FPTasksRepository $fpTasksRepository,  FPRankingsRepository $fpRankingsRepositorySEOTasksRepository $seoTasksRepository
  33.             FPSerpsRepository $fpSerpsRepositoryLocationsRepository $locationsRepositoryUserRepository $userRepositoryEntityManagerInterface $em
  34.     {
  35.         $this->settings = (object) $commonService->getSettings('api');
  36.         $this->client $client;
  37.         $this->userRepository $userRepository;
  38.         $this->fpTasksRepository $fpTasksRepository;
  39.         $this->fpRankingsRepository $fpRankingsRepository;
  40.         $this->fpSerpsRepository $fpSerpsRepository;
  41.         $this->locationsRepository $locationsRepository;
  42.         $this->seoTasksRepository $seoTasksRepository;
  43.         $this->seologger $seoinfoLogger;
  44.         // FOR ERROR and CRITICAL 
  45.         // $this->seologger->error("COME INFORMATION HERE - ".__FUNCTION__." ".__LINE__);
  46.         // FOR FLOW INFORMAITON
  47.         // $this->seologger->info("WHAT WERE DOING - ".__FUNCTION__."->businessDataStoreG"); 
  48.         $this->logger $logger;
  49.         $this->entityManager $em;
  50.     }
  51.     private function connect($method$url$postdata null) {
  52.         $conn $this->client->request($method"https://api.dataforseo.com/v3".$url, [
  53.             'auth_basic' => [$this->settings->MAGICEMAIL$this->settings->MAGICSTRING],
  54.             'headers' => [
  55.                 'User-Agent' => 'Surfside Web SEO',
  56.                 'Accept' => 'application/json',
  57.             ], 
  58.             'json' => $postdata,
  59.         ]);
  60.         return $conn;
  61.     }
  62.     public function getFetchTask($path) {
  63.         $conn $this->connect('GET'$path);
  64.         $content $conn->getContent();
  65.         return $content;
  66.     }
  67.     /**
  68.      * Gets our user info for testing
  69.      */
  70.     public function getUserInfo() {
  71.         $conn $this->connect('GET''/appendix/user_data');
  72.         $content $conn->getContent();
  73.         return $content;
  74.     }
  75.     /**
  76.      * Sets the task to collect GMB Maps information. AKA the list of maps results by topic.
  77.      */
  78.     public function businessMaps($postinfo) {
  79.         /*
  80.         // OUT /serp/google/maps/task_post 
  81.         // IN  /d4return/purpose/serp/google/maps/{task_id}
  82.         */
  83.         $em $this->entityManager;
  84.         $task $em->getRepository(SEOTasks::class)->findOneBy(array('keyword' => $postinfo->keyword'status' => 'sent'));
  85.         if (!$task) {
  86.             $task_id $this->getUUID();
  87.             $postbackurl "https://seopanel.surfsideweb.com/d4return/serp/google/maps/".$task_id."/";
  88.             if(!empty($postinfo->language_code) && !empty($postinfo->location_code) && !empty($postinfo->keyword)) {
  89.                 $postdata[] = array(
  90.                     "language_code" => $postinfo->language_code
  91.                     "location_code" => $postinfo->location_code
  92.                     "keyword" => mb_convert_encoding($postinfo->keyword"UTF-8"),
  93.                     "priority" => $postinfo->priority,
  94.                     "tag" => $task_id,
  95.                     "postback_data" => 'advanced',
  96.                     "postback_url" => $postbackurl ); 
  97.                 $conn $this->connect('POST''/serp/google/maps/task_post'$postdata);
  98.                 $content $conn->getContent();
  99.                 $postinfo->task_id $task_id;
  100.                 $taskback = (object) json_decode($content);
  101.                
  102.                 $taskback $taskback->tasks[0];
  103.                 $postinfo->d4id $taskback->id;
  104.                 $postinfo->api $taskback->data->api;
  105.                 $postinfo->function $taskback->data->function;
  106.                 $postinfo->se $taskback->data->se;
  107.                 $postinfo->se_type 'maps';
  108.                 $postinfo->device $taskback->data->device;
  109.                 $postinfo->os $taskback->data->os;
  110.                 $postinfo->created date('Y-m-d H:i:s');
  111.                 if ($taskback->status_message == 'Task Created.') {
  112.                     $postinfo->status 'sent';
  113.                     $this->storeTask($postinfo);
  114.                 } else {
  115.                     $postinfo->status 'failed to send';
  116.                 }
  117.             }
  118.         } else {
  119.             $postinfo->status 'task already sent';
  120.         }
  121.         return $postinfo;
  122.     }
  123.     /**
  124.      * Sets the task to collect GMB panel information. AKA the main GMB listing info.
  125.      */
  126.     public function businessData($postinfo$force FALSE) {
  127.         /*
  128.         // OUT /business_data/google/my_business_info/task_post 
  129.         // IN  /d4return/purpose/business_data/my_business_info/{task_id}/
  130.         */
  131.         $em $this->entityManager;
  132.         $keywordsafe =  mb_convert_encoding($postinfo->keyword"UTF-8");
  133.         if($force != TRUE) {
  134.             $thirty date('Y-m-d G:i:s'strtotime('-30 days'));
  135.             $task $em->getRepository(SEOTasks::class)->chkRecent($thirty$postinfo->purpose$postinfo->se$postinfo->location_code'gmbusiness'$keywordsafe'desktop');
  136.         }
  137.         if (!$task) {
  138.             $task_id $this->getUUID();
  139.             $purpose $postinfo->purpose;
  140.             $postbackurl "https://seopanel.surfsideweb.com/d4return/".$purpose."/business_data/google/my_business_info/".$task_id."/";
  141.             if(!empty($postinfo->language_code) && !empty($postinfo->location_code) && !empty($postinfo->keyword)) {
  142.                 $postdata[] = array(
  143.                     "language_code" => $postinfo->language_code
  144.                     "location_code" => $postinfo->location_code
  145.                     "keyword" => $keywordsafe,
  146.                     "priority" => $postinfo->priority,
  147.                     "tag" => $task_id,
  148.                     "postback_url" => $postbackurl ); 
  149.                 $postinfo->created date('Y-m-d H:i:s');
  150.                 
  151.                 $conn $this->connect('POST''/business_data/google/my_business_info/task_post'$postdata);
  152.                 $content $conn->getContent();
  153.                 $postinfo->task_id $task_id;
  154.                 $taskback = (object) json_decode($content);
  155.                 $taskback $taskback->tasks[0];
  156.                 $postinfo->d4id $taskback->id;
  157.                 $postinfo->api $taskback->data->api;
  158.                 $postinfo->function $taskback->data->function;
  159.                 $postinfo->se $taskback->data->se;
  160.                 $postinfo->se_type 'gmbusiness';
  161.                 $postinfo->device $taskback->data->device;
  162.                 $postinfo->os $taskback->data->os;
  163.                 if ($taskback->status_message == 'Task Created.') {
  164.                     $postinfo->status 'sent';
  165.                     $this->storeTask($postinfo);
  166.                 } else {
  167.                     $postinfo->status 'Too soon or failed to send';
  168.                 }
  169.             }
  170.         } else {
  171.             $postinfo->status 'Task already sent';
  172.         }
  173.         return $postinfo;
  174.     }
  175.     /**
  176.      * Sets the task to collect GMB reviews segment plus other gplaces info.
  177.      */
  178.     public function businessReviews($postinfo$force FALSE) {
  179.         /*
  180.         // OUT /business_data/google/reviews/task_post 
  181.         // IN  /d4return/purpose/business_data/reviews/{task_id}/
  182.         */
  183.         $em $this->entityManager;
  184.         if($force != TRUE) {
  185.         $thirty date('Y-m-d H:i:s'strtotime('-30 days'));
  186.         $task $em->getRepository(SEOTasks::class)->chkRecent($thirty$postinfo->purpose$postinfo->se$postinfo->location_code'gmbtest'$postinfo->keyword$postinfo->device);
  187.         }
  188.         if (!$task) {
  189.             $task_id $this->getUUID();
  190.             $postbackurl "https://seopanel.surfsideweb.com/d4return/".$postinfo->purpose."/business_data/google/reviews/".$task_id."/";
  191.             if(!empty($postinfo->language_code) && !empty($postinfo->location_code) && !empty($postinfo->keyword)) {
  192.                 //echo $postinfo->keyword.' - '.$postinfo->se.' - '.$postinfo->se_type.' - '.$postinfo->type.' - '.$postinfo->device.' - '.$postinfo->location_code.' - No Task<br>';
  193.                 $postdata[] = array(
  194.                     "language_code" => $postinfo->language_code
  195.                     "location_code" => $postinfo->location_code
  196.                     "keyword" => $postinfo->keyword,
  197.                     "priority" => $postinfo->priority,
  198.                     "tag" => $task_id,
  199.                     "depth" => '20'
  200.                     "sort_by" => 'newest',
  201.                     "postback_url" => $postbackurl ); 
  202.                     //dd($postdata);
  203.                 $postinfo->created date('Y-m-d H:i:s');
  204.                 $conn $this->connect('POST''/business_data/google/reviews/task_post'$postdata);
  205.                 $content $conn->getContent();
  206.                 $postinfo->task_id $task_id;
  207.                 $taskback = (object) json_decode($content);
  208.                 $taskback $taskback->tasks[0];
  209.                 $postinfo->result json_encode($taskback);
  210.                 $postinfo->d4id $taskback->id;
  211.                 $postinfo->api $taskback->data->api;
  212.                 $postinfo->function $taskback->data->function;
  213.                 $postinfo->se $taskback->data->se;
  214.                 $postinfo->device $taskback->data->device;
  215.                 $postinfo->os $taskback->data->os;
  216.                 $postinfo->se_type 'gmbtest';
  217.                 if ($taskback->status_message == 'Task Created.') {
  218.                     $postinfo->status 'sent';
  219.                     $this->storeTask($postinfo);
  220.                     if(isset($postinfo->purpose) && 'footprint' == $postinfo->purpose) {
  221.                         $postinfo->se_type 'reviews';
  222.                         $this->storeFpTask($postinfo);
  223.                     }
  224.                 } else {
  225.                     $postinfo->status 'Too soon or failed to send';
  226.                 }
  227.             }
  228.         } else {
  229.             //echo $postinfo->keyword.' - '.$postinfo->se.' - '.$postinfo->se_type.' - '.$postinfo->device.' - '.$postinfo->location_code.' - <b>Task Exists</b><br>';
  230.             $postinfo->status 'Task already sent';
  231.         }
  232.         return $postinfo;
  233.     }
  234.     public function createFpReportTests($userinfo$prevreport null) {
  235.         //Lets build the current keywords set
  236.         $keywords $this->getUserKeywords($userinfo); //  WHY IS THIS HERE
  237.         $em $this->entityManager;
  238.         $now date('Y-m-d G:i:s');
  239.         // Next lets create the report itself giving it a unique UUID
  240.         $report $em->getRepository(FPReports::class)->findOneBy(array('lead_id' => $userinfo['id'], 'year' => date('Y'), 'month' => date('m'), 'status' => 'pending'));
  241.         if(!$report) {
  242.             $report = new FPReports();
  243.             $report->setLeadID($userinfo['id']);
  244.             $reportid $this->getUUID();
  245.             $report->setUuid($reportid);
  246.             $report->setYear(date('Y'));
  247.             $report->setMonth(date('m'));
  248.             $report->setStatus('pending');
  249.             $report->setEmailed('unsent');
  250.             $report->setCreated(\DateTime::createFromFormat('Y-m-d H:i:s'$now));
  251.             $em->persist($report);
  252.             $em->flush();
  253.             if ($userinfo['local'] == 'yes') {
  254.                 $testtypes = array('kwranking''kwvolumes''mapsranking''pagespeed''backlinks''analytics''legaldocs''socialcheck',  
  255.                     'gscertified''gmbtest'); 
  256.             } else {
  257.                 $testtypes = array('kwranking''kwvolumes''pagespeed''backlinks''analytics''legaldocs''socialcheck''gscertified'); 
  258.             }
  259.             foreach($testtypes as $testtype) {
  260.                 $test $em->getRepository(FPTests::class)->findOneBy(array('type' => $testtype'lead_id' => $userinfo['id'], 'status' => 'pending' ));
  261.                 if(!$test) {
  262.                     $test = new FPTests();
  263.                     $test->setType($testtype);
  264.                     $test->setTestGroup($this->getUUID());
  265.                     $test->setLeadId($userinfo['id']);
  266.                     $test->setReportId($reportid);
  267.                     $test->setYear(date('Y'));
  268.                     $test->setMonth(date('m'));
  269.                     $test->setStatus('pending');
  270.                     $test->setResult(null);
  271.                     $test->setCreated(\DateTime::createFromFormat('Y-m-d H:i:s'$now));
  272.                     $em->persist($test);
  273.                     $em->flush();
  274.                 } 
  275.             }
  276.         } else {
  277.             $reportid $report->getUuid();
  278.         }
  279.         return $reportid;
  280.     }
  281.     public function retrieveOrphanTasks() {
  282.         // Reclaim lost tasts still in SENT status
  283.         $em $this->entityManager;
  284.         $tasks $em->getRepository(SEOTasks::class)->chkOrphanTasks('sent');
  285.         //dd($tasks);
  286.         if($tasks) {
  287.             foreach($tasks as $task) {
  288.                 if($task->getSeType() == 'backlinkchk') {
  289.                     $function 'backlinkchk';
  290.                 } else {
  291.                     $function $task->getFunction();
  292.                 }
  293.                 $path 'https://seopanel.surfsideweb.com/d4return/'.$task->getPurpose().'/'.$task->getApi().'/'.$task->getSe().'/'.$function.'/'.$task->getTaskId().'/';
  294.                 //echo '<a href="'.$path.'">'.$path.'</a><br>';
  295.                 $result = @file_get_contents($path);
  296.                 //dd($result,$task);
  297.                 if(!isset($result) || $result != 'Success') {
  298.                     $task->setStatus('not found');
  299.                     $em->persist($task);
  300.                     $em->flush();
  301.                     if('footprint' == $task->getPurpose() && $function != 'backlinkchk') {
  302.                         $fptask $em->getRepository(FPTasks::class)->findOneBy(array('uuid' => $task->getTaskId()));
  303.                         if($fptask) {
  304.                             $fptask->setStatus('not found');
  305.                             $em->persist($fptask);
  306.                             $em->flush();
  307.                         }
  308.                     }
  309.                 }
  310.                 sleep(1);
  311.             }
  312.             return $tasks;
  313.         } 
  314.     }
  315.     /**
  316.      * Sets the task to collect keyword volume information. 
  317.      */
  318.     public function keywordVolumes($postinfo$force FALSE) {
  319.         /*
  320.         // OUT /keywords_data/google/search_volume/task_post 
  321.         // IN  /d4return/purpose/keywords_data/google/search_volume/{task_id}/
  322.         */
  323.         $em $this->entityManager;
  324.         $keywords json_encode($postinfo->keywords);
  325.         if($force != TRUE) {
  326.         $thirty date('Y-m-d G:i:s'strtotime('-30 days'));
  327.         $task $em->getRepository(SEOTasks::class)->chkRecent($thirty$postinfo->purpose$postinfo->se$postinfo->location_code$postinfo->se_type$keywords$postinfo->device);
  328.         }
  329.         if (!$task) {
  330.             $task_id $this->getUUID();
  331.             $postbackurl "https://seopanel.surfsideweb.com/d4return/".$postinfo->purpose."/keywords_data/google/search_volume/".$task_id."/";
  332.             if(!empty($postinfo->language_code) && !empty($postinfo->location_code) && !empty($postinfo->keywords)) {
  333.                 $postdata[] = array(
  334.                     "language_code" => $postinfo->language_code
  335.                     "location_code" => $postinfo->location_code
  336.                     "keywords" => $postinfo->keywords,
  337.                     "priority" => $postinfo->priority,
  338.                     "search_partners" => TRUE,
  339.                     "tag" => $task_id,
  340.                     "postback_url" => $postbackurl ); 
  341.                 $postinfo->created date('Y-m-d H:i:s');
  342.                 $conn $this->connect('POST''/keywords_data/google/search_volume/task_post'$postdata);
  343.                 $content $conn->getContent();
  344.                 $postinfo->task_id $task_id;
  345.                 $taskback = (object) json_decode($content);
  346.                 $taskback $taskback->tasks[0];
  347.                 $postinfo->result json_encode($taskback);
  348.                 $postinfo->d4id $taskback->id;
  349.                 $postinfo->api $taskback->data->api;
  350.                 $postinfo->function $postinfo->se_type;
  351.                 $postinfo->se $taskback->data->se;
  352.                 $postinfo->type $postinfo->se_type;
  353.                 $postinfo->os 'windows';
  354.                 $postinfo->keyword $keywords;
  355.                 if ($taskback->status_message == 'Task Created.') {
  356.                     $postinfo->status 'sent';
  357.                     $this->storeTask($postinfo);
  358.                     if(isset($postinfo->purpose) && 'footprint' == $postinfo->purpose) {
  359.                         $this->storeFpTask($postinfo);
  360.                     }
  361.                 } else {
  362.                     $postinfo->status 'Failed to send';
  363.                 }
  364.             }
  365.         } else {
  366.             //echo $keywords.' - '.$postinfo->se.' - '.$postinfo->se_type.' - '.$postinfo->device.' - '.$postinfo->location_code.' - <b>Task Exists</b><br>';
  367.             $postinfo->status 'Task already sent';
  368.         }
  369.         return $postinfo;
  370.     }
  371.     public function keywordSerps($postinfo$postbackdata 'regular'$force FALSE) {
  372.         /*
  373.         // OUT /serp/google/organic/task_post 
  374.         // IN  /d4return/purpose/serp/google/organic/{task_id}/
  375.         */
  376.         $em $this->entityManager;
  377.         $task FALSE;
  378.         if($force != TRUE) {
  379.         $thirty date('Y-m-d G:i:s'strtotime('-30 days'));
  380.         $task $em->getRepository(SEOTasks::class)->chkRecent($thirty$postinfo->purpose$postinfo->se$postinfo->location_code$postinfo->se_type$postinfo->keyword$postinfo->device);
  381.         } 
  382.         if (!$task) {
  383.             //echo $postinfo->keyword.' - '.$postinfo->se.' - '.$postinfo->device.' - '.$postinfo->location_code.' - No Task<br>';
  384.             $task_id $this->getUUID();
  385.             if($postinfo->type == 'backlinkchk') {
  386.                 $postinfo->se_type 'backlinkchk';
  387.             }
  388.             $postbackurl "https://seopanel.surfsideweb.com/d4return/".$postinfo->purpose."/serp/".$postinfo->se."/".$postinfo->se_type."/".$task_id."/";
  389.             if(!empty($postinfo->language_code) && !empty($postinfo->location_code) && !empty($postinfo->keyword)) {
  390.                 $postdata[] = array(
  391.                     "language_code" => $postinfo->language_code
  392.                     "location_code" => $postinfo->location_code
  393.                     "keyword" => $postinfo->keyword,
  394.                     "device" => $postinfo->device,
  395.                     "priority" => $postinfo->priority,
  396.                     "tag" => $task_id,
  397.                     "postback_url" => $postbackurl,
  398.                     "postback_data" => $postbackdata ); 
  399.                 $postinfo->created date('Y-m-d H:i:s');
  400.                 $conn $this->connect('POST''/serp/'.$postinfo->se.'/organic/task_post'$postdata);
  401.                 $content $conn->getContent();
  402.                 $postinfo->task_id $task_id;
  403.                 $taskback = (object) json_decode($content);
  404.                 $taskback $taskback->tasks[0];
  405.                 $postinfo->result json_encode($taskback);
  406.                 if($taskback->status_code == 20100) {
  407.                     $postinfo->d4id $taskback->id;
  408.                     $postinfo->api $taskback->data->api;
  409.                     $postinfo->function 'organic';
  410.                     $postinfo->se $taskback->data->se;
  411.                     $postinfo->device $taskback->data->device;
  412.                     $postinfo->os $taskback->data->os;
  413.                 }
  414.                 if ($taskback->status_message == 'Task Created.') {
  415.                     $postinfo->status 'sent';
  416.                     $this->storeTask($postinfo);
  417.                     if(isset($postinfo->purpose) && 'footprint' == $postinfo->purpose) {
  418.                         $this->storeFpTask($postinfo);
  419.                     }
  420.                 } else {
  421.                     $postinfo->status 'Failed to send';
  422.                 }
  423.             }
  424.         } else {
  425.             $postinfo->status 'Task already sent';
  426.         }
  427.         return $postinfo;
  428.     }
  429.     public function keywordMapPacks($postinfo$force FALSE) {
  430.         /*
  431.         // OUT /serp/google/maps/task_post 
  432.         // IN  /d4return/purpose/serp/google/maps/{task_id}/
  433.         */
  434.         $em $this->entityManager;
  435.         if($postinfo->se == 'google') {
  436.             $postbackdata 'advanced';
  437.             $device $postinfo->device;
  438.         } else {
  439.             $postbackdata 'regular';
  440.             $device 'none';
  441.         }
  442.         if($force != TRUE) {
  443.         $thirty date('Y-m-d G:i:s'strtotime('-30 days'));
  444.         $task $em->getRepository(SEOTasks::class)->chkRecent($thirty$postinfo->purpose$postinfo->se$postinfo->location_code$postinfo->se_type$postinfo->keyword$device);
  445.         }
  446.         if (!$task) {
  447.             //echo $postinfo->keyword.' - '.$postinfo->se.' - '.$postinfo->se_type.' - '.$device.' - '.$postinfo->location_code.' - No Task<br>';
  448.             $task_id $this->getUUID();
  449.             $postbackurl "https://seopanel.surfsideweb.com/d4return/".$postinfo->purpose."/serp/".$postinfo->se."/".$postinfo->se_type."/".$task_id."/";
  450.             if(!empty($postinfo->language_code) && !empty($postinfo->location_code) && !empty($postinfo->keyword)) {
  451.                 if($postinfo->se == 'google') { 
  452.                     $postdata[] = array(
  453.                         "language_code" => $postinfo->language_code
  454.                         "location_code" => $postinfo->location_code
  455.                         "keyword" => $postinfo->keyword,
  456.                         "device" => $device,
  457.                         "priority" => $postinfo->priority,
  458.                         "tag" => $task_id,
  459.                         "postback_url" => $postbackurl,
  460.                         "postback_data" => $postbackdata ); 
  461.                 } else {
  462.                     $postdata[] = array(
  463.                         "language_code" => $postinfo->language_code
  464.                         "location_code" => $postinfo->location_code
  465.                         "keyword" => $postinfo->keyword,
  466.                         "priority" => $postinfo->priority,
  467.                         "tag" => $task_id,
  468.                         "postback_url" => $postbackurl,
  469.                         "postback_data" => $postbackdata ); 
  470.                 }
  471.                 $postinfo->created date('Y-m-d H:i:s');
  472.                 
  473.                 $conn $this->connect('POST''/serp/'.$postinfo->se.'/'.$postinfo->se_type.'/task_post'$postdata);
  474.                 $content $conn->getContent();
  475.                 $postinfo->task_id $task_id;
  476.                 $taskback = (object) json_decode($content);
  477.                 $taskback $taskback->tasks[0];
  478.                 $postinfo->result json_encode($taskback);
  479.                 if($taskback->status_code == 20100) {
  480.                     $postinfo->d4id $taskback->id;
  481.                     $postinfo->api $taskback->data->api;
  482.                     $postinfo->function $taskback->data->se_type;
  483.                     $postinfo->se $taskback->data->se;
  484.                     $postinfo->se_type $taskback->data->se_type;
  485.                     if($postinfo->se == 'google') {
  486.                         $postinfo->device $taskback->data->device;
  487.                     } else {
  488.                         $postinfo->device 'none';
  489.                     }
  490.                     $postinfo->os $taskback->data->os;
  491.                 }
  492.                 if ($taskback->status_message == 'Task Created.') {
  493.                     $postinfo->status 'sent';
  494.                     $this->storeTask($postinfo);
  495.                     if(isset($postinfo->purpose) && 'footprint' == $postinfo->purpose) {
  496.                         $this->storeFpTask($postinfo);
  497.                     }
  498.                 } else {
  499.                     $postinfo->status 'Failed to send';
  500.                 }
  501.             }
  502.         } else {
  503.             echo $postinfo->keyword.' - '.$postinfo->se.' - '.$postinfo->se_type.' - '.$postinfo->device.' - '.$postinfo->location_code.' - <b>Task Exists</b><br>';
  504.             $postinfo->status 'Task Exists';
  505.         }
  506.         return $postinfo;
  507.     }
  508.     public function storeTask($taskinfo) {
  509.         $em $this->entityManager;
  510.         $task $em->getRepository(SEOTasks::class)->findOneBy(array('task_id' => $taskinfo->task_id));
  511.         if(!$task) {
  512.             $task = new SEOTasks();
  513.             $task->setPurpose($taskinfo->purpose);
  514.             $task->setTaskId($taskinfo->task_id);
  515.             $task->setD4id($taskinfo->d4id);
  516.             $task->setApi($taskinfo->api);
  517.             $task->setFunction($taskinfo->function);
  518.             $task->setSe($taskinfo->se);
  519.             $task->setLanguageCode($taskinfo->language_code);
  520.             $task->setLocationCode($taskinfo->location_code);
  521.             $task->setKeyword($taskinfo->keyword);
  522.             $task->setSeType($taskinfo->se_type);
  523.             $task->setDevice($taskinfo->device);
  524.             $task->setOs($taskinfo->os);
  525.             $task->setStatus($taskinfo->status);
  526.             $task->setCreated(\DateTime::createFromFormat('Y-m-d H:i:s'$taskinfo->created));
  527.             $em->persist($task);
  528.             $em->flush();
  529.         }
  530.         return $task;
  531.     }
  532.     public function storeFpTask($taskinfo) {
  533.         $em $this->entityManager;
  534.         $task $em->getRepository(FPTasks::class)->findOneBy(array('uuid' => $taskinfo->task_id));
  535.         if(!$task) {
  536.             $task = new FPTasks();
  537.             $task->setTestId($taskinfo->test_id);
  538.             $task->setUuid($taskinfo->task_id);
  539.             $task->setName($taskinfo->type);
  540.             $task->setLeadId($taskinfo->lead_id);
  541.             $task->setKeyword($taskinfo->keyword);
  542.             $task->setSearchEngine($taskinfo->se);
  543.             $task->setSeType($taskinfo->se_type);
  544.             $task->setDevice($taskinfo->device);
  545.             $task->setStatus($taskinfo->status);
  546.             $task->setResult($taskinfo->result);
  547.             $task->setCreated(\DateTime::createFromFormat('Y-m-d H:i:s'$taskinfo->created));
  548.             $em->persist($task);
  549.             $em->flush();
  550.         }
  551.         return $task;
  552.     }
  553.     public function storeFpRanking($ranking) {
  554.         return; // This has been discontinued in favor of the processSerpKwRankings function below
  555.         $em $this->entityManager;
  556.         $rank $em->getRepository(FPRankings::class)->findOneBy(array('uuid' => $ranking->uuid'test_group' => $ranking->test_group));
  557.         if(!$rank) {
  558.             $rank = new FPRankings();
  559.             $rank->setCreated(\DateTime::createFromFormat('Y-m-d H:i:s'$ranking->created));
  560.         }
  561.             $rank->setLeadId($ranking->lead_id);
  562.             $rank->setUuid($ranking->uuid);
  563.             $rank->setTestGroup($ranking->test_group);
  564.             $rank->setKeyword($ranking->keyword);
  565.             $rank->setTitle($ranking->title);
  566.             $rank->setDescription($ranking->description);
  567.             $rank->setBreadcrumb($ranking->breadcrumb);
  568.             $rank->setDomain($ranking->domain);
  569.             $rank->setString($ranking->string);
  570.             $rank->setYear($ranking->year);
  571.             $rank->setMonth($ranking->month);
  572.             $rank->setGoogleDeskNat($ranking->google_desk_nat);
  573.             $rank->setGoogleDeskLoc($ranking->google_desk_loc);
  574.             $rank->setGoogleMobiNat($ranking->google_mobi_nat);
  575.             $rank->setGoogleMobiLoc($ranking->google_mobi_loc);
  576.             $rank->setGoogleAdsNat($ranking->google_ads_nat);
  577.             $rank->setGoogleAdsLoc($ranking->google_ads_loc);
  578.             $rank->setGoogleMapNat($ranking->google_map_nat);
  579.             $rank->setGoogleMapLoc($ranking->google_map_loc);
  580.             $rank->setBingDeskNat($ranking->bing_desk_nat);
  581.             $rank->setBingDeskLoc($ranking->bing_desk_loc);
  582.             $rank->setBingMobiNat($ranking->bing_mobi_nat);
  583.             $rank->setBingMobiLoc($ranking->bing_mobi_loc);
  584.             $rank->setYahooDeskNat($ranking->yahoo_desk_nat);
  585.             $rank->setYahooDeskLoc($ranking->yahoo_desk_loc    );
  586.             $em->persist($rank);
  587.             $em->flush();
  588.             return $rank;
  589.     }
  590.     public function storeQueue($qinfo) {
  591.         $em $this->entityManager;
  592.         $qitem $em->getRepository(IntelQueue::class)->findOneBy(array('content' => $qinfo->content'actionapi' => $qinfo->actionapi'function' => $qinfo->function));
  593.         //dd($qinfo->content);
  594.         if(!$qitem) {
  595.             $qitem = new IntelQueue();
  596.             $qitem->setPurpose($qinfo->purpose);
  597.             $qitem->setLocationCode($qinfo->location_code);
  598.             $qitem->setActionApi($qinfo->actionapi);
  599.             $qitem->setFunction($qinfo->function);
  600.             $qitem->setContent($qinfo->content);
  601.             $qitem->setMore($qinfo->more);
  602.             $qitem->setCreated(\DateTime::createFromFormat('Y-m-d H:i:s'date('Y-m-d H:i:s')));
  603.             $em->persist($qitem);
  604.             $em->flush();
  605.         }
  606.         return $qitem;
  607.     }
  608.     public function getUUID() {
  609.         $randomString openssl_random_pseudo_bytes(16);
  610.         $time_low bin2hex(substr($randomString04));
  611.         $time_mid bin2hex(substr($randomString42));
  612.         $time_hi_and_version bin2hex(substr($randomString62));
  613.         $clock_seq_hi_and_reserved bin2hex(substr($randomString82));
  614.         $node bin2hex(substr($randomString106));
  615.         $time_hi_and_version hexdec($time_hi_and_version);
  616.         $time_hi_and_version $time_hi_and_version >> 4;
  617.         $time_hi_and_version $time_hi_and_version 0x4000;
  618.         $clock_seq_hi_and_reserved hexdec($clock_seq_hi_and_reserved);
  619.         $clock_seq_hi_and_reserved $clock_seq_hi_and_reserved >> 2;
  620.         $clock_seq_hi_and_reserved $clock_seq_hi_and_reserved 0x8000;
  621.         return sprintf('%08s-%04s-%04x-%04x-%012s'$time_low$time_mid$time_hi_and_version$clock_seq_hi_and_reserved$node);
  622.     } 
  623.     private function getTargetLocation($userinfo) {
  624.         if(!empty($userinfo['localtarget'])) {
  625.             $location $this->locationsRepository->findLocationCity($userinfo['localtarget'], $userinfo['state']);
  626.         } else {
  627.             $location $this->locationsRepository->findLocationCity($userinfo['city'], $userinfo['state']);
  628.         }
  629.         return $location->getLocationCode();
  630.     }
  631.     public function processSerpKwRankings($testgroup,$campinfo,$purpose 'footprint') {
  632.         // Lets process the rankings for keywords found in the Serps
  633.         $em $this->entityManager;
  634.         if($purpose == 'footprint') {
  635.             //For now we will do the footprint purpose. Will multipurpose this function later.
  636.             $serpsRepo $em->getRepository(FPSerps::class);
  637.             $rankingsRepo $em->getRepository(FPRankings::class);
  638.         } else {
  639.             //Assume purpose of Campaign. Will do this later.
  640.             //$serpRepo = $this->kwSerpsRepository;
  641.             //$rankRepo = $this->kwRankingsRepository;
  642.         }
  643.         //dd($testgroup,$campinfo);
  644.         $thistestgroup $testgroup->getTestGroup();
  645.         $lead_id $testgroup->getLeadId();
  646.         $checkserps $serpsRepo->findBy(['test_group' => $thistestgroup], ['task_id' => 'ASC']);
  647.         //echo count($checkserps).'<br>';
  648.         $month =  $testgroup->getCreated()->format('m');
  649.         $year =  $testgroup->getCreated()->format('Y');
  650.         $created $testgroup->getCreated()->format('Y-m-d H:i:s');
  651.         foreach($checkserps as $serp) {
  652.             //echo $serp->getKeyword().' - '.$serp->getSearchEngine().' - '.$serp->getDevice().' - '.$serp->getLocation().' - ';
  653.             if($serp->getSearchEngine() == 'google') {
  654.                 $serpfile $serp->getAdvanced();
  655.             } else {
  656.                 $serpfile $serp->getRegular();
  657.             }
  658.             if(!isset($campinfo['domain'])) {
  659.                 $parse parse_url($campinfo['url']);
  660.                 $campinfo['domain'] = $parse['host'];
  661.             }
  662.             $stripdomain str_replace('www.'''$campinfo['domain']); 
  663.             $keyword $serp->getKeyword();
  664.             //echo ' trying for '.$serpfile.'<br>';
  665.             if(file_exists($_ENV["HOMEDIR"].'/'.$serpfile)) {
  666.                 //echo '.... found '.$serpfile.'<br>';
  667.                 $serpfile json_decode(file_get_contents($_ENV["HOMEDIR"].'/'.$serpfile));
  668.                 $serpfile = (object) $serpfile[0];
  669.                 
  670.                 $ranking $rankingsRepo->findOneBy(['lead_id' => $lead_id'keyword' => $keyword'year' => $year'month' => $month]);
  671.                 if(!$ranking) {
  672.                     $ranking = new FPRankings;
  673.                     $ranking->setCreated(\DateTime::createFromFormat('Y-m-d H:i:s'$created));
  674.                     $ranking->setLeadId($lead_id);
  675.                     $ranking->setUuid($this->getUUID());
  676.                     $ranking->setTestGroup($thistestgroup);
  677.                     $ranking->setKeyword($keyword);
  678.                     $ranking->setYear($year);
  679.                     $ranking->setMonth($month);
  680.                 }
  681.                 
  682.                 $thisrank = (object) array();
  683.                 $device $serp->getDevice();
  684.                 $searchengine $serp->getSearchEngine();
  685.                 $locationcode $serp->getLocation();
  686.                 if($locationcode == 2840) {
  687.                     $locationtype 'Country';
  688.                 } else {
  689.                     $locationinfo $this->locationsRepository->findLocationUS($serp->getLocation());
  690.                     $locationtype $locationinfo->getLocationType(); 
  691.                 }
  692.                 if($serpfile->se_domain == 'google.com') { 
  693.                     // Leaving it as is cause may add bing.com later.
  694.                     foreach($serpfile->items as $slisting) {
  695.                         if(!empty($slisting->domain)) {
  696.                             // First we check for Paid adds in the Serp and add the rankings to the 
  697.                             // google_ads_nat and google_ads_loc columns. Maybe bing ads later.
  698.                             if((stristr($slisting->domain$stripdomain) || stristr($slisting->domain$stripdomain)) && $slisting->type == 'paid') {
  699.                                 $column $serp->getSearchEngine().'_ads';
  700.                                 if (($locationtype == 'City' || $locationtype == 'State' || $locationtype == 'County')) {
  701.                                     $thisrank->{$column.'_loc'} = $slisting->rank_group;
  702.                                 } elseif (($locationtype == 'Region' || $locationtype == 'Country')) {
  703.                                     $thisrank->{$column.'_nat'} = $slisting->rank_group;
  704.                                 } else {
  705.                                     $thisrank->{$column.'_nat'} = $slisting->rank_group;
  706.                                 }
  707.                                 // We include these in case they are never found in rankings later. If they are we 
  708.                                 // just overwrite them when the organic rankings are found.
  709.                                 $thisrank->setTitle $slisting->title;
  710.                                 $thisrank->setString $slisting->url;
  711.                                 $thisrank->setDescription $slisting->description;         
  712.                                 break;
  713.                             }
  714.                             
  715.                         }
  716.                     }
  717.                 }
  718.                 
  719.                 if($serpfile->se_domain != 'yahoo.com') { 
  720.                     // This will check for the Google and Bing Maps rankings. If maps are found in the Serp they are 
  721.                     // added to google_map_nat google_map_loc bing_map_nat bing_map_loc columns
  722.                     foreach($serpfile->items as $slisting) {
  723.                         if(!empty($slisting->domain)) {
  724.                             if((stristr($slisting->domain$stripdomain) || stristr($slisting->domain$stripdomain)) && ($slisting->type == 'maps' || $slisting->type == 'local_pack')) {
  725.                                 $column $searchengine.'_map';
  726.                                 if (($locationtype == 'City' || $locationtype == 'State' || $locationtype == 'County')) {
  727.                                     $thisrank->{$column.'_loc'} = $slisting->rank_group;
  728.                                 } elseif (($locationtype == 'Region' || $locationtype == 'Country')) {
  729.                                     $thisrank->{$column.'_nat'} = $slisting->rank_group;
  730.                                 } else {
  731.                                     $thisrank->{$column.'_nat'} = $slisting->rank_group;
  732.                                 }
  733.                                 break;
  734.                             }
  735.                         }
  736.                     } 
  737.                 }
  738.                 
  739.                 // Now we chew on the truly Organic listings. 
  740.                 foreach($serpfile->items as $slisting) {
  741.                     if(!empty($slisting->domain)) {
  742.                         if((stristr($slisting->domain$stripdomain) || stristr($slisting->domain$stripdomain)) && $slisting->type == 'organic') {
  743.                             if($device == 'desktop') {
  744.                                 $column $searchengine.'_desk';
  745.                             } else {
  746.                                 $column $searchengine.'_mobi';
  747.                             }
  748.                             if (($locationtype == 'City' || $locationtype == 'State' || $locationtype == 'County')) {
  749.                                 $thisrank->{$column.'_loc'} = $slisting->rank_group;
  750.                                 $usecolumn $column.'_loc';
  751.                             } elseif (($locationtype == 'Region' || $locationtype == 'Country')) {
  752.                                 $thisrank->{$column.'_nat'} = $slisting->rank_group;
  753.                                 $usecolumn $column.'_nat';
  754.                             } else {
  755.                                 $thisrank->{$column.'_nat'} = $slisting->rank_group;
  756.                                 $usecolumn $column.'_nat';
  757.                             }
  758.                             //echo '<b>'.$slisting->domain.' - '.$serpfile->keyword.' - organic - column: '.$usecolumn.' location: '.$locationcode.' loc_type: '.$locationtype.' rank: '.$slisting->rank_group.'</b><br>';
  759.                             if(!isset($thisrank->domain) || 'google' == $searchengine) {
  760.                                 $thisrank->domain $slisting->domain;
  761.                             }
  762.                             if(!isset($thisrank->title) || 'google' == $searchengine) {
  763.                                 $thisrank->title $slisting->title;
  764.                             }
  765.                             if(!isset($thisrank->string) || 'google' == $searchengine) {
  766.                                 $thisrank->string $slisting->url;
  767.                             }
  768.                             if(!isset($thisrank->description) || 'google' == $searchengine) {
  769.                                 $thisrank->description $slisting->description;
  770.                             }
  771.                             if(!isset($thisrank->breadcrumb) || 'google' == $searchengine) {
  772.                                 $thisrank->breadcrumb $slisting->breadcrumb
  773.                             } 
  774.                             break;
  775.                         }
  776.                     }
  777.                 } 
  778.             } 
  779.             //$this->storeFpRanking($ranking);
  780.             if(isset($thisrank->google_desk_nat)) { $ranking->setGoogleDeskNat($thisrank->google_desk_nat); }
  781.             if(isset($thisrank->google_desk_loc)) { $ranking->setGoogleDeskLoc($thisrank->google_desk_loc); }
  782.             if(isset($thisrank->google_mobi_nat)) { $ranking->setGoogleMobiNat($thisrank->google_mobi_nat); }
  783.             if(isset($thisrank->google_mobi_loc)) { $ranking->setGoogleMobiLoc($thisrank->google_mobi_loc); }
  784.             if(isset($thisrank->google_ads_nat)) { $ranking->setGoogleAdsNat($thisrank->google_ads_nat); }
  785.             if(isset($thisrank->google_ads_loc)) { $ranking->setGoogleAdsLoc($thisrank->google_ads_loc); }
  786.             if(isset($thisrank->google_map_nat)) { $ranking->setGoogleMapNat($thisrank->google_map_nat); }
  787.             if(isset($thisrank->google_map_loc)) { $ranking->setGoogleMapLoc($thisrank->google_map_loc); }
  788.             if(isset($thisrank->bing_desk_nat)) { $ranking->setBingDeskNat($thisrank->bing_desk_nat); }
  789.             if(isset($thisrank->bing_desk_loc)) { $ranking->setBingDeskLoc($thisrank->bing_desk_loc); }
  790.             if(isset($thisrank->bing_mobi_nat)) { $ranking->setBingMobiNat($thisrank->bing_mobi_nat); }
  791.             if(isset($thisrank->bing_mobi_loc)) { $ranking->setBingMobiLoc($thisrank->bing_mobi_loc); }
  792.             if(isset($thisrank->yahoo_desk_nat)) { $ranking->setYahooDeskNat($thisrank->yahoo_desk_nat); }
  793.             if(isset($thisrank->yahoo_desk_loc)) { $ranking->setYahooDeskLoc($thisrank->yahoo_desk_loc); }
  794.             if(isset($thisrank->domain) && empty($ranking->getDomain())) {
  795.                 $ranking->setDomain($thisrank->domain);
  796.             }
  797.             if(isset($thisrank->title) && empty($ranking->getTitle())) {
  798.                 $ranking->setTitle($thisrank->title);
  799.             }
  800.             if(isset($thisrank->string) && empty($ranking->getString())) {
  801.                 $ranking->setString($thisrank->string);
  802.             }
  803.             if(isset($thisrank->description) && empty($ranking->getDescription())) {
  804.                 $ranking->setDescription($thisrank->description);
  805.             }
  806.             if(isset($thisrank->breadcrumb) && empty($ranking->getBreadcrumb())) {
  807.                 $ranking->setBreadcrumb($thisrank->breadcrumb);
  808.             }
  809.             $em->persist($ranking);
  810.             $em->flush();
  811.         }
  812.         //$testgroup->setStatus('ready');
  813.         //$em->persist($testgroup);
  814.         //$em->flush();
  815.         return;
  816.     }
  817.     public function getUserKeywords($userinfo) {
  818.         //Lets build the current keywords set from the user info
  819.         foreach($userinfo as $key => $val) {
  820.             if($userinfo['local'] == 'yes') {
  821.                 if (strstr($key'keyword') && !strstr($key'keywordval') ) {
  822.                     if(!empty($val) && !empty($userinfo['localtarget'])) {
  823.                         $keywords['local'][] = $val.' '.strtolower($userinfo['localtarget']);
  824.                     }
  825.                 }
  826.                 if (strstr($key'keyword') && !strstr($key'keywordval') ) {
  827.                     if(!empty($val) && !empty($userinfo['city'])) {
  828.                         $keywords['local'][] = $val.' '.strtolower($userinfo['city']);
  829.                     }
  830.                 }
  831.             }
  832.             if($userinfo['national'] == 'yes') {
  833.                 if (strstr($key'keyword') && !strstr($key'keywordval') ) {
  834.                     if(!empty($val)) {
  835.                         $keywords['national'][] = $val;
  836.                     }
  837.                 }
  838.             }
  839.         }
  840.         if(!empty($userinfo['brand'])) {
  841.             $keywords['local'][] = mb_convert_encoding(strtolower($userinfo['brand']), "UTF-8");
  842.             $keywords['national'][] = mb_convert_encoding(strtolower($userinfo['brand']), "UTF-8");
  843.         }
  844.         return $keywords;
  845.     }
  846.     /*
  847.     // Here we keep some of the Footprint functions used in other classes
  848.     // Tests kwranking, kwvolumes, mapsranking, pagespeed, gmbtest are D4SEO Service
  849.     */
  850.     /**
  851.      * Create and run kwvolumes and complete the test
  852.      */
  853.     public function testD4kwvolumes($test,$userinfo) {
  854.         //return;
  855.         echo "Creating KWVolumes Tasks<br>";
  856.         $userinfo $this->userRepository->findSafeLeadInfo($test->getLeadId());
  857.         $keywords $this->getUserKeywords($userinfo);
  858.         if($userinfo['national'] == 'yes') {
  859.             $location 2840;
  860.             $postinfo = (object) array( 
  861.                 "language_code" => "en"
  862.                 "location_code" => $location
  863.                 "keywords" =>  $keywords['national'],
  864.                 "purpose" => 'footprint',
  865.                 "priority" => 1,
  866.                 'test_id' => $test->getId(),
  867.                 'se_type' => 'kwvolumes',
  868.                 'se' => 'google',
  869.                 'device' => 'desktop',
  870.                 'lead_id' => $test->getLeadId()
  871.             );  
  872.             $result $this->keywordVolumes($postinfo);
  873.         }
  874.         if($userinfo['local'] = 'yes') {
  875.             $location $this->getTargetLocation($userinfo);
  876.             $postinfo = (object) array( 
  877.                 "language_code" => "en"
  878.                 "location_code" => $location
  879.                 "keywords" =>  $keywords['local'],
  880.                 "purpose" => 'footprint',
  881.                 "priority" => 1,
  882.                 'test_id' => $test->getId(),
  883.                 'se_type' => 'kwvolumes',
  884.                 'se' => 'google',
  885.                 'device' => 'desktop',
  886.                 'lead_id' => $test->getLeadId()
  887.             );  
  888.             $this->keywordVolumes($postinfo);
  889.         }
  890.         /*
  891.         // Get keyword volumes for each of the keywords. Send for each location national and local if applicable.
  892.         // We may want to check if test is still pending on the second run. If so we can force pull from the 
  893.         // retrieval endpoint. Return possibly failed. If we can get it the second time mark test as failed.
  894.         // DO THIS LATER
  895.         */
  896.     }  
  897.     /**
  898.      * Create and run kwranking by calling necessary serps and complete the test
  899.      */
  900.     public function testD4kwranking($test,$userinfo) {
  901.         //return;
  902.         echo "Creating KWRankings Tasks<br>";
  903.         $keywords $this->getUserKeywords($userinfo);
  904.         //dd($keywords);
  905.         $engines = array('google''bing''yahoo');
  906.         $devices = array('desktop''mobile');
  907.         foreach ($engines as $engine) {
  908.             foreach($devices as $device) {
  909.                 if(isset($keywords['national']) && $userinfo['national'] == 'yes') {
  910.                     $locallocation $this->getTargetLocation($userinfo);
  911.                     foreach($keywords['national'] as $keyword) {
  912.                         $location 2840;
  913.                         $postinfo = (object) array( 
  914.                             "language_code" => "en"
  915.                             "location_code" => $location
  916.                             "keyword" =>  $keyword,
  917.                             "purpose" => 'footprint',
  918.                             "priority" => 1,
  919.                             'test_id' => $test->getId(),
  920.                             'type' => 'kwranking',
  921.                             'se_type' => 'organic',
  922.                             'lead_id' => $test->getLeadId(),
  923.                             'se' => $engine,
  924.                             'device' => $device
  925.                         );  
  926.                         $this->keywordSerps($postinfo);
  927.                     }
  928.                     //echo " - National ".$engine." ".$device." ".$location."<br>";
  929.                     foreach($keywords['national'] as $keyword) {
  930.                         $postinfo = (object) array( 
  931.                             "language_code" => "en"
  932.                             "location_code" => $locallocation
  933.                             "keyword" =>  $keyword,
  934.                             "purpose" => 'footprint',
  935.                             "priority" => 1,
  936.                             'test_id' => $test->getId(),
  937.                             'type' => 'kwranking',
  938.                             'se_type' => 'organic',
  939.                             'lead_id' => $test->getLeadId(),
  940.                             'se' => $engine,
  941.                             'device' => $device
  942.                         );  
  943.                         $this->keywordSerps($postinfo);
  944.                     }
  945.                     //echo " - National ".$engine." ".$device." ".$locallocation."<br>";                    
  946.                 }
  947.                 if(isset($keywords['local']) && $userinfo['local'] == 'yes') {
  948.                     if('yahoo' != $engine) {
  949.                         foreach($keywords['local'] as $keyword) {
  950.                             $postinfo = (object) array( 
  951.                                 "language_code" => "en"
  952.                                 "location_code" => $locallocation
  953.                                 "keyword" =>  $keyword,
  954.                                 "purpose" => 'footprint',
  955.                                 "priority" => 1,
  956.                                 'test_id' => $test->getId(),
  957.                                 'type' => 'kwranking',
  958.                                 'se_type' => 'organic',
  959.                                 'lead_id' => $test->getLeadId(),
  960.                                 'se' => $engine,
  961.                                 'device' => $device
  962.                             );
  963.                             $this->keywordSerps($postinfo);
  964.                         }
  965.                     }
  966.                     //echo " - Local ".$engine." ".$device." ".$location."<br>";
  967.                 }
  968.             }
  969.             sleep(1);
  970.         } 
  971.         sleep(1);
  972.     }    
  973.     /**
  974.      * Create and run mapsranking and complete the test
  975.      */
  976.     public function testD4mapsranking($test,$userinfo) {
  977.         //return;
  978.         echo "Creating MapsRanking Tasks<br>";
  979.         $keywords $this->getUserKeywords($userinfo);
  980.         $engines = array('google''bing');
  981.         $devices = array('desktop');
  982.         foreach ($engines as $engine) {
  983.             if($engine == 'google') {
  984.                 $setype 'maps';
  985.             } else {
  986.                 $setype 'local_pack';
  987.             }
  988.             foreach($devices as $device) {
  989.                 if($engine == 'bing' && $device == 'mobile') {
  990.                     break;
  991.                 }
  992.                 if(isset($keywords['national']) && $userinfo['national'] == 'yes') {
  993.                     foreach($keywords['national'] as $keyword) {
  994.                         $location 2840;
  995.                         $postinfo = (object) array( 
  996.                             "language_code" => "en"
  997.                             "location_code" => $location
  998.                             "keyword" =>  $keyword,
  999.                             "purpose" => 'footprint',
  1000.                             "priority" => 1,
  1001.                             'test_id' => $test->getId(),
  1002.                             'type' => 'mapsranking',
  1003.                             'se_type' => $setype,
  1004.                             'se' => $engine,
  1005.                             'lead_id' => $test->getLeadId(),
  1006.                             'engine' => $engine,
  1007.                             'device' => $device,
  1008.                         );  
  1009.                         $this->keywordMapPacks($postinfo);
  1010.                     }
  1011.                     //echo " - National ".$engine." ".$device." ".$location."<br>";
  1012.                 }
  1013.                 if(isset($keywords['local']) && $userinfo['local'] == 'yes') {
  1014.                     $location $this->getTargetLocation($userinfo);
  1015.                     foreach($keywords['local'] as $keyword) {
  1016.                         $postinfo = (object) array( 
  1017.                             "language_code" => "en"
  1018.                             "location_code" => $location
  1019.                             "keyword" =>  $keyword,
  1020.                             "purpose" => 'footprint',
  1021.                             "priority" => 1,
  1022.                             'test_id' => $test->getId(),
  1023.                             'type' => 'mapsranking',
  1024.                             'se_type' => $setype,
  1025.                             'se' => $engine,
  1026.                             'lead_id' => $test->getLeadId(),
  1027.                             'engine' => $engine,
  1028.                             'device' => $device,
  1029.                         );
  1030.                         $this->keywordMapPacks($postinfo);
  1031.                     }
  1032.                     //echo " - Local ".$engine." ".$setype." ".$device." ".$location."<br>";
  1033.                 }
  1034.             }
  1035.         } 
  1036.         sleep(1);
  1037.     }  
  1038.     /**
  1039.      * Create and run gmbtest including GMB and Reviews and complete the test 
  1040.      */
  1041.     public function testD4gmbtest($test$userinfo) {
  1042.         //return;
  1043.         echo "Creating GMB Test Tasks<br>";
  1044.         if(!empty($userinfo['brand'])) {
  1045.             $keyword mb_convert_encoding($userinfo['brand'], "UTF-8");
  1046.         } else {
  1047.             $keyword mb_convert_encoding($userinfo['companyname'], "UTF-8");
  1048.         }
  1049.         $userinfo['localtarget'] = $userinfo['city'];
  1050.         $location $this->getTargetLocation($userinfo);
  1051.         $em $this->entityManager;
  1052.         $place $em->getRepository(Gplaces::class)->findBy(array('title' => $keyword'location' => $location), ['modified' => 'DESC'], 1);
  1053.         if(!$place) {
  1054.             $address trim($userinfo['address'], '.').', '.$userinfo['city'].', '.$userinfo['iso'].' '.$userinfo['zip'];
  1055.             $place $em->getRepository(Gplaces::class)->findOneBy(array('title' => $keyword'address' => $address), ['modified' => 'DESC'], 1);
  1056.         } 
  1057.         if(isset($place)) {
  1058.             $keyword "cid:".$place->getCid();
  1059.             //dd($place);
  1060.         }
  1061.         if($userinfo['local'] == 'yes') {
  1062.             $postinfo = (object) array( 
  1063.                 "language_code" => "en"
  1064.                 "location_code" => $location
  1065.                 "keyword" =>  $keyword,
  1066.                 "purpose" => 'footprint',
  1067.                 "priority" => 1,
  1068.                 'test_id' => $test->getId(),
  1069.                 'type' => 'gmbtest',
  1070.                 'se_type' => 'reviews',
  1071.                 'se' => 'google',
  1072.                 'lead_id' => $test->getLeadId(),
  1073.                 'device' => 'desktop',
  1074.             ); 
  1075.             //dd($postinfo);
  1076.             $this->businessReviews($postinfo);
  1077.         }
  1078.     }  
  1079. }