src/Controller/MainController.php line 119

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Base\ControllerBase;
  4. use App\Entity\LicenseOrder;
  5. use App\Entity\User;
  6. use App\Entity\Company;
  7. use App\Entity\Account;
  8. use App\Entity\Driver;
  9. use App\Entity\Vehicle;
  10. use App\Entity\Trailer;
  11. use App\Entity\Document;
  12. use App\Entity\Setting;
  13. use App\Entity\Link;
  14. use App\Entity\BroadcastMessage//COM-469
  15. use App\Entity\SystemTip// COM-695
  16. use App\Entity\SystemTipLogEntry// COM-695
  17. use App\Services\TimeCalculator;
  18. use App\Services\FormsHelper;
  19. use App\Services\EmailNotifier;
  20. use App\Services\RoutingHelper;
  21. use App\Services\DocumentBuilder;
  22. use App\Services\ActivityGraph;
  23. use App\Type\UserRoleEnum;
  24. use App\Type\DocumentTypeEnum;
  25. use App\Type\CompanyConfigStatusTypeEnum;
  26. use App\Type\CompanyAdminTypeEnum// COM-479
  27. use App\Type\BalanceTypeEnum;
  28. use App\Type\BroadcastMessageReactionEnum//COM-469
  29. use App\Type\SystemTipStatusEnum// COM-695
  30. use Symfony\Bundle\FrameworkBundle\Controller\Controller;
  31. use Symfony\Component\HttpFoundation\Request;
  32. use Symfony\Component\HttpFoundation\Response;
  33. use Symfony\Component\HttpFoundation\JsonResponse;
  34. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  35. use Symfony\Component\HttpFoundation\Cookie;
  36. use Symfony\Component\Routing\Annotation\Route;
  37. use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
  38. use Symfony\Component\Serializer\Serializer;
  39. #use Symfony\Component\Serializer\Encoder\XmlEncoder;
  40. use Symfony\Component\Serializer\Encoder\JsonEncoder;
  41. use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
  42. use Doctrine\Common\Collections\ArrayCollection;
  43. use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface;
  44. use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
  45. use Symfony\Component\Translation\TranslatorInterface;
  46. use Psr\Log\LoggerInterface;
  47. use Sinergi\BrowserDetector\Browser;
  48. class MainController extends ControllerBase
  49. {
  50.     // ******************************************
  51.     //     HOME & LOGIN
  52.     // ******************************************
  53.     /**
  54.      * @Route("/", name="b_home")
  55.      */
  56.     public function home(Request $request)
  57.     {
  58.         $thisUserType = ($this->getUser()==null) ? null $this->getUser()->getRolesUnconverted();
  59.         
  60.         //dd('home thisUserType', $thisUserType);
  61.         
  62.         return $this->redirectToRoute(RoutingHelper::getDefaultRoute($thisUserType));
  63.         
  64.     }
  65.     // login route must correspond to security.yaml's firewalls/XXX/form_login config
  66.     /**
  67.      * @Route("/login-check", name="b_login_check")
  68.      */
  69.     public function login_check(Request $request)
  70.     {
  71.     
  72.         $tokenProvider $this->container->get('security.csrf.token_manager');
  73.         $token $tokenProvider->getToken('authenticate')->getValue();
  74.         //dump('tokenProvider', $tokenProvider);
  75.         //dump('token', $token);
  76.         
  77.         $result = [];
  78.         return new Response($this->jsonEncoder(array(
  79.             's' => true,
  80.             't' => $token,
  81.         )));
  82.     
  83.     }
  84.         
  85.     // login route must correspond to security.yaml's firewalls/XXX/form_login config
  86.     /**
  87.      * @Route("/login", name="b_login")
  88.      */
  89.     public function login(Request $requestAuthenticationUtils $authUtils)
  90.     {
  91.     
  92.         //dump($this);
  93.         //dump($request);
  94.         //dump($authUtils);
  95.         //die();
  96.         
  97.             
  98.         ////$this->handlePageOpen($request, 'general');
  99.         ////$userRepository = $this->getDoctrine()->getRepository(User::class);
  100.         ////$user = $userRepository->find(1);
  101.         //if ($user) echo $user->get_first_name();
  102.         $this->setLanguageAndLocale($request);
  103.         echo "<!-- ";
  104.         //$this->session->set('language', null);
  105.         //dump($this->session->get('language'));
  106.         dump('_SERVER'$_SERVER);
  107.         echo " -->";
  108.         // NB: when the user submits the form, the security system automatically handles the form submission
  109.         // JJM: if logged in already, redirect somewhere
  110.         // $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
  111.         // get the login error if there is one
  112.         $error $authUtils->getLastAuthenticationError();
  113.         //dump($error);
  114.         //if ($error!=null && get_class($error)=='BadCredentialsException') dump($error->getMessage());
  115.         // last username entered by the user
  116.         $lastUsername $authUtils->getLastUsername();
  117.         //echo "error=[$error], lastUsername=[$lastUsername]<br>"; //die();
  118.         
  119.         $response = new Response();
  120.         $initialMessage '';
  121.         $initialMessageType 'info';
  122.         // get msgs from bag    
  123.         if ($error==null && $initialMessage=='') {
  124.             foreach ($this->session->getFlashBag()->get('error', array()) as $message) {
  125.                 $initialMessage "showMsg('$message', false);";
  126.                 $initialMessageType 'error';
  127.                 break;
  128.             }
  129.         }
  130.         if ($error==null && $initialMessage=='') {
  131.             foreach ($this->session->getFlashBag()->get('success', array()) as $message) {
  132.                 $initialMessage "showMsg('$message', true);";
  133.                 $initialMessageType 'success';
  134.                 break;
  135.             }
  136.         }
  137.         
  138.         // browser check, if not done yet
  139.         /*if ($error==false && $initialMessage=='') {
  140.             if ($request->cookies->get('ACE_browser_check')!='done') {
  141.                 $browser = new Browser();
  142.                 //dump($browser->getName());
  143.                 if ($browser->getName() === Browser::IE) { //IE
  144.                     $initialMessage = "showMsg('".$this->translator->trans('message.badBrowser', array(), 'general')."', 'info');";
  145.                     $response->headers->setCookie(
  146.                         new Cookie( 'ACE_browser_check', 'done',  time() + (10 * 365 * 24 * 3600) )
  147.                     );                
  148.                 }
  149.             }
  150.         }*/
  151.         
  152.         /* // tell login page to show the pwd reminder form
  153.         $showPwdResetByDefault = false;
  154.         if ($this->session->get('login-page-referrer')!==null && $this->session->get('login-page-referrer')=='b_forgotPwd') {
  155.             $showPwdResetByDefault = true;
  156.             $this->session->remove('login-page-referrer');
  157.         } */
  158.         //dd($_COOKIE);
  159.         // COM-508
  160.         $response->headers->clearCookie('consumption-waybill''/'null);
  161.         
  162.         $systemInfo $_SERVER['APP_SYSTEM_ID'];
  163.         
  164.         if (0) {
  165.             if (0) {
  166.                 $_SERVER['DATABASE_URL'] = '';
  167.                 $_SERVER['szamlazz_hu_api'] = '';
  168.                 $_SERVER['otp_simple_api_key'] = '';
  169.                 dump('_SERVER'$_SERVER);
  170.             }
  171.                         
  172.             $varsToLog = [
  173.                 'HTTP_HOST',
  174.                 'HTTP_REFERER',
  175.                 'HTTP_SEC_CH_UA_PLATFORM',
  176.                 'HTTP_USER_AGENT',
  177.                 'REDIRECT_SSL_TLS_SNI',
  178.                 'REMOTE_ADDR',
  179.                 'REMOTE_PORT',
  180.                 'REQUEST_URI',
  181.                 'SERVER_ADDR',
  182.                 'SERVER_NAME',
  183.                 'SERVER_PORT',
  184.                 'SSL_TLS_SNI',
  185.             ];
  186.             
  187.             //$systemInfo .= "<br>____________";
  188.             
  189.             foreach($varsToLog as $var) {
  190.                 $systemInfo .= "<br>".$var.": ".($_SERVER[$var] ?? '-null-');
  191.             }
  192.         
  193.         }
  194.         
  195.         return $this->render('backend/login.html.twig', array(
  196.             'last_username' => $lastUsername,
  197.             'error'         => $error,
  198.             'page_title' => $this->translator->trans('application.name', array(), 'general').' - '.
  199.                             $this->translator->trans('page.title', array(), 'login'),
  200.             'initialMessage' => $initialMessage,
  201.             'initialMessageType' => $initialMessageType,
  202.             'currentLanguage' => $this->currentLanguage,
  203.             'systemInfo' => $systemInfo,
  204.             //'emailsAllowed' => $emailsAllowed,
  205.             //'showPwdResetByDefault' => $showPwdResetByDefault,
  206.         ), $response);
  207.     }
  208.     /** COM-754
  209.      * @Route("/log-out", name="b_log_out")
  210.      */
  211.     public function logout(Request $request)
  212.     {
  213.         $timeout $request->query->get('timeout');
  214.         //dump('timeout', $timeout);
  215.         //dd();
  216.         $user $this->getUser();
  217.         if ($user!==null) {
  218.         
  219.             $user->__setDateTime('lastLogoutAt''now'true); //$this->timeCalc->currentDateTime);
  220.             
  221.             if ($timeout==1) {
  222.                 $user->__set('lastLogoutType'User::LOGOUT_TYPE_AUTOMATIC);
  223.             } else {
  224.                 $user->__set('lastLogoutType'User::LOGOUT_TYPE_MANUAL);
  225.             }
  226.             
  227.             $rc $user->save$this->getDoctrine()->getManager(), false );
  228.             if (!$rc) {
  229.                 die('error updating user');
  230.             }
  231.             
  232.         }
  233.     
  234.         //dd('LOG OUT');
  235.         
  236.         return $this->redirectToRoute('b_logout');
  237.     }
  238.     // ******************************************
  239.     //     GENERAL ACTIONS (& CONFIG POPUP)
  240.     // ******************************************
  241.     /**
  242.      * @Route("/general/action", name="general.action", methods={"POST"})
  243.      */
  244.     public function general_action(Request $requestDocumentBuilder $documentBuilder)
  245.     {
  246.         $result $this->getDefaultAjaxReturnRec();
  247.         $returnData = array();
  248.         $em $this->getDoctrine()->getManager();
  249.         //dump('request: '.$request);
  250.         $type $request->request->get('type');
  251.         $step $request->request->get('step');
  252.         $data $request->request->get('data');
  253.         $companyId $request->request->get('companyId') ?? null;
  254.         //dump('type: '.$type);
  255.         //dump('data', $data);
  256.         //dump('step', $step);
  257.         if ($step!==null$step intval($step);
  258.         $action '';
  259.         if ($type=='togglePlayPause') {
  260.             $action 'modeChange';
  261.         } else if ($type=='acceptTerms') {
  262.             $action 'acceptTerms';
  263.         } else if ($type=='keepAlive') {
  264.             $action 'keepAlive';
  265.         }
  266.         // company config steps
  267.         $CONFIG_STEPS = [
  268.             'company' => 0,
  269.             'tofu' => 1,
  270.             'contract' => 2,
  271.             'gdpr' => 3,
  272.             'cookies' => 4,
  273.             'licenseType' => 5,
  274.             'settings' => 6,
  275.             'finish' => 7,
  276.         ];
  277.             
  278.         // set up any parms for handleControllerAction() call below        
  279.         $parms null;
  280.         if ($type=='firstLoginConfigStep' && $step==$CONFIG_STEPS['finish']) {
  281.             // if on last step of configuration, normally would get an exception (no-access-to-company-with-no-license);
  282.             // we need to prevent this, otherwise the config popup will not complete
  283.             $parms = [
  284.                 'lastConfigStep' => true,
  285.             ];
  286.         }        
  287.             
  288.         //$rc = $this->handlePageOpen($request, 'general', 'configuration', null, true); //T
  289.         $rc $this->handleControllerAction($request'general''general'nulltrue$parms); //
  290.         if ($rc!==true && $this->redirectRoute!=null) { //T
  291.             die('no access');
  292.             $result['info'] = 'no access';
  293.             $result['url'] = $this->router->generate('b_log_out');
  294.             return new Response($this->jsonEncoder(array(
  295.                 'result' => $result,
  296.             )));
  297.         }
  298.         if ($type=='firstLoginConfigStep') {
  299.             //dump("firstLoginConfigStep, step: $step");
  300. // CHECK it's a reg user
  301.         
  302.             // used for 2 purposes:
  303.             // - first login when company and user data is set
  304.             // - new company creation
  305.             if (isset($data['companyId']) && $data['companyId']!=null) {
  306.                 $companyId $data['companyId'];
  307.                 $company $this->getDoctrine()->getRepository(Company::class)->findOneById($companyId);
  308.             } else if ($companyId!=null) {
  309.                 $company $this->getDoctrine()->getRepository(Company::class)->findOneById($companyId);
  310.             } else {
  311.                 //$company = new Company;
  312.                 $company $this->company;
  313.                 $companyId $company->getId();
  314.             }
  315.             
  316.             // do action necessary for this config step
  317.             if ($step==$CONFIG_STEPS['company']) {
  318.             
  319.                 // save the company's data
  320.                 //dump('company');
  321.                 // contract
  322.                 $company->__set('name'$data['coName']);
  323.                 $company->__set('postalCode'$data['coAddrPCode']);
  324.                 $company->__set('city'$data['coAddrCity']);
  325.                 $company->__set('address'$data['coAddr']);
  326.                 $company->__set('country'$data['coCountry']);
  327.                 $company->__set('taxNumber'$data['coTaxNumber']);
  328.                 $company->__set('registrationNumber'$data['coRegistrationNumber']);
  329.                 $company->__set('europeanTaxNumber'$data['coEUTaxNumber']);
  330.                 $company->__set('contractSign1'$data['contractSign1']);
  331.                 $company->__set('contractSign1Email'$data['contractSign1Email']);
  332.                 $company->__set('contractSign1Phone'$data['contractSign1Phone']);
  333.                 $company->__set('contractSign2'$data['contractSign2']);
  334.                 $company->__set('contractSign2Email'$data['contractSign2Email']);
  335.                 $company->__set('contractSign2Phone'$data['contractSign2Phone']);
  336.                 // invoicing
  337.                 //invoicingDataSameAsContract        coInvoicingDataSameAsContract
  338.                 $company->__set('invoicingCompanyName'$data['coNameForInvoicing']);
  339.                 $company->__set('invoicingPostalCode'$data['coInvoicingAddrPCode']);
  340.                 $company->__set('invoicingCity'$data['coInvoicingAddrCity']);
  341.                 $company->__set('invoicingAddress'$data['coInvoicingAddr']);
  342.                 $company->__set('invoicingCountry'$data['coInvoicingCountry']);
  343.                 $company->__set('invoicingTaxNumber'$data['coInvoicingTaxNumber']);
  344.                 $company->__set('invoicingEuropeanTaxNumber'$data['coInvoicingEUTaxNumber']);
  345.                 // shipping
  346.                 //coShippingDataSameAsContract        coShippingDataSameAsContract    
  347.                 $company->__set('shippingCompanyName'$data['coNameForShipping']);
  348.                 $company->__set('shippingContactName'$data['coContactNameForShipping']);
  349.                 $company->__set('shippingPostalCode'$data['coShippingAddrPCode']);
  350.                 $company->__set('shippingCity'$data['coShippingAddrCity']);
  351.                 $company->__set('shippingAddress'$data['coShippingAddr']);
  352.                 $company->__set('shippingCountry'$data['coShippingCountry']);
  353.                 if ($company->__get('configurationStep')==null || $company->__get('configurationStep')<$step+1) {
  354.                     $company->__set('configurationStep'$step+1);
  355.                 }
  356.                 // set first type to active trial -- 
  357.                 //$company->__set('shippingAddress', );
  358.                 $rc $company->save$this->getDoctrine()->getManager() );
  359.                 if (!$rc) {
  360.                     die('error updating company');
  361.                 }
  362.                 
  363.                 // save company info entry
  364.                 $settingsValue $this->timeCalc->currentGmDateTimeFull.';u'.$this->getUser()->getId();
  365.                 $this->settingsLoader->updateSetting('config-step''company'$settingsValue$companyfalse);
  366.             } else if ($step==$CONFIG_STEPS['tofu']) {
  367.             
  368.                 //dump('tofu');
  369.                 // save TofU acceptance
  370.                 $settingsValue $this->timeCalc->currentGmDateTimeFull.';u'.$this->getUser()->getId();
  371.                 $this->settingsLoader->updateSetting('config-step''tofu'$settingsValue$companytrue);
  372.                 // check if document exists (we don't want many copies, at this time)
  373.                 $tofuDocuments $this->getDoctrine()->getRepository(Document::class)->findBy([
  374.                                                                                             'company' => $company,
  375.                                                                                             'type' => DocumentTypeEnum::TOFU,
  376.                                                                                             'deleted' => 0,
  377.                                                                                         ]);
  378.                 if ($tofuDocuments==null) {
  379.                     // create document for the TofU
  380.                     $document = new Document();
  381.                     $document->setCompany($company);
  382.                     $document->setName(''); // cannot be null
  383.                     $document->setType(DocumentTypeEnum::TOFU);
  384.                     $rc $document->save$this->getDoctrine()->getManager() );
  385.                     if (!$rc) {
  386.                         die('error updating document');
  387.                     }
  388.                     // generate the PDF sheet
  389.                     $parms = [];
  390.                     $documentBuilder->setParentController($this);
  391.                     $documentBuilder->setAccount($company->getAccount());
  392.                     $documentBuilder->setCompany($company);
  393.                     $documentBuilder->setDocument($document);
  394.                     $documentBuilder->build($parms);
  395.                     
  396.                 }
  397.                 // update config step in the company
  398.                 if ($company->__get('configurationStep')==null || $company->__get('configurationStep')<$step+1) {
  399.                     $company->__set('configurationStep'$step+1);
  400.                     $rc $company->save$this->getDoctrine()->getManager() );
  401.                     if (!$rc) {
  402.                         die('error updating company');
  403.                     }
  404.                 }
  405.                             
  406.             } else if ($step==$CONFIG_STEPS['contract']) {
  407.             
  408.                 //dump('contract');
  409.                 // save contract acceptance
  410.                 $settingsValue $this->timeCalc->currentGmDateTimeFull.';u'.$this->getUser()->getId();
  411.                 $this->settingsLoader->updateSetting('config-step''contract'$settingsValue$companyfalse);
  412.                 // check if document exists (we don't want many copies, at this time)
  413.                 $contractDocuments $this->getDoctrine()->getRepository(Document::class)->findBy([
  414.                                                                                             'company' => $company,
  415.                                                                                             'type' => DocumentTypeEnum::CONTRACT,
  416.                                                                                             'deleted' => 0,
  417.                                                                                         ]);
  418.                 if ($contractDocuments==null) {
  419.             
  420.                     // create document for the contract
  421.                     $document = new Document();
  422.                     $document->setCompany($company);
  423.                     $document->setName(''); // cannot be null
  424.                     $document->setType(DocumentTypeEnum::CONTRACT);
  425.                     $rc $document->save$this->getDoctrine()->getManager() );
  426.                     if (!$rc) {
  427.                         die('error updating document');
  428.                     }
  429.                     // generate the PDF sheet
  430.                     $parms = [];
  431.                     $documentBuilder->setParentController($this);
  432.                     $documentBuilder->setAccount($company->getAccount());
  433.                     $documentBuilder->setCompany($company);
  434.                     $documentBuilder->setDocument($document);
  435.                     $documentBuilder->build($parms);
  436.                 }
  437.                 // update config step in the company
  438.                 if ($company->__get('configurationStep')==null || $company->__get('configurationStep')<$step+1) {
  439.                     $company->__set('configurationStep'$step+1);
  440.                     $rc $company->save$this->getDoctrine()->getManager() );
  441.                     if (!$rc) {
  442.                         die('error updating company');
  443.                     }
  444.                 }
  445.                 
  446.             } else if ($step==$CONFIG_STEPS['gdpr']) {
  447.             
  448.                 //dump('gdpr');
  449.                 // save gdpr acceptance
  450.                 $settingsValue $this->timeCalc->currentGmDateTimeFull.';u'.$this->getUser()->getId();
  451.                 $this->settingsLoader->updateSetting('config-step''gdpr'$settingsValue$companyfalse);
  452.                 // check if document exists (we don't want many copies, at this time)
  453.                 $gdprDocuments $this->getDoctrine()->getRepository(Document::class)->findBy([
  454.                                                                                             'company' => $company,
  455.                                                                                             'type' => DocumentTypeEnum::GDPR,
  456.                                                                                             'deleted' => 0,
  457.                                                                                         ]);
  458.                 if ($gdprDocuments==null) {
  459.             
  460.                     // create document for the contract
  461.                     $document = new Document();
  462.                     $document->setCompany($company);
  463.                     $document->setName(''); // cannot be null
  464.                     $document->setType(DocumentTypeEnum::GDPR);
  465.                     $rc $document->save$this->getDoctrine()->getManager() );
  466.                     if (!$rc) {
  467.                         die('error updating document');
  468.                     }
  469.                     // generate the PDF sheet
  470.                     $parms = [];
  471.                     $documentBuilder->setParentController($this);
  472.                     $documentBuilder->setAccount($company->getAccount());
  473.                     $documentBuilder->setCompany($company);
  474.                     $documentBuilder->setDocument($document);
  475.                     $documentBuilder->build($parms);
  476.                 }
  477.                 
  478.                 // update config step in the company
  479.                 if ($company->__get('configurationStep')==null || $company->__get('configurationStep')<$step+1) {
  480.                     $company->__set('configurationStep'$step+1);
  481.                     $rc $company->save$this->getDoctrine()->getManager() );
  482.                     if (!$rc) {
  483.                         die('error updating company');
  484.                     }
  485.                 }
  486.             
  487.             } else if ($step==$CONFIG_STEPS['cookies']) {
  488.             
  489.                 //dump('cookies');
  490.                 // save cookies acceptance
  491.                 $settingsValue $this->timeCalc->currentGmDateTimeFull.';u'.$this->getUser()->getId();
  492.                 $this->settingsLoader->updateSetting('config-step''cookies'$settingsValue$companyfalse);
  493.                 // update config step in the company
  494.                 if ($company->__get('configurationStep')==null || $company->__get('configurationStep')<$step+1) {
  495.                     $company->__set('configurationStep'$step+1);
  496.                     $rc $company->save$this->getDoctrine()->getManager() );
  497.                     if (!$rc) {
  498.                         die('error updating company');
  499.                     }
  500.                 }
  501.             
  502.             } else if ($step==$CONFIG_STEPS['licenseType']) {
  503.             
  504.                 //dump('licenseType');
  505.                 // save license type
  506.                 $company->__set('licenseType'$data['licenseType']);
  507.                 if ($company->__get('configurationStep')==null || $company->__get('configurationStep')<$step+1) {
  508.                     $company->__set('configurationStep'$step+1);
  509.                 }
  510.                 $rc $company->save$this->getDoctrine()->getManager() );
  511.                 if (!$rc) {
  512.                     die('error updating company');
  513.                 }
  514.             
  515.             } else if ($step==$CONFIG_STEPS['settings']) {
  516.             
  517.                 // copy global parameters (day titles, etc.) to this company
  518.                 if ($company->__get('localParamsChanged')!=true) {
  519.                     //dump('copyGlobalParametersToLocal');
  520.                     $this->dataSynchronizer->copyGlobalParametersToLocal($companyfalse); //JNOTE: false at end, since we don't have day assignments yet
  521.                 }
  522.                 //dump('settings');
  523.                 //dump($data); //die();
  524.                 // save protocol fields
  525.                 $company->__set('protocolCreator'$data['coProtocolCreator']);
  526.                 $company->__set('protocolApprover'$data['coProtocolApprover']);
  527.                 $company->__set('localParamsChanged'true); //_
  528.                 if ($company->__get('configurationStep')==null || $company->__get('configurationStep')<$step+1) {
  529.                     $company->__set('configurationStep'$step+1);
  530.                 }
  531.                 $rc $company->save$this->getDoctrine()->getManager() );
  532.                 if (!$rc) {
  533.                     die('error updating company');
  534.                 }
  535.                 
  536.                 //die();
  537.                 // save settings
  538.                 $changesMade = [];
  539.                 foreach($data as $settingName=>$settingValue) {
  540.                     if (in_array($settingName, ['coProtocolCreator''coProtocolApprover'])) continue;
  541.                     
  542.                     $settingNameArr explode('-'$settingName);
  543.                     $this->settingsLoader->updateSetting($settingNameArr[0], $settingNameArr[1], $settingValue$companytrue); // overwrite with later value
  544.                         
  545.                 }
  546.                 //JNOTE: add logging
  547.             } else if ($step==$CONFIG_STEPS['finish']) {
  548.                 $company->__setDateTime('firstLoginConfigAt'$this->timeCalc->currentDateTime);
  549.                 if ($company->__get('configurationStep')==null || $company->__get('configurationStep')<$step+1) {
  550.                     $company->__set('configurationStep'$step+1);
  551.                 }
  552.                 $rc $company->save$this->getDoctrine()->getManager(), false );
  553.                 if (!$rc) {
  554.                     die('error updating company');
  555.                 }
  556.                 
  557.             }
  558.         } else if ($type=='keepAlive') {
  559.             // nothing is needed here
  560.             $this->session->set('last-user-action-time'time());
  561.         } else { //T
  562.             
  563.             // error
  564.             $result['msg'] = $this->translator->trans('message.genericError', array(), 'general');
  565.             $result['info'] = 'bad action';
  566.             return new Response($this->jsonEncoder(array(
  567.                 'result' => $result,
  568.             )));
  569.                     
  570.         }
  571.         $result['success'] = true;
  572.         return new Response($this->jsonEncoder(array(
  573.             'result' => $result,
  574.             'data' => $returnData,            
  575.         )));
  576.     }
  577.     /**
  578.      * Called periodically during page open
  579.      * @Route("/general/check-session", name="general.session", methods={"POST"})
  580.      */
  581.     public function general_check_session_action(Request $request)
  582.     {
  583.         $rc $this->handleControllerAction($request'general''check-session'nulltrue); //
  584.         if ($rc!==true && $this->redirectRoute!=null) { //T
  585.             die('no access');
  586.             $result['info'] = 'no access';
  587.             $result['url'] = $this->router->generate($this->redirectRoute);
  588.             return new Response($this->jsonEncoder(array(
  589.                 'result' => $result,
  590.             )));
  591.         }
  592.     
  593.         $returnData = [
  594.             'currentTimeUx' => time(),
  595.             'lastUserActionTimeUx' => $this->session->get('last-user-action-time'), // last user action time
  596.             'newEmails' => false,
  597.             'session_id' => session_id(),
  598.         ];
  599.         
  600.         // check if there are new messages
  601.         $this->messageHelper->getNewMessage($returnData['newEmails'], $this->getUser());
  602.         //sleep(5);
  603.         $result['success'] = true;
  604.         return new Response($this->jsonEncoder(array(
  605.             'result' => $result,
  606.             'data' => $returnData,            
  607.         )));
  608.     }
  609.     /**
  610.      * Check to see at certain times, e.g. if logout expiry warning popup can be opened
  611.      * @Route("/general/check-status", name="general.status", methods={"POST"})
  612.      */
  613.     public function general_check_status_action(Request $request)
  614.     {
  615.         $rc $this->handleControllerAction($request'general''check-session'nulltrue); //
  616.         if ($rc!==true && $this->redirectRoute!=null) { //T
  617.             //die('no access');
  618.             $result['info'] = 'no access';
  619.             $result['url'] = $this->router->generate($this->redirectRoute);
  620.             return new Response($this->jsonEncoder(array(
  621.                 'result' => $result,
  622.             )));
  623.         }
  624.     
  625.         $returnData = [
  626.             'currentTimeUx' => time(),
  627.             'lastUserActionTimeUx' => $this->session->get('last-user-action-time'), // last user action time
  628.         ];
  629.         
  630.         //sleep(5);
  631.         $result['success'] = true;
  632.         return new Response($this->jsonEncoder(array(
  633.             'result' => $result,
  634.             'data' => $returnData,            
  635.         )));
  636.     }
  637.     // ******************************************
  638.     //     REGISTRATION
  639.     // ******************************************
  640.     /**
  641.      * @Route("/register", name="b_register")
  642.      */
  643.     public function register(Request $request, \Twig_Environment $twigEmailNotifier $email)
  644.     {
  645.     
  646.         //die('');
  647.     
  648.         //dump($request);
  649.         //dump($this->getUser());
  650.             
  651.         //$this->handlePageOpen($request, 'tofu');
  652.         //$tofuHTML = $tofuTemplate->renderBlock('main', array());
  653.         $this->setLanguageAndLocale($request);
  654.                     
  655.         $initialMessage '';
  656.         $initialMessageType '';
  657.         $initialData = [
  658.             "companyName" => '',
  659.             "username" => '',
  660.             //"plainPassword" => '',
  661.             "email" => '',
  662.             "emailForNotifications" => '',
  663.             "phone" => '',
  664.             "country" => '',
  665.             "city" => '',
  666.             "address" => '',
  667.             "postalCode" => '',
  668.         ];
  669.         if ($this->session->get('reg-form-error')!=null) {
  670.             $initialMessage $this->session->get('reg-form-error');
  671.             $initialMessage "showMsg('$initialMessage', false);";
  672.             $initialMessageType 'error';
  673.             
  674.             $initialData $this->session->get('reg-form-data');
  675.             $this->session->set('reg-form-error'null);
  676.             $this->session->set('reg-form-data'null);
  677.             //dump($initialMessage);
  678.             //dump($initialData);
  679.         }
  680.         /*$email->sendEmail('registration', 
  681.             $this->translator->trans('registrationEmail.subject', array(), 'emails'),
  682.             $this->translator->trans('registrationEmail.body', array(), 'emails'),
  683.             [
  684.                 'FirstName' => 'Joe',
  685.                 'LoginLink' => $_SERVER['APP_HOME_URL'].'/login',
  686.                 'SiteName' => str_replace(['http://', '/'], '', $_SERVER['APP_HOME_URL']),
  687.             ], [
  688.                 'janusz@viewpointmultimedia.com' => 'janusz at vpmm',
  689.             ]
  690.         );
  691.         //die();*/
  692.         $data = [];
  693.         if ($this->session->get('reg-form-data')!=null) {
  694.             $data $this->session->get('reg-form-data');
  695.         }
  696.         // countries
  697.         $countriesArray $this->formsHelper->getCountries($this->currentLanguage);
  698.         // cities
  699.         $citiesArray $this->formsHelper->getCities($this->mainCountry);
  700.         // language strings
  701.         $allMessages $this->translator->getCatalogue()->all();
  702.         $languageStrings['general'] = $allMessages['general'];
  703.         $languageStrings['registration'] = $allMessages['registration'];
  704.         
  705.         $response = new Response();
  706.                 
  707.         return $this->render('frontend/register.html.twig', array(
  708.             'data'         => $data,
  709.             'page_title' => $this->translator->trans('application.name', array(), 'general').' - '.
  710.                             $this->translator->trans('page.title', array(), 'register'),
  711.             'initialMessage' => $initialMessage,
  712.             'initialMessageType' => $initialMessageType,
  713.             'data' => $initialData,
  714.             'countriesArray' => $countriesArray,
  715.             'citiesArray' => $citiesArray,
  716.             'languageStrings_js' => json_encode($languageStrings),
  717.             'currentLanguage' => $this->currentLanguage,
  718.         ), $response);        
  719.     }    
  720.     
  721.     /**
  722.      * @Route("/register/process", name="b_register_process")
  723.      */
  724.     public function register_process(Request $request, \Twig_Environment $twigUserPasswordEncoderInterface $passwordEncoder,
  725.                                      EmailNotifier $email)
  726.     {
  727.     
  728.         $log false;
  729.     
  730.         //die('');
  731.     
  732.         //dump($request);
  733.         //dump($this->getUser());
  734.         //die();    
  735.         $this->setLanguageAndLocale($request);
  736.         
  737.         $data = array(
  738.             'companyName' => $request->request->get('company'),
  739.             'username' => $request->request->get('username'),
  740.             'plainPassword' => $request->request->get('plainPassword'),
  741.             'email' => $request->request->get('email'),
  742.             'emailForNotifications' => $request->request->get('emailForNotifications'),
  743.             'phone' => $request->request->get('phone'),
  744.             'country' => $request->request->get('country'),
  745.             'city' => $request->request->get('city'),
  746.             //'city2' => $request->request->get('city2'),
  747.             'address' => $request->request->get('address'),
  748.             'postalCode' => $request->request->get('postalCode'),
  749.         );
  750.         if ($logdump('data'$data);
  751.         //die();
  752.         // check CSRF token
  753.         $token $request->request->get('_csrf_token');
  754.         if (!$this->isCsrfTokenValid('register'$token)) {
  755.             $this->session->set('reg-form-error'$this->translator->trans('message.genericError', array(), 'general')); //JNOTE
  756.             $this->session->set('reg-form-data'$data);
  757.             if ($logdd('invalid csrf token');
  758.             return $this->redirectToRoute('b_register');
  759.         }                
  760.         $em $this->getDoctrine()->getManager();
  761.         // load system user
  762.         $systemUsers $this->getDoctrine()->getRepository(User::class)->findById($_SERVER['APP_SYSTEM_USER_ID']);
  763.         $systemUser $systemUsers[0];
  764.         //dump($systemUsers, $systemUser); die();
  765.         // check that a company with this name doesn't already exist
  766.         $duplicateCompanies $this->getDoctrine()
  767.                                     ->getRepository(Company::class)
  768.                                     ->findBy([
  769.                                         'name' => $data['companyName'],
  770.                                         'deleted' => 0,
  771.                                     ]);
  772.         if ($duplicateCompanies!=null) { //T
  773.             foreach($duplicateCompanies as $duplicateCompany) {
  774.                 // there is a company with same name, return error
  775.                 $this->session->set('reg-form-error'$this->translator->trans('message.companyNameExists', array(), 'registration'));
  776.                 $this->session->set('reg-form-data'$data);
  777.                 if ($logdd('dup company name');
  778.                 return $this->redirectToRoute('b_register');
  779.             }
  780.         } //
  781.         // check that this username doesn't already exist
  782.         $duplicateUsers $this->getDoctrine()
  783.                                     ->getRepository(User::class)
  784.                                     ->findBy([
  785.                                         'email' => $data['email'],
  786.                                         'deleted' => 0,
  787.                                     ]);
  788.         if ($duplicateUsers!=null) { //T
  789.             //dump('duplicateUsers', $duplicateUsers); //die();
  790.             foreach($duplicateUsers as $duplicateUser) {
  791.                 // there is a user with same email address, return error
  792.                 $this->session->set('reg-form-error'$this->translator->trans('message.emailAddressExists', array(), 'registration'));
  793.                 $this->session->set('reg-form-data'$data);
  794.                 //dd($this->translator->trans('message.emailAddressExists', array(), 'registration'));
  795.                 if ($logdd('dup email addr');
  796.                 return $this->redirectToRoute('b_register');
  797.             }
  798.         } //
  799.         //die('---');
  800.         // create account
  801.         $account = new Account();
  802.         $account->__set('country'$data['country']);
  803.         $account->__set('createdBy'$systemUser);
  804.         $account->__set('type'AccountTypeEnum::REGULAR); //COM-817
  805.         
  806.         if (!$account->save($em)) {
  807.             //die('account save');
  808.             $this->session->set('reg-form-error'$this->translator->trans('message.genericError', array(), 'general'));
  809.             $this->session->set('reg-form-data'$data);
  810.             if ($logdd('account save error');
  811.             return $this->redirectToRoute('b_register');
  812.         }        
  813.         // NOTE: initial idea was to add logic for payment, e.g. company and user shouldn't be created until money is paid;
  814.         // but this can't work like this - we need a user to place an order for a company; a company must belong to an account, etc.
  815.         // create company
  816.         $company = new Company();
  817.         $company->__set('account'$account);
  818.         $company->__set('name'$data['companyName']);
  819.         $company->__set('email'$data['emailForNotifications']);
  820.         $company->__set('phone'$data['phone']);
  821.         $company->__set('country'$data['country']);
  822.         $company->__set('adminType'CompanyAdminTypeEnum::CUSTOMER_TEST); // COM-479
  823.         //if ($data['country']=='hu') {
  824.             $company->__set('city'$data['city']);
  825.         //} else {
  826.         //    $company->__set('city', $data['city2']);
  827.         //}
  828.         $company->__set('address'$data['address']);
  829.         $company->__set('postalCode'$data['postalCode']);
  830.         ///$company->__set('status', 'created'); //JNOTE
  831.         $company->__set('createdBy'$systemUser);
  832.         
  833.         $company->__set('isActive'false); // inactive by default (can log in only to configure the account)
  834.         $company->__set('configurationStep'0); // start of configuration process
  835.         if (!$company->save($em)) {
  836.             //die('company save');
  837.             $this->session->set('reg-form-error'$this->translator->trans('message.genericError', array(), 'general'));
  838.             $this->session->set('reg-form-data'$data);
  839.             if ($logdd('company save error');
  840.             return $this->redirectToRoute('b_register');
  841.         }        
  842.         // create user
  843.         $user = new User();
  844.         $user->__set('account'$account);
  845.         $user->__set('username'$data['username']);
  846.         $user->__set('password'$passwordEncoder->encodePassword($user$data['plainPassword']) );
  847.         $user->__set('roles'UserRoleEnum::ROLE_ACCOUNT_OWNER);
  848.         $user->__set('email'$data['email']);
  849.         $user->__set('currentCompanyViewed'$company); // set company to the one just created (default - can be changed later)
  850.         $user->__set('createdBy'$systemUser);
  851.         if (!$user->save($em)) {
  852.             //die('user save');
  853.             $this->session->set('reg-form-error'$this->translator->trans('message.genericError', array(), 'general'));
  854.             $this->session->set('reg-form-data'$data);
  855.             if ($logdd('user save error');
  856.             return $this->redirectToRoute('b_register');
  857.         }   
  858.         // update the account with the user and company created above
  859.         $accounts $this->getDoctrine()->getRepository(Account::class)->findById($account->getId());
  860.         if ($accounts==null) {
  861.             //die('error getting account');
  862.             $this->session->set('reg-form-error'$this->translator->trans('message.genericError', array(), 'general'));
  863.             $this->session->set('reg-form-data'$data);
  864.             if ($logdd('account read error');
  865.             return $this->redirectToRoute('b_register');
  866.         }  
  867.         //dump($accounts);
  868.         
  869.         $accounts[0]->__set('primaryCompany'$company);
  870.         $accounts[0]->__set('primaryUser'$user);
  871.         //$accounts[0]->__set('updatedBy', $systemUser);
  872.         //dump('------', $accounts[0], $company, $user);
  873.         if (!$accounts[0]->save($emfalse)) {
  874.             // ignore error
  875.             if ($logdd('account update error');
  876.             die('error updating account');
  877.         }  
  878.         // send email welcoming the person, and telling him to log into his account to configure it (if not already done so)
  879.         if (0) {
  880.             $email->sendEmail('registration'
  881.                 $this->translator->trans('registrationEmail.subject', array(), 'emails'),
  882.                 $this->translator->trans('registrationEmail.body', array(), 'emails'),
  883.                 [
  884.                     'FirstName' => 'Joe',
  885.                     'LoginLink' => $_SERVER['APP_HOME_URL'].'/login',
  886.                     'SiteName' => str_replace(['http://''/'], ''$_SERVER['APP_HOME_URL']),
  887.                 ], [
  888.                     $data['emailForNotifications'] => $data['companyName'],
  889.                 ]
  890.             );
  891.             if ($log) ('after email send');
  892.         }
  893.         
  894.         if ($logdd('end of reg process');
  895.         //dd('---');
  896.         return $this->redirectToRoute('b_register_ack');
  897.     }    
  898.     /**
  899.      * @Route("/register-thankyou", name="b_register_ack")
  900.      */
  901.     public function register_ack(Request $request, \Twig_Environment $twig)
  902.     {
  903.     
  904.         //dump($request);
  905.         //dump($this->getUser());
  906.             
  907.         //$this->handlePageOpen($request, 'tofu');
  908.         $this->setLanguageAndLocale($request);
  909.                     
  910.         $initialMessage $this->translator->trans('info.registrationAckMessage', array(), 'registration');
  911.         $initialMessageType '';
  912.         $response = new Response();
  913.                 
  914.         return $this->render('frontend/register-ack.html.twig', array(
  915.             'page_title' => $this->translator->trans('application.name', array(), 'general').' - '.
  916.                             $this->translator->trans('page.title', array(), 'register'),
  917.             'initialMessage' => $initialMessage,
  918.             'initialMessageType' => $initialMessageType,
  919.         ), $response);        
  920.     }    
  921.     // ******************************************
  922.     //     PASSWORD RESET
  923.     // ******************************************
  924.     /**
  925.      * @Route("/pwdreset", name="b_password_reset.pg")
  926.      */
  927.     public function password_reset_pg(Request $request, \Twig_Environment $twig)
  928.     {
  929.         //dump($request);
  930.         //dump($this->getUser());
  931.         //$this->handlePageOpen($request, 'tofu');
  932.         //$tofuHTML = $tofuTemplate->renderBlock('main', array());
  933.         $this->setLanguageAndLocale($request);
  934.         $initialMessage '';
  935.         $initialMessageType '';
  936.         if ($this->session->get('pwdreset-form-error')!=null) {
  937.             $initialMessage $this->session->get('pwdreset-form-error');
  938.             $initialMessageType 'error';
  939.         }
  940.         $data = [];
  941.         if ($this->session->get('pwdreset-form-data')!=null) {
  942.             $data $this->session->get('pwdreset-form-data');
  943.         }
  944.         // language strings
  945.         $allMessages $this->translator->getCatalogue()->all();
  946.         $languageStrings['general'] = $allMessages['general'];
  947.         $languageStrings['password-reset'] = $allMessages['password-reset'];
  948.         $response = new Response();
  949.         return $this->render('frontend/password-reset-request.html.twig', array(
  950.             'data'         => $data,
  951.             'page_title' => $this->translator->trans('application.name', array(), 'general').' - '.
  952.                 $this->translator->trans('page.title', array(), 'register'),
  953.             'initialMessage' => $initialMessage,
  954.             'initialMessageType' => $initialMessageType,
  955.             'languageStrings_js' => json_encode($languageStrings),
  956.         ), $response);
  957.     }
  958.     /**
  959.      * @Route("/pwdreset/request/process", name="b_pwdreset_request_process.action", methods={"POST"})
  960.      */
  961.     public function pwdreset_request_process_action(Request $requestUserPasswordEncoderInterface $passwordEncoder,
  962.                                                     EmailNotifier $email)
  963.     {
  964.         //die('emailing disabled temporarily');
  965.         //dump($request);
  966.         //dump($this->getUser());
  967.         //die('pwdreset_request_process_action');
  968.         // check CSRF token
  969.         $token $request->request->get('_csrf_token');
  970.         if (!$this->isCsrfTokenValid('password-reset'$token)) {
  971.         
  972.             $this->session->set('pwdreset-form-error''error');
  973.             $this->session->set('pwdreset-form-data', []);
  974.             // JNOTE: message!!!!
  975.             return $this->redirectToRoute('b_password_reset.pg');
  976.         }
  977.         $data = array(
  978.             //'username' => $request->request->get('username'),
  979.             'email' => $request->request->get('email'),
  980.         );
  981.         //dump($data, $token);
  982.         //die();
  983.         $em $this->getDoctrine()->getManager();
  984.         // load system user
  985.         $systemUsers $this->getDoctrine()->getRepository(User::class)->findById($_SERVER['APP_SYSTEM_USER_ID']);
  986.         $systemUser $systemUsers[0];
  987.         // find the user for this request
  988.         $foundUser $this->getDoctrine()
  989.             ->getRepository(User::class)
  990.             ->findOneBy([
  991.                          'email' => $data['email'],
  992.                          'deleted' => 0,
  993.                      ]);
  994.         if ($foundUser==null) { //T
  995.             // normally, this should be a reported error
  996.             // BUT it can happen that this page is used to test out if email addresses are in this system
  997.             // to make this much less useful, report to the user that everything went ok        
  998.         
  999.             return $this->redirectToRoute('b_pwdreset_request_ack.pg');
  1000.         
  1001.         }
  1002.         //dump('$foundUser', $foundUser);
  1003.         //die('---');
  1004.         // create password reset link
  1005.         $pwdResetlink = new Link();
  1006.         $pwdResetlink->__set('company'null);
  1007.         $pwdResetlink->__set('type'0); //JNOTE
  1008.         $pwdResetlink->generateCode();
  1009.         $pwdResetlink->__set('relatedUser'$foundUser);
  1010.         $pwdResetlink->__set('createdBy'$systemUser);
  1011.         //dump('$pwdResetlink', $pwdResetlink);
  1012.         if (!$pwdResetlink->save($em)) { //T
  1013.         
  1014.             $this->session->set('page-title',   ['password-reset''page.title.error']);
  1015.             $this->session->set('page-content', ['general''message.genericError']);
  1016.             return $this->redirectToRoute('b_error.pg');
  1017.             
  1018.         }
  1019.         // send email with the password reset link
  1020.         if (1) {
  1021.         
  1022.             // LINK SECURITY
  1023.             // We use two separate strings, to be sure that we're secure and unique; both are binary strings, encoded using md5
  1024.             // - pwdResetCode: unique code, the main thing looked up
  1025.             // - encodedEmailAddr: related user's email address, also encoded using md5
  1026.             // Link verification is two-fold:
  1027.             // - find a link with the matching pwdResetCode
  1028.             // - confirm that the user associated with the link has the same email address (hashed using md5) 
  1029.             
  1030.             $linkUrl $_SERVER['APP_HOME_URL'];
  1031.             $linkUrl .= $this->router->generate('b_pwdreset_selectNewPassword.pg', [
  1032.                 'pwdResetCode' => $pwdResetlink->getCode(),
  1033.                 'encodedEmailAddr' => md5($data['email']),
  1034.             ]);
  1035.             //dump('linkUrl', $linkUrl); die();
  1036.             
  1037.             $userName $foundUser->getName();
  1038.             if ($userName==''$userName $foundUser->getUsername();
  1039.         
  1040.             $email->sendEmail('passwordReset'
  1041.                 $this->translator->trans('passwordResetEmail.subject', array(), 'emails'),
  1042.                 $this->translator->trans('passwordResetEmail.body', array(), 'emails'),
  1043.                 [
  1044.                     'Name' => $userName,
  1045.                     'CodeBeforeLink' => "<a href='$linkUrl'>",
  1046.                     'CodeAfterLink' => "</a>",
  1047.                     'LinkAddress' => $linkUrl,
  1048.                     'SiteName' => str_replace(['https://''http://''/'], ''$_SERVER['APP_HOME_URL']),
  1049.                 ], [
  1050.                     $data['email'] => $userName,
  1051.                 ]
  1052.             );
  1053.             //die('=====');
  1054.         }
  1055.         //die('--');
  1056.         return $this->redirectToRoute('b_pwdreset_request_ack.pg');
  1057.     }
  1058.     /**
  1059.      * @Route("/pwdreset/request/thank-you", name="b_pwdreset_request_ack.pg")
  1060.      */
  1061.     public function pwdreset_request_ack_pg(Request $request, \Twig_Environment $twig)
  1062.     {
  1063.         //dump($request);
  1064.         //dump($this->getUser());
  1065.         //$this->handlePageOpen($request, 'tofu');
  1066.         $this->setLanguageAndLocale($request);
  1067.         $initialMessage '';
  1068.         $initialMessageType '';
  1069.         $initialMessage $this->translator->trans('message.linkSent', array(), 'password-reset');
  1070.         $initialMessageType '';
  1071.         $response = new Response();
  1072.         return $this->render('frontend/password-reset-request-ack.html.twig', array(
  1073.             'page_title' => $this->translator->trans('application.name', array(), 'general').' - '.
  1074.                 $this->translator->trans('page.title.linkSent', array(), 'password-reset'),
  1075.             'initialMessage' => $initialMessage,
  1076.             'initialMessageType' => $initialMessageType,
  1077.         ), $response);
  1078.     }
  1079.     /**
  1080.      * @Route("/pwdreset/act/{pwdResetCode}/{encodedEmailAddr}", name="b_pwdreset_selectNewPassword.pg")
  1081.      */
  1082.     public function b_pwdreset_selectNewPassword_pg(Request $request$pwdResetCode$encodedEmailAddr, \Twig_Environment $twig)
  1083.     {
  1084.         //dump('b_pwdreset_selectNewPassword_pg', $request, $pwdResetCode);
  1085.         //dump($this->getUser());
  1086.         //die('new pass sel');
  1087.         //$this->handlePageOpen($request, 'tofu');
  1088.         $this->setLanguageAndLocale($request);
  1089.         $pwdResetlink null;
  1090.         $relatedUser null;
  1091.         // validate the link
  1092.         $rc $this->validatePwdResetLink($pwdResetCode$encodedEmailAddr,
  1093.                                           $pwdResetlink$relatedUser);
  1094.         if ($rc!==true) { //T
  1095.             // if $rc is not true, it has the proper redirect return Response
  1096.             return $rc;
  1097.         } //T
  1098.         // language strings
  1099.         $allMessages $this->translator->getCatalogue()->all();
  1100.         $languageStrings['general'] = $allMessages['general'];
  1101.         $languageStrings['password-reset'] = $allMessages['password-reset'];
  1102.         $response = new Response();
  1103.         return $this->render('frontend/password-reset.html.twig', array(
  1104.             'page_title' => $this->translator->trans('application.name', array(), 'general').' - '.
  1105.                 $this->translator->trans('page.title', array(), 'register'),
  1106.             'initialMessage' => ''//$initialMessage,
  1107.             'initialMessageType' => ''//$initialMessageType,
  1108.             'languageStrings_js' => json_encode($languageStrings),
  1109.             'c1' => $pwdResetCode,
  1110.             'c2' => $encodedEmailAddr,
  1111.         ), $response);
  1112.     }
  1113.     /**
  1114.      * @Route("/pwdreset/sel/process", name="b_pwdreset_selectNewPassword.action", methods={"POST"})
  1115.      */
  1116.     public function b_pwdreset_selectNewPassword_action(Request $requestUserPasswordEncoderInterface $passwordEncoder)
  1117.     {
  1118.         //dump($request);
  1119.         //dump($this->getUser());
  1120.         //die('b_pwdreset_selectNewPassword_action');
  1121.         // check CSRF token
  1122.         $token $request->request->get('_csrf_token');
  1123.         if (!$this->isCsrfTokenValid('password-reset2'$token)) {
  1124.             die('invalid token');
  1125.             return $this->redirectToRoute('b_register');
  1126.         }
  1127.         $data = [
  1128.             'plainPassword' => $request->request->get('plainPassword'),
  1129.             'plainPassword2' => $request->request->get('plainPassword2'),
  1130.             'pwdResetCode' => $request->request->get('c1'),
  1131.             'encodedEmailAddr' => $request->request->get('c2'),
  1132.         ];
  1133.         //dump($data); //, $token);
  1134.         //die();
  1135.         if ($data['plainPassword'] != $data['plainPassword2']) {
  1136.             die('passwords do not match');
  1137.         }
  1138.         $em $this->getDoctrine()->getManager();
  1139.         
  1140.         $pwdResetlink null;
  1141.         $relatedUser null;
  1142.         // validate the link
  1143.         $rc $this->validatePwdResetLink($data['pwdResetCode'], $data['encodedEmailAddr'],
  1144.                                           $pwdResetlink$relatedUser);
  1145.         if ($rc!==true) { //T
  1146.             // if $rc is not true, it has the proper redirect return Response
  1147.             return $rc;
  1148.         } //T
  1149.         // load system user
  1150.         $systemUsers $this->getDoctrine()->getRepository(User::class)->findById($_SERVER['APP_SYSTEM_USER_ID']);
  1151.         $systemUser $systemUsers[0];
  1152.         // change the user password
  1153.         //dump('relatedUser 1', $relatedUser);
  1154.         $relatedUser->__set('password'$passwordEncoder->encodePassword($relatedUser$data['plainPassword']) );
  1155.         $relatedUser->__set('updatedBy'$systemUser);
  1156.         //dump('relatedUser 2', $relatedUser);
  1157.         if (!$relatedUser->save($em)) { //T
  1158.             // email address hash in email not the same as in the db, send to error page        
  1159.             $this->session->set('page-title',   ['password-reset''page.title.error']);
  1160.             $this->session->set('page-content', ['general''message.genericError']);
  1161.             return $this->redirectToRoute('b_error.pg');
  1162.         }
  1163.         // invalidate the link
  1164.         if (1) {
  1165.             // mark the link as deleted
  1166.             $pwdResetlink->setDeleted(true);
  1167.             
  1168.             if (!$pwdResetlink->save($em)) {
  1169.                 die('error marking link as deleted');
  1170.             }
  1171.         } else {
  1172.         
  1173.             // delete the link completely
  1174.             
  1175.         }
  1176.         
  1177.         //die('===');
  1178.         
  1179.         return $this->redirectToRoute('b_pwdreset_selectNewPassword_ack.pg');
  1180.     }
  1181.     /**
  1182.      * @Route("/pwdreset/sel/thank-you", name="b_pwdreset_selectNewPassword_ack.pg")
  1183.      */
  1184.     public function b_pwdreset_selectNewPassword_ack_pg(Request $request, \Twig_Environment $twig)
  1185.     {
  1186.         //dump($request);
  1187.         //dump($this->getUser());
  1188.         //$this->handlePageOpen($request, 'tofu');
  1189.         $this->setLanguageAndLocale($request);
  1190.         $initialMessage '';
  1191.         $initialMessageType '';
  1192.         $response = new Response();
  1193.         return $this->render('frontend/password-reset-ack.html.twig', array(
  1194.             'page_title' => $this->translator->trans('application.name', array(), 'general').' - '.
  1195.                 $this->translator->trans('page.title', array(), 'register'),
  1196.             'initialMessage' => $initialMessage,
  1197.             'initialMessageType' => $initialMessageType,
  1198.         ), $response);
  1199.     }
  1200.     
  1201.     private function validatePwdResetLink($pwdResetCode$encodedEmailAddr,
  1202.                                           &$pwdResetlink, &$relatedUser) {
  1203.     
  1204.         // load the link
  1205.         $pwdResetlink $this->getDoctrine()->getRepository(Link::class)->findOneByCode($pwdResetCode);
  1206.         //dump('pwdResetlink', $pwdResetlink);
  1207.         if ($pwdResetlink==null) { //T
  1208.             // no link found, send to error page        
  1209.             $this->session->set('page-title',   ['password-reset''page.title.error']);
  1210.             $this->session->set('page-content', ['password-reset''message.invalidLink']);
  1211.             return $this->redirectToRoute('b_error.pg');
  1212.             
  1213.         } else if ($pwdResetlink->getDeleted()==true) { //T
  1214.         
  1215.             // link already used, send to error page    
  1216.             $this->session->set('page-title',   ['password-reset''page.title.linkAlreadyUsed']);
  1217.             $this->session->set('page-content', ['password-reset''message.linkAlreadyUsed']);
  1218.             return $this->redirectToRoute('b_error.pg');
  1219.         
  1220.         }
  1221.         
  1222.         // check for link expiry
  1223.         $this->timeCalc->refreshTimeZone();
  1224.         $linkAgeInMinutes $this->timeCalc->getMinutesDifferenceSimple($this->timeCalc->currentDateTime$pwdResetlink->__getDateTimeFormatted('createdAt'));
  1225.         //dump(date_default_timezone_get());
  1226.         //dump("O: ".$pwdResetlink->__getDateTimeFormatted('createdAt').", N:".$this->timeCalc->currentDateTime.", diff: $linkAgeInMinutes min");
  1227.         //dump(date("Y-m-d H:i")); die();
  1228.         //dump('linkAgeInMinutes', $linkAgeInMinutes); die();
  1229.         if ($linkAgeInMinutes 60) { //T
  1230.             // link expired, send to error page    
  1231.             $this->session->set('page-title',   ['password-reset''page.title.linkExpired']);
  1232.             $this->session->set('page-content', ['password-reset''message.linkExpired']);
  1233.             return $this->redirectToRoute('b_error.pg');
  1234.         
  1235.         }
  1236.         //die('==');
  1237.         // get the user connected to this link
  1238.         $relatedUser $pwdResetlink->__get('relatedUser');
  1239.         //dump('relatedUser', $relatedUser);
  1240.         if ($relatedUser==null) {
  1241.             // no link found, send to error page        
  1242.             $this->session->set('page-title',   ['password-reset''page.title.error']);
  1243.             $this->session->set('page-content', ['password-reset''message.invalidLink']);
  1244.             return $this->redirectToRoute('b_error.pg');
  1245.         }
  1246.         
  1247.         $relatedUserEncodedEmail md5($relatedUser->getEmail());
  1248.         if (!hash_equals($relatedUserEncodedEmail$encodedEmailAddr)) { //T
  1249.             // email address hash in email not the same as in the db, send to error page        
  1250.             $this->session->set('page-title',   ['password-reset''page.title.error']);
  1251.             $this->session->set('page-content', ['password-reset''message.invalidLink']);
  1252.             return $this->redirectToRoute('b_error.pg');
  1253.         } else {
  1254.             //dump("hashes same: db[$relatedUserEncodedEmail] link[$encodedEmailAddr]");
  1255.         }
  1256.         
  1257.         return true;
  1258.     }
  1259.     // ******************************************
  1260.     //     MISCELLANEOUS
  1261.     // ******************************************
  1262.     /**
  1263.      * @Route("/language/{lang}", name="language.change.action", methods={"POST"})
  1264.      */
  1265.     public function language_change_action(Request $request$lang)
  1266.     {
  1267.     
  1268.         //dump($request);
  1269.         $result $this->getDefaultAjaxReturnRec();
  1270.         $this->session->set('language'$lang);
  1271.         /*$rc = $this->handleControllerAction($request, $this->module, 'edit', $entities[0], true);
  1272.         if ($rc!==true) {
  1273.             $result['error'] = 'no-access';
  1274.             $result['url'] = $this->redirectRoute;
  1275.             return new Response($this->jsonEncoder($result));
  1276.         }*/
  1277.         $result['success'] = true;
  1278.         return new Response($this->jsonEncoder(array(
  1279.             'result' => $result,
  1280.         )));
  1281.         
  1282.     }         
  1283.     
  1284.     /**
  1285.      * @Route("/driver-vehicle/filter/{driverVehicleId}", name="driver-vehicle-filter.action", methods={"POST"})
  1286.      */
  1287.     public function filter_action(Request $request$driverVehicleId)
  1288.     {
  1289.         $result $this->getDefaultAjaxReturnRec();
  1290.         /*$rc = $this->handleControllerAction($request, $this->module, 'edit', $this->emptyEntity);
  1291.         if ($rc!==true) {
  1292.             return $this->redirectToRoute($this->redirectRoute);
  1293.         }*/
  1294.         if (substr($driverVehicleId01)=='V') {
  1295.             $this->session->set('selected-vehicle'substr($driverVehicleId1));
  1296.         } else {
  1297.             $this->session->set('selected-driver'$driverVehicleId);
  1298.         }
  1299.         //$this->session->set('selected-range', "$startDate;$endDate");
  1300.         
  1301.         $result['success'] = true;
  1302.         //dump($result); die();
  1303.         return new Response($this->jsonEncoder(array(
  1304.             'result' => $result,
  1305.         )));
  1306.     
  1307.     }
  1308.     /** COM-469
  1309.      * @Route("/message-reaction", name="message-reaction.action", methods={"POST"})
  1310.      */
  1311.     public function message_reaction_action(Request $request)
  1312.     {
  1313.         $result $this->getDefaultAjaxReturnRec();
  1314.         $rc $this->handleControllerAction($request'general''message-reaction'nulltrue); // COM-792: use 'message-reaction'
  1315.         if ($rc!==true) {
  1316.             die('no access');
  1317.         }
  1318.         $broadcastMessageId $request->request->get('brMessageId');
  1319.         $buttonAction $request->request->get('buttonAction');
  1320.         $dontShowAgain = (($request->request->get('dontShow') ?? 'false')=='true');
  1321.         //dump('message_reaction_action data', $broadcastMessageId, $buttonAction, $dontShowAgain);
  1322.         // load the message
  1323.         $broadcastMsgRepository $this->getDoctrine()->getRepository(BroadcastMessage::class);
  1324.         $broadcastMsg $broadcastMsgRepository->findOneById($broadcastMessageId);
  1325.         if ($broadcastMsg==null) {
  1326.             die();
  1327.         }
  1328.         // get the reaction
  1329.         if ($buttonAction=='install') {
  1330.             $reactionType BroadcastMessageReactionEnum::REQUEST_FUNCTION;
  1331.         } else if ($buttonAction=='skip') {
  1332.             if ($dontShowAgain) {
  1333.                 $reactionType BroadcastMessageReactionEnum::CLOSE_AND_HIDE;
  1334.             } else {
  1335.                 $reactionType BroadcastMessageReactionEnum::CLOSE;
  1336.             }
  1337.         } else {
  1338.             die();
  1339.         }
  1340.         // save the reaction to db
  1341.         $this->messageHelper->saveBroadcastMessageReaction($broadcastMsg$this->company$this->getUser(), $reactionType);
  1342.         // save the reaction into session variable, no need to show the popup again, until the next login
  1343.         $sessionVar $this->session->get('broadcast-msgs');
  1344.         if ($sessionVar==null) {
  1345.             $sessionVar = [
  1346.                 $broadcastMessageId => $reactionType,
  1347.             ];
  1348.         } else {
  1349.             $sessionVar[$broadcastMessageId] = $reactionType;
  1350.         }
  1351.         $this->session->set('broadcast-msgs'$sessionVar);
  1352.         //dump('sessionVar', $sessionVar);
  1353.         // send notification email, if the function was requested
  1354.         if (&&
  1355.             $reactionType==BroadcastMessageReactionEnum::REQUEST_FUNCTION &&
  1356.             isset($_SERVER["APP_COMPASS_NOTIFICATION_EMAIL_ADDRS"])) {
  1357.             
  1358.             $this->emails->sendEmail('compass-notification'
  1359.                 $this->translator->trans('notification.featureRequested.subject', array(), 'emails'),
  1360.                 $this->translator->trans('notification.featureRequested.body', array(), 'emails'),
  1361.                 [
  1362.                     'CompanyName' => $this->company->getName(),
  1363.                     'FeatureName' => 'Statistics Module',
  1364.                     'UsersName' => $this->getUser()->getName(),
  1365.                 ], null
  1366.             );
  1367.         }
  1368.         // return
  1369.         $result['success'] = true;
  1370.         //dump($result); die();
  1371.         return new Response($this->jsonEncoder(array(
  1372.             'result' => $result,
  1373.         )));
  1374.     
  1375.     }
  1376.     /** COM-695
  1377.      * @Route("/system-tip-action", name="system-tip-action.action", methods={"POST"})
  1378.      */
  1379.     public function system_tip_action_action(Request $request)
  1380.     {
  1381.         $result $this->getDefaultAjaxReturnRec();
  1382.         $rc $this->handleControllerAction($request'general''list'nulltrue);
  1383.         if ($rc!==true) {
  1384.             die('no access');
  1385.         }
  1386.         $systemTipIds $request->request->get('systemTipIds');
  1387.         $actionType $request->request->get('actionType');
  1388.         $getNew $request->request->get('getNew'); // how many new tips to get (none=false)
  1389.         //dump("system_tip_reaction_action data ( systemTipIds, $actionType, $getNew)", $systemTipIds);
  1390.         //die();
  1391.         // since a Compass user has access to all companies, we don't want this user's actions
  1392.         // (opening Bob popup, etc.) to be included in the stats - so we handle that user differently
  1393.         if ($this->getUser()->getRolesUnconverted()==UserRoleEnum::ROLE_SUPER_ADMIN) {
  1394.             // what happens depends on the system & the admin type of the company
  1395.             // - on techsupp, all actions by Compass user are recorded
  1396.             // - on DEV, ditto
  1397.             // - on LIVE, actions by Compass user are recorded ONLY if co. admin type is Internal
  1398.             //   (they are ignored for types "live", "trial active", "trial expired"
  1399.             
  1400.             $companyAdminType $this->company->__get('adminType');
  1401.             
  1402.             $allowActionSave false;
  1403.             if ($_SERVER['APP_SYSTEM_ID']=='TechSupp') { //T
  1404.                 // on TechSupp, always allow
  1405.                 $allowActionSave true;
  1406.                 // JNOTE-TESTING:
  1407.                 //if ($companyAdminType==CompanyAdminTypeEnum::INTERNAL_TEST) { //T
  1408.                 //    $allowActionSave = true;
  1409.                 //} else { //T
  1410.                 //    $allowActionSave = false;
  1411.                 //}
  1412.             
  1413.                 //dump('TechSupp, allowActionSave: '.$allowActionSave);
  1414.             } else if ($_SERVER['APP_SYSTEM_ID']=='DEV') { //T1
  1415.         
  1416.                 // on DEV, always allow
  1417.                 $allowActionSave true;
  1418.                 //dump('DEV, allowActionSave: '.$allowActionSave);
  1419.             
  1420.             } else if ($_SERVER['APP_SYSTEM_ID']=='LIVE') {  //T 1
  1421.             
  1422.                 // on LIVE, only allow if company type is "Internal"
  1423.                 if ($companyAdminType==CompanyAdminTypeEnum::INTERNAL_TEST) { //T1
  1424.                     $allowActionSave true;
  1425.                 } //T1
  1426.                 //dump('LIVE, allowActionSave: '.$allowActionSave);
  1427.             } else {
  1428.                 die();
  1429.             }
  1430.         } else if ($this->getUser()->getRolesUnconverted()==UserRoleEnum::ROLE_ACCOUNT_OWNER ||
  1431.                    $this->getUser()->getRolesUnconverted()==UserRoleEnum::ROLE_ADMIN) {
  1432.             // for registered or admin users, record the action
  1433.             $allowActionSave true;
  1434.         } else if ($this->getUser()->getRolesUnconverted()==UserRoleEnum::ROLE_USER) { // N/A
  1435.         
  1436.             // for all other users, do not record (it should not even show)
  1437.             // (ROLE_USER, ROLE_UPLOAD_ONLY, ROLE_UPLOAD_PROTOCOL)
  1438.             $allowActionSave false;
  1439.     
  1440.         } else { //
  1441.             // catch all
  1442.             if ($_SERVER['APP_SYSTEM_ID']=='LIVE') {
  1443.                 // to be safe, do not allow on LIVE
  1444.                 $allowActionSave false;
  1445.             } else {
  1446.             
  1447.                 // allow on other systems
  1448.                 $allowActionSave true;
  1449.             }
  1450.         }
  1451.             
  1452.         // load the message
  1453.         $systemTipRepository $this->getDoctrine()->getRepository(SystemTip::class);
  1454.         if ($actionType=='show') {
  1455.             $tipStatus SystemTipStatusEnum::SHOWN;
  1456.         } else if ($actionType=='ack') {
  1457.             $tipStatus SystemTipStatusEnum::ACKED;
  1458.         } else if ($actionType=='snooze') {
  1459.             $tipStatus SystemTipStatusEnum::SNOOZED;
  1460.         } else {
  1461.             die();
  1462.         }
  1463.         
  1464.         if ($allowActionSave) {
  1465.         
  1466.             foreach($systemTipIds as $systemTipId) {
  1467.         
  1468.                 //dump($systemTipId);
  1469.                 //continue;
  1470.         
  1471.                 // update system tip
  1472.                 $systemTip $systemTipRepository->findOneById($systemTipId);
  1473.                 if ($systemTip==null) {
  1474.                     die('null');
  1475.                 }
  1476.             
  1477.                 $systemTip->__set('status'$tipStatus);
  1478.             
  1479.                 $rc $systemTip->save$this->getDoctrine()->getManager(), false ); // no updated* field change
  1480.                 if (!$rc) {
  1481.                     die('error updating tip');
  1482.                 }
  1483.                 // add history entry for this tip
  1484.                 $systemTipLogEntry = new SystemTipLogEntry;
  1485.                 $systemTipLogEntry->__set('company'$this->company);
  1486.                 $systemTipLogEntry->__set('systemTip'$systemTip);
  1487.                 $systemTipLogEntry->__set('status'$tipStatus);
  1488.                 $rc $systemTipLogEntry->save$this->getDoctrine()->getManager(), false ); // no updated* field change
  1489.                 if (!$rc) {
  1490.                     die('error updating tip log entry');
  1491.                 }
  1492.                 //dump('updated');
  1493.             
  1494.                 unset($systemTip);
  1495.                 unset($systemTipLogEntry);
  1496.             
  1497.             }
  1498.         
  1499.         }
  1500.         // get new tip if requested        
  1501.         if ($getNew!==false) {
  1502.             $newTipInfo $this->ai->getSystemTipsForCompany($this->companytrue$getNew);
  1503.             //dump('newTip', $newTip);
  1504.             
  1505.             $result['newTips'] = [];
  1506.             
  1507.             if ($newTipInfo['tips']!==null && is_array($newTipInfo['tips']) && count($newTipInfo['tips'])>0) {
  1508.                 foreach($newTipInfo['tips'] as $newTip) {
  1509.                 
  1510.                     // use this tip
  1511.                     $result['newTips'][] = $newTip;
  1512.                     // mark this tip as shown (if allowed)
  1513.                     if ($allowActionSave) {
  1514.             
  1515.                         // update system tip
  1516.                         $systemTip $systemTipRepository->findOneById($newTip['id']);
  1517.                         if ($systemTip!=null) {
  1518.                 
  1519.                             $systemTip->__set('status'SystemTipStatusEnum::SHOWN);
  1520.             
  1521.                             $rc $systemTip->save$this->getDoctrine()->getManager(), false ); // no updated* field change
  1522.                             if (!$rc) {
  1523.                                 die('error updating tip');
  1524.                             }
  1525.                             // add history entry for this tip
  1526.                             $systemTipLogEntry = new SystemTipLogEntry;
  1527.                             $systemTipLogEntry->__set('company'$this->company);
  1528.                             $systemTipLogEntry->__set('systemTip'$systemTip);
  1529.                             $systemTipLogEntry->__set('status'SystemTipStatusEnum::SHOWN);
  1530.                             $rc $systemTipLogEntry->save$this->getDoctrine()->getManager(), false ); // no updated* field change
  1531.                             if (!$rc) {
  1532.                                 die('error updating tip log entry');
  1533.                             }
  1534.                             //dump('updated');
  1535.             
  1536.                             unset($systemTip);
  1537.                             unset($systemTipLogEntry);
  1538.                     
  1539.                         }
  1540.                     
  1541.                     }
  1542.                     
  1543.                 }
  1544.             } else {
  1545.             
  1546.                 // no more tips
  1547.                 //$result['newTips'] = null;
  1548.             }
  1549.         }
  1550.         // return
  1551.         $result['success'] = true;
  1552.         //dump($result); die();
  1553.         return new Response($this->jsonEncoder(array(
  1554.             'result' => $result,
  1555.         )));
  1556.     
  1557.     }
  1558.     /**
  1559.      * @Route("/ipn_otpsimple", name="b.otpsimple.ipn", methods={"POST"})
  1560.      */
  1561.     function otp_simple_ipn(Request $request)
  1562.     {
  1563.         require_once($_SERVER['APP_HOME_DIR'].'vendor/OTPSimple/SimplePayV21.php');
  1564.         require_once($_SERVER['APP_HOME_DIR'].'vendor/OTPSimple/config.php');
  1565.         //dump('initial config', $config);
  1566.         $date = new \DateTime();
  1567.         $json file_get_contents('php://input');
  1568.         //dump('intitial json', $json);
  1569.         //$this->symfonyLogger->info("otp_simple_ipn json: $json");
  1570.         //$this->symfonyLogger->info($request->getContent());
  1571.         //$this->symfonyLogger->info($request);
  1572.         $json json_decode($json,true);
  1573.         //dump('json_decode json', $json);
  1574.         $trid $json['transactionId'];
  1575.         $json['receiveDate'] = $date->format(('Y-m-d\TH:i:sO'));
  1576.         $json json_encode($json);
  1577.         //$this->symfonyLogger->info("otp_simple_ipn 2: $json");
  1578.         $trx = new \SimplePayIpn;
  1579.         $trx->addConfig($config);
  1580.         //dump('trx after addConfig', $trx);
  1581.         //dump('json with receiveDate updated', $json);
  1582.         $orderRepository $this->getDoctrine()->getRepository(LicenseOrder::class);
  1583.         $orderRepository->findOrderByTrid($trid,$result);
  1584.         if (@$result) {
  1585.             $details json_decode($result->details,true);
  1586.             $details['card_payment_IPN'] = $json;
  1587.             $details json_encode($details);
  1588.             $result->setDetails($details);
  1589.             $result->setStatus(98);
  1590.             $em $this->getDoctrine()->getManager();
  1591.             $em->persist($result);
  1592.             $em->flush();
  1593.         }
  1594.         if ($trx->isIpnSignatureCheck($json)) {
  1595.             var_dump($trx);
  1596.             $trx->runIpnConfirm();
  1597.             var_dump($trx);
  1598.         }
  1599.         $signature base64_encode(hash_hmac('sha384',$json,'7wUt7af1h1JuTn1v01128562ZtZ7J3jz',true));
  1600.         $response = new Response();
  1601.         $response->setContent($json);
  1602.         $response->headers->set('Signature',$signature);
  1603.         return $response;
  1604.     }
  1605.     /**
  1606.      * @Route("/test-function", name="test-function")
  1607.      */
  1608.     public function test(Request $requestActivityGraph $graph)
  1609.     {
  1610.     
  1611.         die();
  1612.         dump('PHP method_exists($graph, "loadVehicleActivities"): '.method_exists($graph'loadVehicleActivities'));
  1613.         dump('---');
  1614.         dump('get_class_methods($graph)'get_class_methods($graph));
  1615.         dump('graph'$graph);
  1616.         die();
  1617.     }
  1618. }