Guest User

v2

a guest
Nov 29th, 2016
41
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 92.56 KB | None | 0 0
  1. <?php
  2.  
  3. use Olivemedia\Video\VideoService as Service;
  4.  
  5. include_once( APPPATH . 'libraries/d2r/Mobile_API_Controller.php');
  6.  
  7. use Stripe\Stripe as Stripe;
  8. use Stripe\Charge as Stripe_Charge;
  9. use Stripe\Customer as Stripe_Customer;
  10.  
  11. class V2 extends Mobile_API_Controller {
  12.  
  13.     public function __construct(){
  14.         parent::__construct();
  15.     }
  16.  
  17.     public function member_login_get() {
  18.  
  19.         try {
  20.  
  21.             $member = Member::find_valid_registered_by_id(
  22.                 $this->member_id
  23.             );
  24.  
  25.             $membership_active = true;
  26.  
  27.             if ($member->is_learner() && $member->organisation->is_membership_enabled) {
  28.            
  29.                 $member_membership = MemberMembership::last(array('conditions'=> array("member_id = ?", $member->id)));
  30.  
  31.                 try{
  32.                    
  33.                     if($member_membership){
  34.                         $member_membership->check_is_expired();                    
  35.                         $membership_active = true;
  36.                     } else {
  37.                         $membership_active = false;
  38.                     }
  39.  
  40.                 } catch(Exception $e) {
  41.                     $membership_active = flase;
  42.                 }
  43.             }
  44.  
  45.             return $this->response(array('success' => 'true', 'result' => array(
  46.                 'id' => $member->id,
  47.                 'organisation_id' => $member->organisation_id,
  48.                 'username' => $member->user->username,
  49.                 'first_name' => $member->first_name,
  50.                 'last_name' => $member->last_name,
  51.                 'email' => $member->email,
  52.                 'mobile_number' => $member->mobile_number,
  53.                 'mobile_country_code' => $member->country_code,
  54.                 'created_at' => $member->created_at,
  55.                 'updated_at' => $member->updated_at,
  56.                 'is_verified' => ($member->is_verified()) ? 1 : 0,
  57.                 'verification_stage' => $member->verification_stage,
  58.                 'is_trainer' => $member->is_trainer,
  59.                 'is_team_admin' => $member->is_team_admin,
  60.                 'is_admin' => $member->is_admin,
  61.                 'is_super_admin' => $member->is_super_admin,
  62.                 'is_site_manager' => $member->is_site_manager,
  63.                 'image_key' => rtrim(strtr(base64_encode($member->image_key), '+/', '-_'), '='),
  64.                 'membership_active' => $membership_active
  65.  
  66.             )));
  67.  
  68.         } catch (Exception $e) {
  69.             return $this->error_response($e->getMessage());
  70.         }
  71.         exit;
  72.     }
  73.  
  74.     public function membership_charges_get() {
  75.  
  76.         try {
  77.  
  78.             $member_membership = MemberMembership::last(array('conditions'=> array("member_id = ?", $this->member_id)));
  79.             $membership_data = array();
  80.             if($member_membership) {
  81.                 $membership_data['duration'] = $member_membership->membership_duration;
  82.                 $membership_data['expiry_date'] = $member_membership->expires_at;
  83.                 $membership_data['is_expired'] = $member_membership->is_expired;
  84.             }
  85.             return $this->response(array('success' => 'true', 'results' => array(
  86.                 'week' => 7.20,
  87.                 'month' => 28.80,
  88.                 'year' => 374.40,
  89.                 'membership_data' => $membership_data
  90.             )));
  91.         } catch (Exception $e) {
  92.             return $this->error_response($e->getMessage());
  93.         }
  94.     }
  95.  
  96.     private function get_charge_for_duration($membership_duration) {
  97.  
  98.         $membership_charges = array(
  99.             '1 week' => 7.20,
  100.             '1 month' => 28.80,
  101.             '1 year' => 374.40
  102.         );
  103.  
  104.         if(!array_key_exists($membership_duration, $membership_charges)) {
  105.             throw new MembershipDurationNotValidException('The duration has to be either \'week\' or \'month\' or \'year\'');
  106.         } else {
  107.  
  108.             return $membership_charges[$membership_duration];
  109.         }
  110.     }
  111.  
  112.     private function activate_membership($membership_duration) {
  113.  
  114.         try {
  115.  
  116.             $member_membership = MemberMembership::create(array(
  117.                 'member' => Member::find($this->member_id),
  118.                 'membership_duration' => $membership_duration
  119.             ));
  120.        
  121.             return $member_membership->id;
  122.         } catch (Exception $e) {
  123.             throw $e;
  124.         }
  125.     }
  126.  
  127.     public function purchase_membership_post(){
  128.  
  129.         if(!isset($this->_post_json_args->token)) {
  130.             $this->_post_json_args->token = "";
  131.         }
  132.  
  133.         if(!isset($this->_post_json_args->new_card)) $this->_post_json_args->new_card = 0;
  134.  
  135.         $token = $this->_post_json_args->token;
  136.         $new_card = $this->_post_json_args->new_card;
  137.  
  138.         Stripe::setApiKey(PAYMENTS_STRIPE_PRIVATE_KEY);
  139.  
  140.         try {
  141.  
  142.             $membership_charge = $this->get_charge_for_duration($this->_post_json_args->membership_duration);
  143.  
  144.             $member = Member::find_valid_registered_by_id(
  145.                 $this->member_id
  146.             );
  147.  
  148.             $organisation = Organisation::find_valid_by_id(
  149.                 $this->current_organisation_id
  150.             );
  151.  
  152.             if($member->customer != null) {
  153.  
  154.                 $stripe_customer = Stripe_Customer::retrieve($member->customer->stripe_id);
  155.  
  156.                 if($token != "" && $new_card == 1) {
  157.  
  158.                     $stripe_customer->card = $token;
  159.                     $stripe_customer->save();
  160.                 }
  161.  
  162.             } else if($new_card == 0 && $token == "") {
  163.  
  164.                 return $this->error_response("Your existing card has been removed from ours records please use the pay with a new card form. If your existing card is still valid please feel free to re-enter those details.");
  165.  
  166.             } else {
  167.  
  168.                 if($token == "") {
  169.                     return $this->error_response("There has been an issue processing your payment : code(008)");
  170.                 }
  171.                 $stripe_customer = Stripe_Customer::create(array(
  172.                     "card" => $token,
  173.                     "description" => $member->email)
  174.                 );
  175.  
  176.                 $customer = new Customer(array(
  177.                     'stripe_id' => $stripe_customer->id
  178.                 ));
  179.  
  180.                 $customer->set_member($member);
  181.  
  182.                 $customer->save();
  183.             }
  184.  
  185.             Stripe_Charge::create(array(
  186.                "amount" => ($membership_charge * 100), # amount in cents, again
  187.               "currency" => $member->organisation->currency,
  188.                "customer" => $stripe_customer->id,
  189.                "description" => "Mobile purchasing membership")
  190.             );
  191.  
  192.             $membership_id = $this->activate_membership($this->_post_json_args->membership_duration);  
  193.             return $this->response(array("success" => "true", "id" => $membership_id));
  194.         } catch(Stripe_CardError $e) {
  195.             $body = $e->getJsonBody();
  196.             $err  = $body['error'];
  197.             return $this->error_response($err['message']);
  198.         } catch (Stripe_InvalidRequestError $e) {
  199.             return $this->error_response("There has been an issue processing your payment : code(004) ");
  200.         } catch (Stripe_AuthenticationError $e) {
  201.             return $this->error_response("There has been an issue processing your payment : code(005) ");
  202.         } catch (Stripe_ApiConnectionError $e) {
  203.             return $this->error_response("There has been an issue processing your payment : code(006) ");
  204.         } catch (Stripe_Error $e) {
  205.             return $this->error_response("There has been an issue processing your payment : code(007) ");
  206.         } catch(MembershipDurationNotValidException $e) {
  207.             return $this->error_response($e->getMessage());
  208.         } catch (Exception $e) {
  209.             return $this->error_response($e->getMessage());
  210.         }
  211.     }
  212.  
  213.     public function member_details_post() {
  214.  
  215.         try {
  216.  
  217.             if(!isset($this->_post_json_args->first_name)) $this->_post_json_args->first_name = null;
  218.             if(!isset($this->_post_json_args->last_name)) $this->_post_json_args->last_name = null;
  219.             if(!isset($this->_post_json_args->email)) $this->_post_json_args->email = null;
  220.             if(!isset($this->_post_json_args->username)) $this->_post_json_args->username = null;
  221.  
  222.             $member = Member::find_valid_registered_by_id(
  223.                 $this->member_id
  224.             );
  225.  
  226.             $member->first_name = $this->_post_json_args->first_name;
  227.             $member->last_name = $this->_post_json_args->last_name;
  228.             if($this->_post_json_args->email != $member->email) $member->email = $this->_post_json_args->email;
  229.  
  230.             if($member->is_registered()) {
  231.                 if($member->user->username != $this->_post_json_args->username) $member->user->username = $this->_post_json_args->username;
  232.                 $member->user->save();
  233.             }
  234.  
  235.             $member->save();
  236.  
  237.             return $this->response(array("success" => "true"));
  238.  
  239.         } catch (Exception $e) {
  240.             return $this->error_response($e->getMessage());
  241.         }
  242.  
  243.     }
  244.  
  245.     public function member_password_post() {
  246.  
  247.         try {
  248.  
  249.             if(!isset($this->_post_json_args->password)) $this->_post_json_args->password = null;
  250.             if(!isset($this->_post_json_args->passwordconfirm)) $this->_post_json_args->passwordconfirm = null;
  251.  
  252.             $member = Member::find_valid_registered_by_id(
  253.                 $this->member_id
  254.             );
  255.  
  256.             $member->user->reset_password(
  257.                 $this->_post_json_args->password,
  258.                 $this->_post_json_args->passwordconfirm
  259.             );
  260.  
  261.             $member->user->save();
  262.  
  263.             return $this->response(array("success" => "true"));
  264.  
  265.         } catch (Exception $e) {
  266.             return $this->error_response($e->getMessage());
  267.         }
  268.  
  269.  
  270.  
  271.     }
  272.  
  273.     public function member_mobile_post() {
  274.  
  275.         try {
  276.  
  277.             if(!isset($this->_post_json_args->mobile_number)) $this->_post_json_args->mobile_number = null;
  278.             if(!isset($this->_post_json_args->mobile_country_code)) $this->_post_json_args->mobile_country_code = null;
  279.  
  280.             $member = Member::find_valid_registered_by_id(
  281.                 $this->member_id
  282.             );
  283.  
  284.             $mobile_number = $this->_post_json_args->mobile_country_code.$this->_post_json_args->mobile_number;
  285.  
  286.             $mobile_number = urldecode($mobile_number);
  287.             $mobile_number = trim($mobile_number);
  288.  
  289.             $member->mobile_number = $mobile_number;
  290.             $member->country_code = $this->_post_json_args->mobile_country_code;
  291.             $member->save();
  292.  
  293.             return $this->response(array("success" => "true"));
  294.  
  295.         } catch (Exception $e) {
  296.             return $this->error_response($e->getMessage());
  297.         }
  298.  
  299.  
  300.  
  301.     }
  302.  
  303.     public function member_image_post() {
  304.  
  305.         try {
  306.  
  307.             if(!isset($this->_post_json_args->imagedata)) return $this->error_response("Image data required");
  308.  
  309.             $member = Member::find_valid_registered_by_id(
  310.                 $this->member_id
  311.             );
  312.  
  313.             $member_image_temp = new SplFileObject('/tmp/member_'.$this->member_id.'_image.jpeg', 'w+');
  314.  
  315.             $member_image_temp->fwrite(base64_decode($this->_post_json_args->imagedata));
  316.  
  317.             $s3_client = \Aws\S3\S3Client::factory(array(
  318.                 'key'    => AWS_S3_ACCESS_KEY,
  319.                 'secret' => AWS_S3_SECRET_KEY,
  320.                 'region' => 'us-east-1'
  321.             ));
  322.  
  323.             $key_base_path = $member->base_path;
  324.  
  325.             $hash = md5(uniqid(rand(), true));
  326.  
  327.             $key = $key_base_path.$hash.'.jpeg';
  328.  
  329.             $key = new AcademyHQ\S3\Key($key);
  330.  
  331.             $image_upload = new AcademyHQ\S3\Image\Factory($s3_client, AWS_S3_ASSETS_BUCKET);
  332.  
  333.             $image = $image_upload->create($key, $member_image_temp);
  334.  
  335.             $member->image_key = $image->get_reference()->get_key()->to_string();
  336.  
  337.             $member->save();
  338.  
  339.             $member_image_temp = null;
  340.  
  341.             unlink('/tmp/member_'.$this->member_id.'_image.jpeg');
  342.  
  343.             return $this->response(array("success" => "true", "image_key" => rtrim(strtr(base64_encode($member->image_key), '+/', '-_'), '=')));
  344.  
  345.         } catch (Exception $e) {
  346.             //return $this->error_response($e->getMessage());//DEV returns all aws errors as well (these should not go to the app.
  347.             return $this->error_response("There was an error accepting your image please contact us. : code(009)");
  348.         }
  349.  
  350.     }
  351.  
  352.     public function member_token_post() {
  353.  
  354.         if(!isset($this->_post_json_args->device_token)) $this->_post_json_args->device_token = null;
  355.         if(!isset($this->_post_json_args->is_ios)) $this->_post_json_args->is_ios = 0;
  356.         if(!isset($this->_post_json_args->is_android)) $this->_post_json_args->is_android = 0;
  357.  
  358.         try {
  359.  
  360.             $tokenNew = false;
  361.  
  362.             $member = Member::find_valid_registered_by_id(
  363.                 $this->member_id
  364.             );
  365.  
  366.             $token = PushToken::find_by_device_token(
  367.                 $this->_post_json_args->device_token
  368.             );
  369.  
  370.             if($token == null) {
  371.  
  372.                 $tokenNew = true;
  373.  
  374.                 $token = PushToken::create(array(
  375.                     'device_token' => $this->_post_json_args->device_token,
  376.                     'is_ios' => $this->_post_json_args->is_ios,
  377.                     'is_android' => $this->_post_json_args->is_android,
  378.                 ));
  379.             }
  380.  
  381.             $token->set_member($member);
  382.  
  383.             $token->save();
  384.  
  385.             return $this->response(array("success" => "true", "token_new" => $tokenNew, "member_id" => $member->id ));
  386.  
  387.         } catch (Exception $e) {
  388.             return $this->error_response($e->getMessage());
  389.         }
  390.  
  391.  
  392.     }
  393.  
  394.     public function org_details_get() {
  395.  
  396.         try {
  397.  
  398.             $organisation = Organisation::find_valid_by_id(
  399.                 $this->current_organisation_id
  400.             );
  401.  
  402.             return $this->response(array('success' => 'true', 'result' => array(
  403.                 'id' => $organisation->id,
  404.                 'name' => $organisation->name,
  405.                 'branding_hex' => $organisation->branding_hex,
  406.                 'branding_hex_dark' => Util::mobile_branding_darken($organisation->branding_hex, -50),
  407.                 'currency' => $organisation->currency,
  408.                 'language' => $organisation->language,
  409.                 'mobile_validation_enabled' => $organisation->mobile_validation_enabled,
  410.                 'mobile_validation_skippable' => $organisation->mobile_validation_skippable,
  411.                 'created_at' => $organisation->created_at,
  412.                 'updated_at' => $organisation->updated_at,
  413.                 'image_key' => rtrim(strtr(base64_encode($organisation->branding_logo_key), '+/', '-_'), '=')
  414.             )));
  415.  
  416.         } catch (Exception $e) {
  417.             return $this->error_response($e->getMessage());
  418.         }
  419.  
  420.     }
  421.  
  422.     public function documents_get($from = null, $limit = null, $page_number = 1) {
  423.  
  424.         if($limit == null) $limit = $this->config->item('mobile_api_pagination_limit');
  425.         if($from == null) {
  426.             $from = date("Y-m-d H:i:s", 0);
  427.         } else {
  428.             $from = urldecode($from);
  429.         }
  430.  
  431.         $from = date("Y-m-d H:i:s", strtotime($from)+1);
  432.  
  433.         try {
  434.  
  435.             $organisation = Organisation::find_valid_by_id(
  436.                 $this->current_organisation_id
  437.             );
  438.  
  439.             $page = new Page();
  440.             $page->set_per_page($limit);
  441.             $page->set_current_page_number($page_number);
  442.  
  443.             $document_search = new DocumentSearch();
  444.             $document_search
  445.                 ->set_page($page)
  446.                 ->set_date_filter('updated')
  447.                 ->set_date_from($from)
  448.                 ->set_organisation($organisation);
  449.  
  450.             $document_search->execute();
  451.  
  452.             $results = array();
  453.  
  454.             $l = $document_search->get_row_per_current_page();
  455.  
  456.             for($i = 0; $i < $l; $i++){
  457.  
  458.                 $document = $document_search[$i];
  459.  
  460.                 $document_details = array(
  461.                     'id' => $document->id,
  462.                     'name' => $document->name,
  463.                     'created_at' => $document->created_at,
  464.                     'updated_at' => $document->updated_at,
  465.                     'is_deleted' => $document->is_deleted,
  466.                     'is_required' => $document->is_required,
  467.                     'is_active' => $document->is_active
  468.                 );
  469.  
  470.                 array_push($results, $document_details);
  471.  
  472.             }
  473.  
  474.             return $this->response(array('success' => 'true', 'total_rows' => (int) $l, 'result' => $results));
  475.  
  476.         } catch (Exception $e) {
  477.             return $this->error_response($e->getMessage());
  478.         }
  479.  
  480.     }
  481.  
  482.     public function document_get($document_id) {
  483.  
  484.         try {
  485.  
  486.             $document = Document::find_valid_by_id(
  487.                 $document_id
  488.             );
  489.  
  490.             return $this->response(array('success' => 'true', 'results' => array(
  491.                 'id' => $document->id,
  492.                 'name' => $document->name,
  493.                 'created_at' => $document->created_at,
  494.                 'updated_at' => $document->updated_at,
  495.                 'is_deleted' => $document->is_deleted,
  496.                 'is_required' => $document->is_required,
  497.                 'is_active' => $document->is_active
  498.             )));
  499.  
  500.         } catch (Exception $e) {
  501.             return $this->error_response($e->getMessage());
  502.         }
  503.  
  504.     }
  505.  
  506.     public function search_member_name_get($first = null, $last= null, $limit = null, $page_number = 1) {
  507.  
  508.         if($limit == null) $limit = $this->config->item('mobile_api_pagination_limit');
  509.  
  510.         try {
  511.  
  512.             $organisation = Organisation::find_valid_by_id(
  513.                 $this->current_organisation_id
  514.             );
  515.  
  516.             $organisationFactory = new OrganisationFactory();
  517.             $organisation = $organisationFactory->get($organisation);
  518.  
  519.             $page = new Page();
  520.             $page->set_per_page($limit);
  521.             $page->set_current_page_number($page_number);
  522.  
  523.             $member_search = new MemberFilteredSearch();
  524.             $member_search->set_page($page);
  525.             $member_search->set_organisation($organisation);
  526.             $member_search->set_is_deleted(0);
  527.             $member_search->set_is_active(1);
  528.  
  529.             if($first != null) {
  530.                 $member_search->set_first_name($first);
  531.             }
  532.  
  533.             if($last != null) {
  534.                 $member_search->set_last_name($last);
  535.             }
  536.  
  537.             $member_search->execute();
  538.  
  539.             $results = array();
  540.  
  541.             $l = $member_search->get_row_per_current_page();
  542.  
  543.             for($i = 0; $i < $l; $i++){
  544.  
  545.                 $member = $member_search[$i];
  546.  
  547.                 $member_details = array(
  548.                     'id' => $member->id,
  549.                     'first_name' => $member->first_name,
  550.                     'last_name' => $member->last_name,
  551.                 );
  552.  
  553.                 array_push($results, $member_details);
  554.             }
  555.  
  556.             return $this->response(array('success' => 'true', 'total_rows' => (int) $l, 'result' => $results));
  557.  
  558.         } catch (Exception $e) {
  559.             return $this->error_response($e->getMessage());
  560.         }
  561.  
  562.     }
  563.  
  564.     public function search_member_mobile_number_get($mobile = null, $limit = null, $page_number = 1) {
  565.  
  566.         if($limit == null) $limit = $this->config->item('mobile_api_pagination_limit');
  567.  
  568.         try {
  569.  
  570.             $organisation = Organisation::find_valid_by_id(
  571.                 $this->current_organisation_id
  572.             );
  573.  
  574.             $organisationFactory = new OrganisationFactory();
  575.             $organisation = $organisationFactory->get($organisation);
  576.  
  577.             $page = new Page();
  578.             $page->set_per_page($limit);
  579.             $page->set_current_page_number($page_number);
  580.  
  581.             $member_search = new MemberFilteredSearch();
  582.             $member_search->set_page($page)
  583.                 ->set_role('learner')
  584.                 ->set_mobile_number($mobile)
  585.                 ->set_organisation($organisation);
  586.  
  587.             $member_search->execute();
  588.  
  589.             $results = array();
  590.  
  591.             $l = $member_search->get_row_per_current_page();
  592.  
  593.             for($i = 0; $i < $l; $i++){
  594.  
  595.                 $member = $member_search[$i];
  596.  
  597.                 $member_details = array(
  598.                     'id' => $member->id,
  599.                     'first_name' => $member->first_name,
  600.                     'last_name' => $member->last_name,
  601.                 );
  602.  
  603.                 array_push($results, $member_details);
  604.             }
  605.  
  606.             return $this->response(array('success' => 'true', 'total_rows' => (int) $l, 'result' => $results));
  607.  
  608.         } catch (Exception $e) {
  609.             return $this->error_response($e->getMessage());
  610.         }
  611.  
  612.     }
  613.  
  614.     public function verify_mobile_post() {
  615.  
  616.         if(file_exists('vendor/twilio/sdk/Services/Twilio.php'))
  617.         {
  618.             require_once('vendor/twilio/sdk/Services/Twilio.php');
  619.         }
  620.         else {
  621.             return $this->error_response("Error sending SMS please contact us. : code(012) ");
  622.         }
  623.  
  624.         try {
  625.  
  626.             if(!isset($this->_post_json_args->mobile_number)) $this->_post_json_args->mobile_number = null;
  627.             if(!isset($this->_post_json_args->mobile_country_code)) $this->_post_json_args->mobile_country_code = null;
  628.  
  629.             $member = Member::find_valid_registered_by_id(
  630.                 $this->member_id
  631.             );
  632.  
  633.             $mobile_number = $this->_post_json_args->mobile_country_code.$this->_post_json_args->mobile_number;
  634.  
  635.             $validation = MemberValidationCode::create(array(
  636.                 'member' => $member,
  637.                 'mobile_number' => $mobile_number,
  638.                 'country_code' => $this->_post_json_args->mobile_country_code
  639.             ));
  640.  
  641.             $client = new Twilio\Rest\Client(ACCOUNT_SID_FOR_SMS, AUTH_TOKEN_FOR_SMS);
  642.             $message = $client->messages->create(
  643.                 $mobile_number,
  644.                 array(
  645.                     'from' => TWILIO_SMS_NUMBER,
  646.                     'body' => "Your AcademyHQ verification code is ".$validation->validation_code
  647.                 )
  648.             );
  649.  
  650.             $validation->sms_id = $message->sid;
  651.             $validation->save();
  652.  
  653.             $member->verification_stage = 1;
  654.             $member->save();
  655.  
  656.             return $this->response(array("success" => "true"));
  657.  
  658.         } catch (Exception $e) {
  659.             return $this->error_response($e->getMessage());
  660.         }
  661.  
  662.     }
  663.  
  664.     public function verify_code_post() {
  665.  
  666.         try {
  667.  
  668.             if(!isset($this->_post_json_args->verifycode)) $this->_post_json_args->verifycode = null;
  669.  
  670.             $member = Member::find_valid_registered_by_id(
  671.                 $this->member_id
  672.             );
  673.  
  674.             $verifycode = MemberValidationCode::find_by_validation_code(
  675.                 $this->_post_json_args->verifycode
  676.             );
  677.  
  678.             if($verifycode != null) {
  679.                 if($verifycode->member_id == $member->id) {
  680.  
  681.                     $mobile_number = urldecode($verifycode->mobile_number);
  682.                     $mobile_number = trim($mobile_number);
  683.  
  684.                     $member->verification_stage = 2;
  685.                     $member->mobile_number = $mobile_number;
  686.                     $member->country_code = $verifycode->country_code;
  687.                     $member->save();
  688.  
  689.                     $verifycode->complete();
  690.  
  691.                     return $this->response(array("success" => "true"));
  692.  
  693.                 }
  694.             }
  695.  
  696.             return $this->error_response("Verify code incorrect");
  697.         } catch (Exception $e) {
  698.             return $this->error_response($e->getMessage());
  699.         }
  700.     }
  701.  
  702.     public function verify_image_post() {
  703.  
  704.         try {
  705.  
  706.             if(!isset($this->_post_json_args->imagedata)) return $this->error_response("Image data required");
  707.  
  708.             $member = Member::find_valid_registered_by_id(
  709.                 $this->member_id
  710.             );
  711.  
  712.             $member_image_temp = new SplFileObject('/tmp/member_'.$this->member_id.'_image.jpeg', 'w+');
  713.  
  714.             $member_image_temp->fwrite(base64_decode($this->_post_json_args->imagedata));
  715.  
  716.             $s3_client = \Aws\S3\S3Client::factory(array(
  717.                 'key'    => AWS_S3_ACCESS_KEY,
  718.                 'secret' => AWS_S3_SECRET_KEY,
  719.                 'region' => 'us-east-1'
  720.             ));
  721.  
  722.             $key_base_path = $member->base_path;
  723.  
  724.             $hash = md5(uniqid(rand(), true));
  725.  
  726.             $key = $key_base_path.$hash.'.jpeg';
  727.  
  728.             $key = new AcademyHQ\S3\Key($key);
  729.  
  730.             $image_upload = new AcademyHQ\S3\Image\Factory($s3_client, AWS_S3_ASSETS_BUCKET);
  731.  
  732.             $image = $image_upload->create($key, $member_image_temp);
  733.  
  734.             $member->image_key = $image->get_reference()->get_key()->to_string();
  735.  
  736.             $member->verification_stage = 3;
  737.             $member->save();
  738.  
  739.             $member_image_temp = null;
  740.  
  741.             unlink('/tmp/member_'.$this->member_id.'_image.jpeg');
  742.  
  743.             return $this->response(array("success" => "true", "image_key" => rtrim(strtr(base64_encode($member->image_key), '+/', '-_'), '=')));
  744.  
  745.         } catch (Exception $e) {
  746.             //return $this->error_response($e->getMessage());//DEV returns all aws errors as well (these should not go to the app.
  747.             return $this->error_response("There was an error accepting your image please contact us. : code(010)");
  748.  
  749.         }
  750.  
  751.  
  752.  
  753.     }
  754.  
  755.     public function verify_state_get() {
  756.  
  757.         try {
  758.  
  759.             $member = Member::find_valid_registered_by_id(
  760.                 $this->member_id
  761.             );
  762.  
  763.             $member->verification_stage = 4;
  764.             $member->is_verified = 1;
  765.             $member->save();
  766.  
  767.             return $this->response(array("success" => "true"));
  768.  
  769.         } catch (Exception $e) {
  770.             return $this->error_response($e->getMessage());
  771.         }
  772.  
  773.     }
  774.  
  775.     public function enrolment_get($enrolment_id) {
  776.  
  777.         try {
  778.  
  779.             $enrolment = Enrolment::find_valid_by_id(
  780.                 $enrolment_id
  781.             );
  782.  
  783.             $course = $enrolment->course;
  784.  
  785.             $modules = array();
  786.  
  787.             if($enrolment->course->has_modules()) {
  788.  
  789.                 foreach($enrolment->course->modules as $module) {
  790.  
  791.                     $module_details = array();
  792.  
  793.                     $module_details = array(
  794.                         'id'    => $module->id,
  795.                         'created_at' => $module->created_at,
  796.                         'order' => $module->ordering,
  797.                         'updated_at' => $module->updated_at,
  798.                         'course_id' => $module->course_id,
  799.                         'name'  => $module->name,
  800.                         'description_message'  => $module->description,//description is a reserved key on iOS hence the miss match of keys here
  801.                         'completion_message' => $module->completion_message,
  802.                         'duration' => $module->duration,
  803.                         'typical_time' => $module->typical_time,
  804.                         'is_active' => $module->is_active,
  805.                         'is_deleted' => $module->is_deleted,
  806.                     );
  807.  
  808.                     $modules[] = $module_details;
  809.                 }
  810.             }
  811.  
  812.             $course_details = array(
  813.                 'id' => $course->id,
  814.                 'created_at' => $course->created_at,
  815.                 'updated_at' => $course->updated_at,
  816.                 'name'  => $course->name,
  817.                 'is_active' => $course->is_active,
  818.                 'is_deleted' => $course->is_deleted,
  819.                 'module_count' => $course->module_count,
  820.                 'has_certificate'  => $course->has_certificate,
  821.                 'expiry_months' => $course->expiry_months,
  822.                 'image_key' => rtrim(strtr(base64_encode($course->image_key), '+/', '-_'), '='),
  823.                 'modules' => $modules
  824.  
  825.             );
  826.  
  827.             return $this->response(array('success' => 'true', 'result' => array(
  828.                 'id' => $enrolment->id,
  829.                 'created_at' => $enrolment->created_at,
  830.                 'updated_at' => $enrolment->updated_at,
  831.                 'started_at' => $enrolment->started_at,
  832.                 'completed_at' => $enrolment->completed_at,
  833.                 'succeeded_at' => $enrolment->succeeded_at,
  834.                 'failed_at' => $enrolment->failed_at,
  835.                 'reminded_at' => $enrolment->reminded_at,
  836.                 'last_resumed_at' => $enrolment->last_resumed_at,
  837.  
  838.                 'progress' => $enrolment->progress,
  839.                 'time_spent' => $enrolment->time_spent,
  840.                 'score' => $enrolment->score,
  841.  
  842.                 'course_id' => $enrolment->course_id,
  843.  
  844.                 'is_started' => $enrolment->is_started,
  845.                 'is_completed' => $enrolment->is_completed,
  846.                 'is_successful' => $enrolment->is_successful,
  847.                 'is_failed' => $enrolment->is_failed,
  848.                 'is_manual' => $enrolment->is_manual,
  849.                 'is_active' => $enrolment->is_active,
  850.                 'is_deleted' => $enrolment->is_deleted,
  851.  
  852.                 'expire_at' => $enrolment->expire_at,
  853.                 'is_expired' => $enrolment->is_expired,
  854.  
  855.                 'course' => $course_details,
  856.  
  857.             )));
  858.  
  859.         } catch (Exception $e) {
  860.             return $this->error_response($e->getMessage());
  861.         }
  862.  
  863.     }
  864.  
  865.     public function enrolments_get($from = null, $limit = null, $page_number = 1) {
  866.  
  867.         if($limit == null) $limit = $this->config->item('mobile_api_pagination_limit');
  868.         if($from == null) {
  869.             $from = date("Y-m-d H:i:s", 0);
  870.         } else {
  871.             $from = urldecode($from);
  872.         }
  873.  
  874.         $from = date("Y-m-d H:i:s", strtotime($from)+1);
  875.  
  876.         try {
  877.  
  878.             $member = Member::find_valid_registered_by_id(
  879.                 $this->member_id
  880.             );
  881.  
  882.             $organisation = Organisation::find_valid_by_id(
  883.                 $this->current_organisation_id
  884.             );
  885.  
  886.             $page = new Page();
  887.             $page->set_per_page($limit);
  888.             $page->set_current_page_number($page_number);
  889.  
  890.             $enrolment_search = new EnrolmentMobileFilteredSearch();
  891.             $enrolment_search->set_page($page)
  892.                 ->set_order('updated_at', 'DESC')
  893.                 ->set_type('standard')
  894.                 ->set_date_filter('updated')
  895.                 ->set_date_from($from)
  896.                 ->set_member($member)
  897.                 ->set_organisation($organisation);
  898.  
  899.             $enrolment_search->execute();
  900.  
  901.             $results = array();
  902.  
  903.             $l = $enrolment_search->get_row_per_current_page();
  904.  
  905.             for($i = 0; $i < $l; $i++){
  906.  
  907.                 $enrolment = $enrolment_search[$i];
  908.  
  909.                 $course = $enrolment->course;
  910.  
  911.                 $modules = array();
  912.                
  913.                 if($enrolment->course->has_modules()) {
  914.  
  915.                     foreach($enrolment->course->modules as $module) {
  916.                         $module_details = array();
  917.  
  918.                         $module_details = array(
  919.                             'id'    => $module->id,
  920.                             'created_at' => $module->created_at,
  921.                             'updated_at' => $module->updated_at,
  922.                             'order' => $module->ordering,
  923.                             'course_id' => $module->course_id,
  924.                             'name'  => $module->name,
  925.                             'description_message'  => $module->description,//description is a reserved key on iOS hence the miss match of keys here
  926.                             'completion_message' => $module->completion_message,
  927.                             'duration' => $module->duration,
  928.                             'typical_time' => $module->typical_time,
  929.                             'is_active' => $module->is_active,
  930.                             'is_deleted' => $module->is_deleted,
  931.                         );
  932.  
  933.                         $modules[] = $module_details;
  934.                     }  
  935.                 }
  936.                 if($course->standard != null) {
  937.                     $course_mobile = $course->standard->is_mobile_enabled;
  938.                 } else {
  939.                     $course_mobile = 0;
  940.                 }
  941.  
  942.                 $course_details = array(
  943.                     'id' => $course->id,
  944.                     'created_at' => $course->created_at,
  945.                     'updated_at' => $course->updated_at,
  946.                     'name'  => $course->name,
  947.                     'is_active' => $course->is_active,
  948.                     'is_deleted' => $course->is_deleted,
  949.                     'module_count' => $course->module_count,
  950.                     'has_certificate'  => $course->has_certificate,
  951.                     'expiry_months' => $course->expiry_months,
  952.                     'image_key' => rtrim(strtr(base64_encode($course->image_key), '+/', '-_'), '='),
  953.                     'modules' => $modules,
  954.                     'is_mobile_enabled' => $course_mobile
  955.  
  956.                 );
  957.  
  958.                 $enrolment_details = array(
  959.                     'id' => $enrolment->id,
  960.                     'created_at' => $enrolment->created_at,
  961.                     'updated_at' => $enrolment->updated_at,
  962.                     'started_at' => $enrolment->started_at,
  963.                     'completed_at' => $enrolment->completed_at,
  964.                     'succeeded_at' => $enrolment->succeeded_at,
  965.                     'failed_at' => $enrolment->failed_at,
  966.                     'reminded_at' => $enrolment->reminded_at,
  967.                     'last_resumed_at' => $enrolment->last_resumed_at,
  968.  
  969.                     'progress' => $enrolment->progress,
  970.                     'time_spent' => $enrolment->time_spent,
  971.                     'score' => $enrolment->score,
  972.  
  973.                     'course_id' => $enrolment->course_id,
  974.  
  975.                     'is_started' => $enrolment->is_started,
  976.                     'is_completed' => $enrolment->is_completed,
  977.                     'is_successful' => $enrolment->is_successful,
  978.                     'is_failed' => $enrolment->is_failed,
  979.                     'is_manual' => $enrolment->is_manual,
  980.                     'is_active' => $enrolment->is_active,
  981.                     'is_deleted' => $enrolment->is_deleted,
  982.  
  983.                     'expire_at' => $enrolment->expire_at,
  984.                     'is_expired' => $enrolment->is_expired,
  985.  
  986.                     'course' => $course_details,
  987.  
  988.                 );
  989.  
  990.                 array_push($results, $enrolment_details);
  991.  
  992.             }
  993.  
  994.             return $this->response(array('success' => 'true', 'total_rows' => (int) $l, 'result' => $results));
  995.  
  996.         } catch (Exception $e) {
  997.             return $this->error_response($e->getMessage());
  998.         }
  999.  
  1000.     }
  1001.  
  1002.     public function enrolment_launch_get($enrolment_id) {
  1003.  
  1004.         if(file_exists(APPPATH . 'libraries/ScormCloud/ScormEngineService.php'))
  1005.         {
  1006.             require_once(APPPATH . 'libraries/ScormCloud/ScormEngineService.php');
  1007.         }
  1008.         else {
  1009.             return $this->error_response("Error loading SCORM library please contact us. : code(013)");
  1010.         }
  1011.  
  1012.         $scorm_api = new ScormEngineService(
  1013.             SCORM_API_URL,
  1014.             SCORM_APP_ID,
  1015.             SCORM_SECRET,
  1016.             'rusticisoftware.phplibrary.1.2.1'
  1017.         );
  1018.  
  1019.         try {
  1020.  
  1021.             $enrolment = Enrolment::find_valid_by_id_and_member_id(
  1022.                 $enrolment_id,
  1023.                 $this->member_id
  1024.             );
  1025.  
  1026.             if($enrolment->standard){
  1027.  
  1028.                 $standard_enrolment = $enrolment->standard;
  1029.  
  1030.                 if(!$enrolment->is_started()){
  1031.  
  1032.                     $registration = $standard_enrolment->start();
  1033.                 } else {
  1034.  
  1035.                     $registration = $standard_enrolment->resume();
  1036.                 }
  1037.  
  1038.             } else {
  1039.                 return $this->error_response("Non standard enrolment");
  1040.             }
  1041.  
  1042.             $registration_scorm = RegistrationScorm::find_valid_by_registration_id($registration->id);
  1043.  
  1044.             if(!$registration_scorm->is_started()) {
  1045.                 $registration_scorm->start($scorm_api);
  1046.             }
  1047.  
  1048.             $registration_scorm->resume($scorm_api);
  1049.  
  1050.             $callback_url = 'http://courseexitcallback/';
  1051.  
  1052.             $launch_url = $registration_scorm->get_launch_url($scorm_api, $callback_url);
  1053.  
  1054.             return $this->response(array('success' => 'true', 'result' => array("scorm_url" => urldecode($launch_url))));
  1055.  
  1056.         } catch (Exception $e) {
  1057.             return $this->error_response($e->getMessage());
  1058.         }
  1059.  
  1060.     }
  1061.  
  1062.     private function generate_certificate($enrolment_id) {
  1063.  
  1064.         try {
  1065.             $enrolment = Enrolment::find_valid_by_id($enrolment_id);
  1066.  
  1067.             $metadata = array(
  1068.                 'name' => $enrolment->member->member_info,
  1069.                 'course' => $enrolment->course->name,
  1070.                 $enrolment->succeeded_at
  1071.             );
  1072.  
  1073.             $ukata_client = new UkataClient(UKATA_API_KEY);
  1074.             $response = $ukata_client->get_certificate_url($metadata);
  1075.  
  1076.             $bucket_key = Certificate::store($response, $enrolment);
  1077.             $enrolment->standard->certificate_key = $bucket_key;
  1078.             $enrolment->standard->save();
  1079.  
  1080.             return true;
  1081.         } catch (Exception $e) {
  1082.  
  1083.             print_r($e->getMessage());
  1084.             exit();
  1085.         }
  1086.     }
  1087.  
  1088.     public function enrolment_close_get($enrolment_id) {
  1089.  
  1090.         if(file_exists(APPPATH . 'libraries/ScormCloud/ScormEngineService.php'))
  1091.         {
  1092.             require_once(APPPATH . 'libraries/ScormCloud/ScormEngineService.php');
  1093.         }
  1094.         else {
  1095.             return $this->error_response("Error loading SCORM library please contact us. : code(014)");
  1096.         }
  1097.  
  1098.         $scorm_api = new ScormEngineService(
  1099.             SCORM_API_URL,
  1100.             SCORM_APP_ID,
  1101.             SCORM_SECRET,
  1102.             'rusticisoftware.phplibrary.1.2.1'
  1103.         );
  1104.  
  1105.         try {
  1106.  
  1107.             $enrolment = Enrolment::find_valid_by_id_and_member_id(
  1108.                 $enrolment_id,
  1109.                 $this->member_id
  1110.             );
  1111.  
  1112.             if($enrolment->standard){
  1113.  
  1114.                 $standard_enrolment = $enrolment->standard;
  1115.  
  1116.             } else {
  1117.                 return $this->error_response("Non standard enrolment");
  1118.             }
  1119.  
  1120.             unset($enrolment);
  1121.  
  1122.             $registration = $standard_enrolment->current_registration;
  1123.             $registration_scorm = RegistrationScorm::find_valid_by_registration_id($registration->id);
  1124.  
  1125.             $scorm_registration_service = $scorm_api->getRegistrationService();
  1126.             $registration_summary = $scorm_registration_service->GetRegistrationSummary($registration_scorm->scorm_id);
  1127.  
  1128.             $registration_scorm->regen($registration_summary);
  1129.             $registration_scorm->enrolment->regen($scorm_api);
  1130.  
  1131.             $next_registration = null;
  1132.  
  1133.             if($registration_scorm->registration->is_completed()) {
  1134.                 if (!$registration_scorm->module->is_last_module()) {
  1135.                     $next_registration = $registration_scorm->enrolment->current_registration;
  1136.                     $next_registration = $next_registration->id;
  1137.                 }
  1138.             }
  1139.  
  1140.             if($registration_scorm->enrolment->is_successful()) {
  1141.  
  1142.                 if($registration_scorm->enrolment->course->has_certificate()) {
  1143.  
  1144.                     $certificate_generator = $registration_scorm->enrolment->course->certificate->certificate_generator;
  1145.  
  1146.                     $certificate_info = $certificate_generator->store($registration_scorm->enrolment);
  1147.  
  1148.                     $member_enrolment_certificate = MemberEnrolmentCertificate::create(array(
  1149.                         'member' => $registration_scorm->enrolment->member,
  1150.                         'certificate' => $registration_scorm->enrolment->course->certificate,
  1151.                         'enrolment_succeeded_at' => $registration_scorm->enrolment->succeeded_at,
  1152.                         'expire_at' => $registration_scorm->enrolment->expire_at,
  1153.                         'certificate_key' => $certificate_info['key']
  1154.                     ));
  1155.                 }              
  1156.             }
  1157.  
  1158.             $enrolment = Enrolment::find_valid_by_id_and_member_id(
  1159.                 $enrolment_id,
  1160.                 $this->member_id
  1161.             );
  1162.  
  1163.             $enrolment_details = array(
  1164.                 'id' => $enrolment->id,
  1165.                 'created_at' => $enrolment->created_at,
  1166.                 'updated_at' => $enrolment->updated_at,
  1167.                 'started_at' => $enrolment->started_at,
  1168.                 'completed_at' => $enrolment->completed_at,
  1169.                 'succeeded_at' => $enrolment->succeeded_at,
  1170.                 'failed_at' => $enrolment->failed_at,
  1171.                 'reminded_at' => $enrolment->reminded_at,
  1172.                 'last_resumed_at' => $enrolment->last_resumed_at,
  1173.  
  1174.                 'progress' => $enrolment->progress,
  1175.                 'time_spent' => $enrolment->time_spent,
  1176.                 'score' => $enrolment->score,
  1177.  
  1178.                 'course_id' => $enrolment->course_id,
  1179.  
  1180.                 'is_started' => $enrolment->is_started,
  1181.                 'is_completed' => $enrolment->is_completed,
  1182.                 'is_successful' => $enrolment->is_successful,
  1183.                 'is_failed' => $enrolment->is_failed,
  1184.                 'is_manual' => $enrolment->is_manual,
  1185.                 'is_active' => $enrolment->is_active,
  1186.                 'is_deleted' => $enrolment->is_deleted,
  1187.  
  1188.                 'expire_at' => $enrolment->expire_at,
  1189.                 'is_expired' => $enrolment->is_expired
  1190.             );
  1191.            
  1192.             return $this->response(array('success' => 'true', 'result' => $enrolment_details, 'next_registration' => $next_registration));
  1193.  
  1194.         } catch (Exception $e) {
  1195.             return $this->error_response($e->getMessage());
  1196.         }
  1197.  
  1198.     }
  1199.  
  1200.     public function licenses_get($from = null, $limit = null, $page_number = 1) {
  1201.  
  1202.         if($limit == null) $limit = $this->config->item('mobile_api_pagination_limit');
  1203.         if($from == null) {
  1204.             $from = date("Y-m-d H:i:s", 0);
  1205.         } else {
  1206.             $from = urldecode($from);
  1207.         }
  1208.  
  1209.         $from = date("Y-m-d H:i:s", strtotime($from)+1);
  1210.  
  1211.         try {
  1212.  
  1213.             $organisation = Organisation::find_valid_by_id(
  1214.                 $this->current_organisation_id
  1215.             );
  1216.  
  1217.             $page = new Page();
  1218.             $page->set_per_page($limit);
  1219.             $page->set_current_page_number($page_number);
  1220.  
  1221.             $license_search = new LicenseMobileFilteredSearch();
  1222.             $license_search->set_page($page)
  1223.                 ->set_order('updated_at', 'DESC')
  1224.                 ->set_date_updated_from($from)
  1225.                 ->set_is_purchasable()
  1226.                 ->set_organisation($organisation);
  1227.  
  1228.             $license_search->execute();
  1229.  
  1230.             $licenses = array();
  1231.             foreach ($license_search as $license) {
  1232.                 $licenses[] = $license;
  1233.             }
  1234.  
  1235.             $licenses = PurchasableLicenseOrdering::arrange($licenses, "asc");
  1236.  
  1237.             $results = array();
  1238.  
  1239.             $l = sizeof($licenses);
  1240.  
  1241.             for($i = 0; $i < $l; $i++){
  1242.  
  1243.                 $license = $licenses[$i];
  1244.  
  1245.                 $course = $license->course_standard->course;
  1246.  
  1247.                 $module_details = array();
  1248.  
  1249.                 if($license->course_standard != null) {
  1250.                     $course_mobile = $license->course_standard->is_mobile_enabled;
  1251.                 } else {
  1252.                     $course_mobile = 0;
  1253.                 }
  1254.  
  1255.                 if($course_mobile == 0 ){
  1256.                     $non_mobile_inject = "This course is not mobile enabled. You will need to login via the web to take this course.";
  1257.                 } else {
  1258.                     $non_mobile_inject = "";
  1259.                 }
  1260.  
  1261.                 $modules = array();
  1262.  
  1263.                 if($license->course_standard->has_modules()) {
  1264.  
  1265.                     foreach($license->course_standard->course->modules as $module) {
  1266.  
  1267.                         $module_details = array();
  1268.  
  1269.                         $module_details = array(
  1270.                             'id'    => $module->id,
  1271.                             'created_at' => $module->created_at,
  1272.                             'updated_at' => $module->updated_at,
  1273.                             'order' => $module->ordering,
  1274.                             'course_id' => $module->course_id,
  1275.                             'name'  => $module->name,
  1276.                             'description_message'  => $non_mobile_inject.$module->description,//description is a reserved key on iOS hence the miss match of keys here
  1277.                             'completion_message' => $module->completion_message,
  1278.                             'duration' => $module->duration,
  1279.                             'typical_time' => $module->typical_time,
  1280.                             'is_active' => $module->is_active,
  1281.                             'is_deleted' => $module->is_deleted,
  1282.                         );
  1283.  
  1284.                         $modules[] = $module_details;
  1285.                     }    
  1286.                 }
  1287.  
  1288.                 $course_details = array(
  1289.                     'id' => $course->id,
  1290.                     'created_at' => $course->created_at,
  1291.                     'updated_at' => $course->updated_at,
  1292.                     'name'  => $course->name,
  1293.                     'is_active' => $course->is_active,
  1294.                     'is_deleted' => $course->is_deleted,
  1295.                     'module_count' => $course->module_count,
  1296.                     'has_certificate'  => $course->has_certificate,
  1297.                     'expiry_months' => $course->expiry_months,
  1298.                     'image_key' => rtrim(strtr(base64_encode($course->image_key), '+/', '-_'), '='),
  1299.                     'modules' => $modules,
  1300.                     'is_mobile_enabled' => $course_mobile
  1301.                 );
  1302.  
  1303.                 $license_details = array(
  1304.                     'id' => $license->id,
  1305.                     'created_at' => $license->created_at,
  1306.                     'updated_at' => $license->updated_at,
  1307.  
  1308.                     'course_id' => $license->course_standard->course->id,
  1309.  
  1310.                     'is_active' => $license->is_active,
  1311.                     'is_deleted' => $license->is_deleted,
  1312.                     'is_purchasable' => $license->is_purchasable,
  1313.                     'is_auto_enrollable' => $license->is_auto_enrollable,
  1314.                     'quantity' => $license->quantity,
  1315.                     'used' => $license->used,
  1316.                     'available' => $license->available,
  1317.                     'price' => $license->price,
  1318.                     'course' => $course_details
  1319.  
  1320.                 );
  1321.  
  1322.                 array_push($results, $license_details);
  1323.  
  1324.             }
  1325.  
  1326.             return $this->response(array('success' => 'true', 'total_rows' => (int) $l, 'result' => $results));
  1327.  
  1328.         } catch (Exception $e) {
  1329.             return $this->error_response($e->getMessage());
  1330.         }
  1331.  
  1332.     }
  1333.  
  1334.     public function purchase_license_post($license_id){
  1335.  
  1336.         if(!isset($this->_post_json_args->token)) {
  1337.             //return $this->error_response("There has been an issue processing your payment : code(008)");
  1338.             $this->_post_json_args->token = "";
  1339.         }
  1340.  
  1341.         if(!isset($this->_post_json_args->new_card)) $this->_post_json_args->new_card = 0;
  1342.  
  1343.         $token = $this->_post_json_args->token;
  1344.         $new_card = $this->_post_json_args->new_card;
  1345.  
  1346.         Stripe::setApiKey(PAYMENTS_STRIPE_PRIVATE_KEY);
  1347.  
  1348.         try {
  1349.  
  1350.             $member = Member::find_valid_registered_by_id(
  1351.                 $this->member_id
  1352.             );
  1353.  
  1354.             $organisation = Organisation::find_valid_by_id(
  1355.                 $this->current_organisation_id
  1356.             );
  1357.  
  1358.             $license = License::find_by_id_and_organisation_id(
  1359.                 $license_id,
  1360.                 $organisation->id
  1361.             );
  1362.  
  1363.             //check license is purchasable
  1364.  
  1365.             if($member->customer != null) {
  1366.  
  1367.                 $stripe_customer = Stripe_Customer::retrieve($member->customer->stripe_id);
  1368.  
  1369.                 //echo("existing customer");
  1370.  
  1371.                 if($token != "" && $new_card == 1) {
  1372.  
  1373.                     //echo("new card");
  1374.  
  1375.                     $stripe_customer->card = $token;
  1376.                     $stripe_customer->save();
  1377.  
  1378.                 }
  1379.  
  1380.             } else if($new_card == 0 && $token == "") {
  1381.  
  1382.                 return $this->error_response("Your existing card has been removed from ours records please use the pay with a new card form. If your existing card is still valid please feel free to re-enter those details.");
  1383.  
  1384.             } else {
  1385.                 //echo("new customer");
  1386.  
  1387.                 if($token == "") {
  1388.                     return $this->error_response("There has been an issue processing your payment : code(008)");
  1389.                 }
  1390.                 //using token to construct new customer.
  1391.                 $stripe_customer = Stripe_Customer::create(array(
  1392.                         "card" => $token,
  1393.                         "description" => $member->email)
  1394.                 );
  1395.  
  1396.                 $customer = new Customer(array(
  1397.                     'stripe_id' => $stripe_customer->id
  1398.                 ));
  1399.  
  1400.                 $customer->set_member($member);
  1401.  
  1402.                 $customer->save();
  1403.  
  1404.             }
  1405.  
  1406.             $member_licenses_order = new MemberMobileLicenseOrder(
  1407.                 $organisation,
  1408.                 $license,
  1409.                 $member
  1410.             );
  1411.  
  1412.             $member_licenses_order->check_purchasable();
  1413.  
  1414.             Stripe_Charge::create(array(
  1415.                "amount" => $member_licenses_order->get_total_in_cents(), # amount in cents, again
  1416.               "currency" => $member_licenses_order->get_currency(),
  1417.                "customer" => $stripe_customer->id,
  1418.                "description" => "Mobile purchasing ".$member_licenses_order->get_total_items()." course(s)")
  1419.             );
  1420.  
  1421.             $newenrolment = $member_licenses_order->purchase();
  1422.  
  1423.             $emailBody = $this->load->view(
  1424.                 'emails/purchaser/purchaser_mobile_receipt',
  1425.                 array(
  1426.                     'member_licenses_order' => $member_licenses_order,
  1427.                 ),
  1428.                 true
  1429.             );
  1430.                 try {
  1431.                     Email::push(array(
  1432.                         'type' => 'payment-receipt',
  1433.                         'from' => PAYMENTS_RECEIPT_EMAIL_FROM,
  1434.                         'to' => $member->email,
  1435.                         'subject' => "New Payment Receipt on the ".$organisation->name." Academy",
  1436.                         'body' => $emailBody,
  1437.                     ));
  1438.  
  1439.                     Email::push(array(
  1440.                         'type' => 'payment-receipt',
  1441.                         'from' => PAYMENTS_RECEIPT_EMAIL_FROM,
  1442.                         'to' => PAYMENTS_RECEIPT_EMAIL_FROM,
  1443.                         'subject' => "New Payment Receipt on the ".$organisation->name." Academy",
  1444.                         'body' => $emailBody,
  1445.                     ));
  1446.  
  1447.                 } catch (exception $recipt_error) {
  1448.  
  1449.                 }
  1450.  
  1451.             return $this->response(array("success" => "true", "id" => $newenrolment->enrolment_id));
  1452.  
  1453.         } catch(Stripe_CardError $e) {
  1454.             // Since it's a decline, Stripe_CardError will be caught
  1455.             $body = $e->getJsonBody();
  1456.             $err  = $body['error'];
  1457.  
  1458.             /*print('Status is:' . $e->getHttpStatus() . "\n");
  1459.             print('Type is:' . $err['type'] . "\n");
  1460.             print('Code is:' . $err['code'] . "\n");
  1461.             // param is '' in this case
  1462.             print('Param is:' . $err['param'] . "\n");
  1463.             print('Message is:' . $err['message'] . "\n");*/
  1464.  
  1465.             return $this->error_response($err['message']);
  1466.  
  1467.  
  1468.         } catch (Stripe_InvalidRequestError $e) {
  1469.             // Invalid parameters were supplied to Stripe's API
  1470.             //return $this->error_response("There has been an issue processing your payment : code(004) ".$e->getMessage());
  1471.             return $this->error_response("There has been an issue processing your payment : code(004) ");
  1472.  
  1473.         } catch (Stripe_AuthenticationError $e) {
  1474.             // Authentication with Stripe's API failed
  1475.             // (maybe you changed API keys recently)
  1476.             //return $this->error_response("There has been an issue processing your payment : code(005) ".$e->getMessage());
  1477.             return $this->error_response("There has been an issue processing your payment : code(005) ");
  1478.  
  1479.         } catch (Stripe_ApiConnectionError $e) {
  1480.             // Network communication with Stripe failed
  1481.             //return $this->error_response("There has been an issue processing your payment : code(006) ".$e->getMessage());
  1482.             return $this->error_response("There has been an issue processing your payment : code(006) ");
  1483.  
  1484.         } catch (Stripe_Error $e) {
  1485.             // Display a very generic error to the user,
  1486.             //return $this->error_response("There has been an issue processing your payment : code(007) ".$e->getMessage());
  1487.             return $this->error_response("There has been an issue processing your payment : code(007) ");
  1488.  
  1489.         } catch (Exception $e) {
  1490.             // Something else happened, completely unrelated to Stripe
  1491.             return $this->error_response($e->getMessage());
  1492.         }
  1493.  
  1494.     }
  1495.  
  1496.     public function certificates_get($from = null, $limit = null, $page_number = 1) {
  1497.  
  1498.         if($limit == null) $limit = $this->config->item('mobile_api_pagination_limit');
  1499.         if($from == null) {
  1500.             $from = date("Y-m-d H:i:s", 0);
  1501.         } else {
  1502.             $from = urldecode($from);
  1503.         }
  1504.  
  1505.         $from = date("Y-m-d H:i:s", strtotime($from)+1);
  1506.  
  1507.         try {
  1508.  
  1509.             $member = Member::find_valid_registered_by_id(
  1510.                 $this->member_id
  1511.             );
  1512.  
  1513.             $organisation = Organisation::find_valid_by_id(
  1514.                 $this->current_organisation_id
  1515.             );
  1516.  
  1517.             $page = new Page();
  1518.             $page->set_per_page($limit);
  1519.             $page->set_current_page_number($page_number);
  1520.  
  1521.             $cert_search = new EnrolmentMobileFilteredSearch();
  1522.             $cert_search->set_page($page)
  1523.                 ->set_order('updated_at', 'DESC')
  1524.                 ->set_is_completed(1)
  1525.                 ->set_is_successful(1)
  1526.                 ->set_date_filter('updated')
  1527.                 ->set_date_from($from)
  1528.                 ->set_member($member)
  1529.                 ->set_organisation($organisation);
  1530.  
  1531.             $cert_search->execute();
  1532.  
  1533.             $results = array();
  1534.  
  1535.             $l = $cert_search->get_row_per_current_page();
  1536.  
  1537.             for($i = 0; $i < $l; $i++){
  1538.  
  1539.                 $cert = $cert_search[$i];
  1540.  
  1541.                 $course = $cert->course;
  1542.  
  1543.                 $course_details = array(
  1544.                     'id' => $course->id,
  1545.                     'created_at' => $course->created_at,
  1546.                     'updated_at' => $course->updated_at,
  1547.                     'name'  => $course->name,
  1548.                     'is_active' => $course->is_active,
  1549.                     'is_deleted' => $course->is_deleted,
  1550.                     'module_count' => $course->module_count,
  1551.                     'has_certificate'  => $course->has_certificate,
  1552.                     'expiry_months' => $course->expiry_months,
  1553.                     'image_key' => rtrim(strtr(base64_encode($course->image_key), '+/', '-_'), '=')
  1554.  
  1555.                 );
  1556.  
  1557.                 $cert_details = array(
  1558.                     'id' => $cert->id,
  1559.                     'created_at' => $cert->created_at,
  1560.                     'updated_at' => $cert->updated_at,
  1561.                     'started_at' => $cert->started_at,
  1562.                     'completed_at' => $cert->completed_at,
  1563.                     'succeeded_at' => $cert->succeeded_at,
  1564.  
  1565.                     'is_started' => $cert->is_started,
  1566.                     'is_completed' => $cert->is_completed,
  1567.                     'is_successful' => $cert->is_successful,
  1568.                     'is_failed' => $cert->is_failed,
  1569.                     'is_manual' => $cert->is_manual,
  1570.                     'is_active' => $cert->is_active,
  1571.                     'is_deleted' => $cert->is_deleted,
  1572.  
  1573.                     'expire_at' => $cert->expire_at,
  1574.                     'is_expired' => $cert->is_expired,
  1575.  
  1576.                     'course_id' => $cert->course_id,
  1577.                     'course' => $course_details,
  1578.  
  1579.                 );
  1580.  
  1581.                 array_push($results, $cert_details);
  1582.  
  1583.             }
  1584.  
  1585.             return $this->response(array('success' => 'true', 'total_rows' => (int) $l, 'result' => $results));
  1586.  
  1587.         } catch (Exception $e) {
  1588.             return $this->error_response($e->getMessage());
  1589.         }
  1590.  
  1591.     }
  1592.  
  1593.     private function generate_enrolment_certificate($enrolment) {
  1594.  
  1595.         try {
  1596.             $certificate_generator = $enrolment->course->certificate->certificate_generator;
  1597.  
  1598.             $certificate_info = $certificate_generator->store($enrolment);
  1599.  
  1600.             $member_enrolment_certificate = MemberEnrolmentCertificate::create(array(
  1601.                 'member' => $enrolment->member,
  1602.                 'certificate' => $enrolment->course->certificate,
  1603.                 'enrolment_succeeded_at' => $enrolment->succeeded_at,
  1604.                 'expire_at' => $enrolment->expire_at,
  1605.                 'certificate_key' => $certificate_info['key']
  1606.             ));
  1607.             return $member_enrolment_certificate->member_certificate;
  1608.         } catch (Exception $e) {
  1609.  
  1610.             print_r($e->getMessage());
  1611.             exit();
  1612.         }
  1613.     }
  1614.  
  1615.     private function generate_practical_session_certificate($enrolment) {
  1616.         try {
  1617.  
  1618.             $ioc = new IOCContainer();
  1619.             $certificate_generator = $ioc->bind_generator('DefaultStandardCertificate');
  1620.  
  1621.             $certificate_info = $certificate_generator->store($enrolment);
  1622.  
  1623.             $member_practical_session_certificate = MemberPracticalSessionCertificate::create(array(
  1624.                 'member' => $enrolment->member,
  1625.                 'course' => $enrolment->course,
  1626.                 'certificate_key' => $certificate_info['key'],
  1627.                 'enrolment_succeeded_at' => $enrolment->succeeded_at,
  1628.                 'expire_at' => $enrolment->expire_at
  1629.             ));
  1630.  
  1631.             return $member_practical_session_certificate->member_certificate;
  1632.  
  1633.         } catch (Exception $e) {
  1634.             print_r($e->getMessage());
  1635.             exit();
  1636.         }
  1637.     }
  1638.  
  1639.     public function certificate_image_get($enrolment_id) {
  1640.  
  1641.         try {
  1642.  
  1643.             $enrolment = Enrolment::find_undeleted_by_id($enrolment_id);
  1644.             $enrolment->check_is_not_successful();
  1645.             $enrolment->check_is_not_completed();
  1646.  
  1647.             if($enrolment->offline) {
  1648.  
  1649.                 $this->offline_certificate_image_get($enrolment_id);
  1650.             } else {
  1651.  
  1652.                 $member_certificate = MemberCertificate::find_by_member_id_and_course_id(
  1653.                     $enrolment->member->id,
  1654.                     $enrolment->course->id
  1655.                 );
  1656.  
  1657.                 if(!$member_certificate) {
  1658.  
  1659.                     if($enrolment->is_successful && $enrolment->course->has_certificate()) {
  1660.                         $member_certificate = $this->generate_enrolment_certificate($enrolment);
  1661.                     } elseif($enrolment->is_successful() && $enrolment->standard && $enrolment->standard->practical_session_complete) {
  1662.                         $member_certificate = $this->generate_practical_session_certificate($enrolment);
  1663.                     }
  1664.                 }
  1665.  
  1666.                 if($member_certificate->practical_session_certificate) {
  1667.                     $ioc = new IOCContainer();
  1668.                     $certificate_generator = $ioc->bind_generator('DefaultStandardCertificate');
  1669.                 } elseif ($member_certificate->enrolment_certificate) {
  1670.                     $certificate_generator = $member_certificate->enrolment_certificate->certificate->certificate_generator;
  1671.                 }
  1672.  
  1673.                 $certificate_generator->retrieve($member_certificate, "D");
  1674.             }
  1675.         } catch (Exception $e) {
  1676.             return $this->error_response("There has been an error creating your certificate please contact us.: code(015)");
  1677.         }
  1678.     }
  1679.  
  1680.     private function offline_certificate_image_get($enrolment_id, $method = 'attachment') {
  1681.  
  1682.         try {
  1683.  
  1684.             $enrolment_offline = EnrolmentOffline::find_valid_by_enrolment_id($enrolment_id);
  1685.  
  1686.             $member_certificate = MemberCertificate::find_by_member_id_and_course_id(
  1687.                 $enrolment_offline->member->id,
  1688.                 $enrolment_offline->course->id
  1689.             );
  1690.  
  1691.             $certificate_generator = $member_certificate->enrolment_certificate->certificate->certificate_generator;
  1692.  
  1693.             $certificate_generator->retrieve($member_certificate, "D");
  1694.  
  1695.         } catch(Exception $e) {
  1696.  
  1697.             return $this->error_response("There has been an error creating your certificate please contact us.: code(015)");
  1698.         }
  1699.     }
  1700.  
  1701.     public function videos_categories_get($from = null, $limit = null, $page_number = 1) {
  1702.  
  1703.         if($limit == null) $limit = $this->config->item('mobile_api_pagination_limit');
  1704.         if($from == null) {
  1705.             $from = date("Y-m-d H:i:s", 0);
  1706.         } else {
  1707.             $from = urldecode($from);
  1708.         }
  1709.  
  1710.         $from = date("Y-m-d H:i:s", strtotime($from)+1);
  1711.  
  1712.         try {
  1713.  
  1714.             $organisation = Organisation::find_valid_by_id(
  1715.                 $this->current_organisation_id
  1716.             );
  1717.  
  1718.             $page = new Page();
  1719.             $page->set_per_page($limit);
  1720.             $page->set_current_page_number($page_number);
  1721.  
  1722.             $video_categories_search = new VideoCategorySearch();
  1723.             $video_categories_search->set_page($page)
  1724.                 ->set_date_filter('updated')
  1725.                 ->set_date_from($from)
  1726.                 ->set_organisation($organisation);
  1727.  
  1728.             $video_categories_search->execute();
  1729.  
  1730.             $results = array();
  1731.  
  1732.             $l = $video_categories_search->get_row_per_current_page();
  1733.  
  1734.             for($i = 0; $i < $l; $i++){
  1735.  
  1736.                 $video_category = $video_categories_search[$i];
  1737.  
  1738.                 $video_category_result = array(
  1739.                     'id' => $video_category->id,
  1740.                     'created_at' => $video_category->created_at,
  1741.                     'updated_at' => $video_category->updated_at,
  1742.  
  1743.                     'name'      => $video_category->name,
  1744.  
  1745.                     'is_active' => $video_category->is_active,
  1746.                     'is_deleted' => $video_category->is_deleted,
  1747.  
  1748.                 );
  1749.  
  1750.                 array_push($results, $video_category_result);
  1751.  
  1752.             }
  1753.  
  1754.             return $this->response(array('success' => 'true', 'total_rows' => (int) $l, 'result' => $results));
  1755.  
  1756.         } catch (Exception $e) {
  1757.             return $this->error_response($e->getMessage());
  1758.         }
  1759.  
  1760.     }
  1761.  
  1762.     public function videos_get($from = null, $limit = null, $page_number = 1) {
  1763.  
  1764.         if($limit == null) $limit = $this->config->item('mobile_api_pagination_limit');
  1765.         if($from == null) {
  1766.             $from = date("Y-m-d H:i:s", 0);
  1767.         } else {
  1768.             $from = urldecode($from);
  1769.         }
  1770.  
  1771.         $from = date("Y-m-d H:i:s", strtotime($from)+1);
  1772.  
  1773.         try {
  1774.  
  1775.             $client = Service::factory(array(
  1776.                 'client_id' => VIDEO_SERVICE_CLIENT_ID,
  1777.                 'client_secret_key' =>  VIDEO_SERVICE_CLIENT_SECRET_KEY,
  1778.             ));
  1779.  
  1780.             $organisation = Organisation::find_valid_by_id(
  1781.                 $this->current_organisation_id
  1782.             );
  1783.  
  1784.             $page = new Page();
  1785.             $page->set_per_page($limit);
  1786.             $page->set_current_page_number($page_number);
  1787.  
  1788.             $videos_search = new VideoSearch();
  1789.             $videos_search->set_page($page)
  1790.                 ->set_date_filter('updated')
  1791.                 ->set_date_from($from)
  1792.                 ->set_is_uploaded(1)
  1793.                 ->set_organisation($organisation);
  1794.  
  1795.             $videos_search->execute();
  1796.  
  1797.             $results = array();
  1798.  
  1799.             $l = $videos_search->get_row_per_current_page();
  1800.  
  1801.             for($i = 0; $i < $l; $i++){
  1802.  
  1803.                 $video = $videos_search[$i];
  1804.  
  1805.                 try {
  1806.  
  1807.                     $olive_media_video = Service::find_by_id($client, $video->olive_video_id);
  1808.  
  1809.                     $video_url = $olive_media_video['data']['hls_url'];
  1810.                     $renditions = $olive_media_video['data']['mp4_renditions'];
  1811.  
  1812.                     $deleted =  $video->is_deleted;
  1813.  
  1814.                 } catch(Exception $e) {
  1815.  
  1816.                     $video_url = "";
  1817.                     $renditions = "";
  1818.  
  1819.                     $deleted = 1;
  1820.                 }
  1821.  
  1822.                 $video = array(
  1823.                         'id' => $video->id,
  1824.                         'created_at' => $video->created_at,
  1825.                         'updated_at' => $video->updated_at,
  1826.                         'published_at' => $video->published_at,
  1827.                         'video_category_id' => $video->video_category_id,
  1828.  
  1829.                         'name' => $video->name,
  1830.                         'description' => $video->description,
  1831.                         'olive_id' => $video->olive_video_id,
  1832.  
  1833.                         'is_uploaded' => $video->is_uploaded,
  1834.                         'is_rendition_complete' => $video->is_rendition_complete,
  1835.                         'is_published' => $video->is_published,
  1836.                         'is_active' => $video->is_active,
  1837.                         'is_deleted' => $deleted,
  1838.  
  1839.                         'video_url' => $video_url,
  1840.                         'renditions' => $renditions
  1841.  
  1842.                         );
  1843.  
  1844.                     array_push($results, $video);
  1845.  
  1846.  
  1847.             }
  1848.  
  1849.             return $this->response(array('success' => 'true', 'total_rows' => (int) $l, 'result' => $results));
  1850.  
  1851.         } catch (Exception $e) {
  1852.             return $this->error_response($e->getMessage());
  1853.         }
  1854.  
  1855.     }
  1856.  
  1857.     public function audits_get($from = null, $limit = null, $page_number = 1) {
  1858.  
  1859.         if($limit == null) $limit = $this->config->item('mobile_api_pagination_limit');
  1860.         if($from == null) {
  1861.             $from = date("Y-m-d H:i:s", 0);
  1862.         } else {
  1863.             $from = urldecode($from);
  1864.         }
  1865.  
  1866.         $from = date("Y-m-d H:i:s", strtotime($from)+1);
  1867.  
  1868.         try {
  1869.  
  1870.             $organisation = Organisation::find_valid_by_id(
  1871.                 $this->current_organisation_id
  1872.             );
  1873.  
  1874.             $page = new Page();
  1875.             $page->set_per_page($limit);
  1876.             $page->set_current_page_number($page_number);
  1877.  
  1878.             $audit_search = new AuditFormSearch();
  1879.             $audit_search
  1880.                 ->set_page($page)
  1881.                 ->set_date_filter('updated')
  1882.                 ->set_is_published(1)
  1883.                 ->set_date_from($from)
  1884.                 ->set_organisation($organisation);
  1885.  
  1886.             $audit_search->execute();
  1887.  
  1888.             $results = array();
  1889.  
  1890.             $l = $audit_search->get_row_per_current_page();
  1891.  
  1892.             for($i = 0; $i < $l; $i++){
  1893.  
  1894.                 $audit = $audit_search[$i];
  1895.  
  1896.                 $audit_details = array(
  1897.                     'id' => $audit->id,
  1898.                     'name' => $audit->name,
  1899.                     'created_at' => $audit->created_at,
  1900.                     'updated_at' => $audit->updated_at,
  1901.                     'is_deleted' => $audit->is_deleted,
  1902.                     'is_published' => $audit->is_published,
  1903.                     'is_active' => $audit->is_active
  1904.                 );
  1905.  
  1906.                 array_push($results, $audit_details);
  1907.  
  1908.             }
  1909.  
  1910.             return $this->response(array('success' => 'true', 'total_rows' => (int) $audit_search->total_rows, 'result' => $results));
  1911.  
  1912.         } catch (Exception $e) {
  1913.             return $this->error_response($e->getMessage());
  1914.         }
  1915.  
  1916.     }
  1917.  
  1918.     public function member_documents_get($from = null, $limit = null, $page_number = 1) {
  1919.  
  1920.         if($limit == null) $limit = $this->config->item('mobile_api_pagination_limit');
  1921.         if($from == null) {
  1922.             $from = date("Y-m-d H:i:s", 0);
  1923.         } else {
  1924.             $from = urldecode($from);
  1925.         }
  1926.  
  1927.         $from = date("Y-m-d H:i:s", strtotime($from)+1);
  1928.  
  1929.         try {
  1930.  
  1931.             $member = Member::find_valid_registered_by_id(
  1932.                 $this->member_id
  1933.             );
  1934.  
  1935.             $organisation = Organisation::find_valid_by_id(
  1936.                 $this->current_organisation_id
  1937.             );
  1938.  
  1939.             $page = new Page();
  1940.             $page->set_per_page($limit);
  1941.             $page->set_current_page_number($page_number);
  1942.  
  1943.             $document_search = new MemberDocumentSearch();
  1944.             $document_search->set_page($page)
  1945.                 ->set_date_filter('updated')
  1946.                 ->set_date_from($from)
  1947.                 ->set_member($member);
  1948.  
  1949.             $document_search->execute();
  1950.  
  1951.             $results = array();
  1952.  
  1953.             $l = $document_search->get_row_per_current_page();
  1954.  
  1955.             for($i = 0; $i < $l; $i++){
  1956.  
  1957.                 $member_document = $document_search[$i];
  1958.  
  1959.                 $document = $member_document->document;
  1960.  
  1961.                 $document_details = array(
  1962.                     'id' => $document->id,
  1963.                     'name' => $document->name,
  1964.                     'created_at' => $document->created_at,
  1965.                     'updated_at' => $document->updated_at,
  1966.                     'is_deleted' => $document->is_deleted,
  1967.                     'is_required' => $document->is_required,
  1968.                     'is_active' => $document->is_active
  1969.                 );
  1970.  
  1971.                 $member_document_details = array(
  1972.                     'id' => $member_document->id,
  1973.                     'created_at' => $member_document->created_at,
  1974.                     'updated_at' => $member_document->updated_at,
  1975.                     'is_deleted' => $member_document->is_deleted,
  1976.                     'is_active' => $member_document->is_active,
  1977.                     'is_expired' => $member_document->is_expired,
  1978.  
  1979.                     'expires_at' => $member_document->expires_at,
  1980.  
  1981.                     'document_key' => rtrim(strtr(base64_encode($member_document->document_key), '+/', '-_'), '='),
  1982.  
  1983.                     'document_id' => $member_document->document_id,
  1984.                     'document' => $document_details
  1985.  
  1986.                 );
  1987.  
  1988.                 array_push($results, $member_document_details);
  1989.  
  1990.             }
  1991.  
  1992.             return $this->response(array('success' => 'true', 'total_rows' => (int) $l, 'result' => $results));
  1993.  
  1994.         } catch (Exception $e) {
  1995.             return $this->error_response($e->getMessage());
  1996.         }
  1997.     }
  1998.  
  1999.     public function member_document_post() {
  2000.  
  2001.         if(!isset($this->_post_json_args->document_id)) $this->_post_json_args->document_id = null;
  2002.         if(!isset($this->_post_json_args->expires_at)) $this->_post_json_args->expires_at = null;
  2003.  
  2004.         try {
  2005.  
  2006.             $member = Member::find_valid_registered_by_id(
  2007.                 $this->member_id
  2008.             );
  2009.  
  2010.             $document = Document::find_valid_by_id(
  2011.                 $this->_post_json_args->document_id
  2012.             );
  2013.  
  2014.             $member_document = MemberDocument::create(array(
  2015.                 'member' => $member,
  2016.                 'expires_at' => $this->_post_json_args->expires_at,
  2017.                 'document' => $document
  2018.             ));
  2019.  
  2020.             $member_document->save();
  2021.  
  2022.             return $this->response(array("success" => "true", "id" => $member_document->id));
  2023.  
  2024.         } catch (Exception $e) {
  2025.             return $this->error_response("There has been an error creating your certificate please contact us.: code(016)");
  2026.             //return $this->error_response($e->getMessage());
  2027.         }
  2028.  
  2029.     }
  2030.  
  2031.     public function member_document_image_post($member_document_id) {
  2032.  
  2033.         if(!isset($this->_post_json_args->imagedata)) return $this->error_response("Image data required");
  2034.  
  2035.         try {
  2036.  
  2037.             $member = Member::find_valid_registered_by_id(
  2038.                 $this->member_id
  2039.             );
  2040.  
  2041.             $member_document = MemberDocument::find_valid_by_id(
  2042.                 $member_document_id
  2043.             );
  2044.  
  2045.             if($member_document->member_id != $this->member_id) return $this->error_response("This document does not belong to the current user.");
  2046.  
  2047.             $member_document_image_temp = new SplFileObject('/tmp/member_document_'.$this->member_id.'_image.jpeg', 'w+');
  2048.  
  2049.             $member_document_image_temp->fwrite(base64_decode($this->_post_json_args->imagedata));
  2050.  
  2051.             $s3_client = \Aws\S3\S3Client::factory(array(
  2052.                 'key'    => AWS_S3_ACCESS_KEY,
  2053.                 'secret' => AWS_S3_SECRET_KEY,
  2054.                 'region' => 'us-east-1'
  2055.             ));
  2056.  
  2057.             $key_base_path = $member->base_path;
  2058.  
  2059.             $hash = md5(uniqid(rand(), true));
  2060.  
  2061.             $key = $key_base_path.$hash.'.jpeg';
  2062.  
  2063.             $key = new AcademyHQ\S3\Key($key);
  2064.  
  2065.             $image_upload = new AcademyHQ\S3\Image\Factory($s3_client, AWS_S3_ASSETS_BUCKET);
  2066.  
  2067.             $image = $image_upload->create($key, $member_document_image_temp);
  2068.  
  2069.             $member_document->document_key = $image->get_reference()->get_key()->to_string();
  2070.  
  2071.             $member_image_temp = null;
  2072.  
  2073.             unlink('/tmp/member_document_'.$this->member_id.'_image.jpeg');
  2074.  
  2075.             $member_document->save();
  2076.  
  2077.             return $this->response(array("success" => "true", "document_key" => rtrim(strtr(base64_encode($member_document->document_key), '+/', '-_'), '=')));
  2078.  
  2079.         } catch (Exception $e) {
  2080.             //return $this->error_response($e->getMessage());//DEV returns all aws errors as well (these should not go to the app.
  2081.             return $this->error_response("There was an error accepting your image please contact us. : code(008)");
  2082.         }
  2083.  
  2084.     }
  2085.  
  2086.     public function member_audits_get($from = null, $limit = null, $page_number = 1) {
  2087.  
  2088.         if($limit == null) $limit = $this->config->item('mobile_api_pagination_limit');
  2089.         if($from == null) {
  2090.             $from = date("Y-m-d H:i:s", 0);
  2091.         } else {
  2092.             $from = urldecode($from);
  2093.         }
  2094.  
  2095.         $from = date("Y-m-d H:i:s", strtotime($from)+1);
  2096.  
  2097.         try {
  2098.  
  2099.             $member = Member::find_valid_registered_by_id(
  2100.                 $this->member_id
  2101.             );
  2102.  
  2103.             $organisation = Organisation::find_valid_by_id(
  2104.                 $this->current_organisation_id
  2105.             );
  2106.  
  2107.             $page = new Page();
  2108.             $page->set_per_page($limit);
  2109.             $page->set_current_page_number($page_number);
  2110.  
  2111.             $member_audit_search = new MemberAuditFormSearch();
  2112.             $member_audit_search->set_page($page)
  2113.                 ->set_date_filter('updated')
  2114.                 ->set_is_submitted(1)
  2115.                 ->set_date_from($from)
  2116.                 ->set_member($member);
  2117.  
  2118.             $member_audit_search->execute();
  2119.  
  2120.             $results = array();
  2121.  
  2122.             $l = $member_audit_search->get_row_per_current_page();
  2123.  
  2124.             for($i = 0; $i < $l; $i++){
  2125.  
  2126.                 $member_audit = $member_audit_search[$i];
  2127.  
  2128.                 $audit = $member_audit->audit_form;
  2129.  
  2130.                 $audit_details = array(
  2131.                     'id' => $audit->id,
  2132.                     'name' => $audit->name,
  2133.                     'created_at' => $audit->created_at,
  2134.                     'updated_at' => $audit->updated_at,
  2135.                     'is_deleted' => $audit->is_deleted,
  2136.                     'is_published' => $audit->is_published,
  2137.                     'is_active' => $audit->is_active
  2138.                 );
  2139.  
  2140.                 $member_audit_details = array(
  2141.                     'id' => $member_audit->id,
  2142.                     'created_at' => $member_audit->created_at,
  2143.                     'updated_at' => $member_audit->updated_at,
  2144.                     'submitted_at' => $member_audit->submitted_at,
  2145.                     'is_deleted' => $member_audit->is_deleted,
  2146.                     'is_active' => $member_audit->is_active,
  2147.                     'is_submitted' => $member_audit->is_submitted,
  2148.  
  2149.                     'audit_id' => $member_audit->audit_form_id,
  2150.                     'audit' => $audit_details,
  2151.  
  2152.                 );
  2153.  
  2154.                 array_push($results, $member_audit_details);
  2155.  
  2156.             }
  2157.  
  2158.             return $this->response(array('success' => 'true', 'total_rows' => (int) $member_audit_search->total_rows, 'result' => $results));
  2159.  
  2160.         } catch (Exception $e) {
  2161.             return $this->error_response($e->getMessage());
  2162.         }
  2163.  
  2164.     }
  2165.  
  2166.     public function member_audit_get($audit_form_id) {
  2167.  
  2168.         try {
  2169.  
  2170.             $member = Member::find_valid_registered_by_id(
  2171.                 $this->member_id
  2172.             );
  2173.  
  2174.             $callback_url = "http://auditexitcallback/";
  2175.  
  2176.             $audit_form = AuditForm::find_valid_by_id($audit_form_id);
  2177.  
  2178.             $existing_member_audit_form = new MemberAuditFormSearch();
  2179.  
  2180.             $page = new Page();
  2181.             $page->set_per_page(1);
  2182.             $page->set_current_page_number(1);
  2183.  
  2184.             $existing_member_audit_form->set_page($page)
  2185.                 ->set_member($member)
  2186.                 ->set_audit_form($audit_form)
  2187.                 ->set_is_submitted(0);
  2188.             $existing_member_audit_form->execute();
  2189.  
  2190.             $l = $existing_member_audit_form->get_row_per_current_page();
  2191.  
  2192.             if($l > 0 ) {
  2193.  
  2194.                 $member_audit_form = $existing_member_audit_form[0];
  2195.  
  2196.             } else {
  2197.                 $member_audit_form = MemberAuditForm::create(array(
  2198.                     'audit_form' => $audit_form,
  2199.                     'member' => $member,
  2200.                     'form_data' => $audit_form->form_element,
  2201.                 ));
  2202.             }
  2203.  
  2204.             $member_audit_form_token = MemberAuditFormTokenFactory::create($member_audit_form);
  2205.  
  2206.             $member_audit_form->check_is_submitted();
  2207.  
  2208.             $member_audit_form_service = new \MemberAuditFormService($member_audit_form_token->token);
  2209.             $launch_url = $member_audit_form_service->get_launch_url(
  2210.                 $callback_url,
  2211.                 $member
  2212.             );
  2213.  
  2214.             return $this->response(array("success" => "true", "id" => $member_audit_form->id, "launch_url" => $launch_url));
  2215.  
  2216.         } catch(Exception $e) {
  2217.             return $this->error_response($e->getMessage());
  2218.         }
  2219.     }
  2220.  
  2221.     public function member_audit_view_get($member_audit_form_id) {
  2222.  
  2223.         try {
  2224.  
  2225.             $member = Member::find_valid_registered_by_id(
  2226.                 $this->member_id
  2227.             );
  2228.  
  2229.             $member_audit_form = MemberAuditForm::find_valid_by_id_and_member_id(
  2230.                 $member_audit_form_id,
  2231.                 $member->id
  2232.             );
  2233.  
  2234.             $callback_url = "http://auditexitcallback/";
  2235.  
  2236.             $member_audit_form->check_is_not_submitted();
  2237.  
  2238.             $member_audit_form_token = MemberAuditFormTokenFactory::create($member_audit_form);
  2239.  
  2240.             $member_audit_form_service = new \MemberAuditFormService($member_audit_form_token->token);
  2241.             $launch_url = $member_audit_form_service->get_view_url(
  2242.                 $callback_url,
  2243.                 $member
  2244.             );
  2245.  
  2246.             return $this->response(array("success" => "true", "view_url" => $launch_url));
  2247.  
  2248.         } catch(Exception $e) {
  2249.             return $this->error_response($e->getMessage());
  2250.         }
  2251.     }
  2252.  
  2253.     public function records_member_details_get($member_id) {
  2254.  
  2255.         try {
  2256.  
  2257.             $requesting_member = Member::find_valid_registered_by_id(
  2258.                 $this->member_id
  2259.             );
  2260.  
  2261.             if(!$requesting_member->is_trainer()  && !$requesting_member->is_admin()  && !$requesting_member->is_super_admin() && !$requesting_member->is_site_manager()) {
  2262.                 return $this->error_response("User roles not valid");
  2263.             }
  2264.  
  2265.             $member = Member::find_valid_registered_by_id(
  2266.                 $member_id
  2267.             );
  2268.  
  2269.             $requesting_orgs = $requesting_member->organisation->get_all_organisation_ids();
  2270.  
  2271.             if(!in_array($member->organisation->id, $requesting_orgs))  {
  2272.                 return $this->error_response("User not a member of requesting admins organisation");
  2273.             }
  2274.  
  2275.             /*if($requesting_member->organisation->id != $member->organisation->id ) {
  2276.                 return $this->error_response("User not a member of requesting admins organisation");
  2277.             }*/
  2278.  
  2279.             /*$total_documents = MemberDocument::count_valid_by_member_id(
  2280.                 $member_id
  2281.             );*/
  2282.  
  2283.             $page = new Page();
  2284.             $page->set_per_page(10);
  2285.             $page->set_current_page_number(1);
  2286.  
  2287.             $document_search = new MemberDocumentSearch();
  2288.             $document_search->set_page($page)
  2289.                 ->set_date_filter('updated')
  2290.                 ->set_member($member)
  2291.                 ->set_is_active(1)
  2292.                 ->set_is_deleted(0)
  2293.                 ->set_is_document_active(1)
  2294.                 ->set_is_document_deleted(0);
  2295.  
  2296.             $document_search->execute();
  2297.  
  2298.             $cert_search = new EnrolmentMobileFilteredSearch();
  2299.             $cert_search->set_page($page)
  2300.                 ->set_order('updated_at', 'DESC')
  2301.                 ->set_is_completed(1)
  2302.                 ->set_is_successful(1)
  2303.                 ->set_has_certificate(1)
  2304.                 ->set_is_active(1)
  2305.                 ->set_is_deleted(0)
  2306.                 ->set_is_course_active(1)
  2307.                 ->set_is_course_deleted(0)
  2308.                 ->set_member($member);
  2309.  
  2310.             $cert_search->execute();
  2311.  
  2312.             $total_certificates = $cert_search->get_total_rows();
  2313.             $total_documents = $document_search->get_total_rows();
  2314.  
  2315.  
  2316.             /*$total_certificates = Enrolment::count_valid_by_member_id_and_is_completed_and_is_successful(
  2317.                 $member_id,
  2318.                 1,
  2319.                 1
  2320.             );*/
  2321.  
  2322.             return $this->response(array('success' => 'true', 'result' => array(
  2323.                 'id' => $member->id,
  2324.                 'is_verified' => ($member->is_verified()) ? true : false,
  2325.                 'verification_stage' => $member->verification_stage,
  2326.                 'first_name' => $member->first_name,
  2327.                 'last_name' => $member->last_name,
  2328.                 'email' => $member->email,
  2329.                 'username' => ($member->is_registered()) ? $member->user->username : null,
  2330.                 'mobile_number' => $member->mobile_number,
  2331.                 'mobile_country_code' => $member->country_code,
  2332.                 'created_at' => $member->created_at,
  2333.                 'updated_at' => $member->updated_at,
  2334.                 'documents_total' => $total_documents,
  2335.                 'certificates_total' => $total_certificates,
  2336.                 'image_key' => rtrim(strtr(base64_encode($member->image_key), '+/', '-_'), '=')
  2337.             )));
  2338.  
  2339.         } catch (Exception $e) {
  2340.             return $this->error_response($e->getMessage());
  2341.         }
  2342.  
  2343.     }
  2344.  
  2345.     public function records_member_documents_get($member_id, $from = null, $limit = null, $page_number = 1) {
  2346.  
  2347.         if($limit == null) $limit = $this->config->item('mobile_api_pagination_limit');
  2348.         if($from == null) {
  2349.             $from = date("Y-m-d H:i:s", 0);
  2350.         } else {
  2351.             $from = urldecode($from);
  2352.         }
  2353.  
  2354.         $from = date("Y-m-d H:i:s", strtotime($from)+1);
  2355.  
  2356.         try {
  2357.  
  2358.             $requesting_member = Member::find_valid_registered_by_id(
  2359.                 $this->member_id
  2360.             );
  2361.  
  2362.             if(!$requesting_member->is_trainer()  && !$requesting_member->is_admin()  && !$requesting_member->is_super_admin() && !$requesting_member->is_site_manager()) {
  2363.                 return $this->error_response("User roles not valid");
  2364.             }
  2365.  
  2366.             $member = Member::find_valid_registered_by_id(
  2367.                 $member_id
  2368.             );
  2369.  
  2370.             $organisation = Organisation::find_valid_by_id(
  2371.                 $this->current_organisation_id
  2372.             );
  2373.  
  2374.             $page = new Page();
  2375.             $page->set_per_page($limit);
  2376.             $page->set_current_page_number($page_number);
  2377.  
  2378.             $document_search = new MemberDocumentSearch();
  2379.             $document_search->set_page($page)
  2380.                 ->set_date_filter('updated')
  2381.                 ->set_date_from($from)
  2382.                 ->set_member($member);
  2383.  
  2384.             $document_search->execute();
  2385.  
  2386.             $results = array();
  2387.  
  2388.             $l = $document_search->get_row_per_current_page();
  2389.  
  2390.             for($i = 0; $i < $l; $i++){
  2391.  
  2392.                 $member_document = $document_search[$i];
  2393.  
  2394.                 $document = $member_document->document;
  2395.  
  2396.                 $document_details = array(
  2397.                     'id' => $document->id,
  2398.                     'name' => $document->name,
  2399.                     'created_at' => $document->created_at,
  2400.                     'updated_at' => $document->updated_at,
  2401.                     'is_deleted' => $document->is_deleted,
  2402.                     'is_required' => $document->is_required,
  2403.                     'is_active' => $document->is_active
  2404.                 );
  2405.  
  2406.                 $member_document_details = array(
  2407.                     'id' => $member_document->id,
  2408.                     'created_at' => $member_document->created_at,
  2409.                     'updated_at' => $member_document->updated_at,
  2410.                     'is_deleted' => $member_document->is_deleted,
  2411.                     'is_active' => $member_document->is_active,
  2412.                     'is_expired' => $member_document->is_expired,
  2413.  
  2414.                     'expires_at' => $member_document->expires_at,
  2415.  
  2416.                     'document_key' =>  rtrim(strtr(base64_encode($member_document->document_key), '+/', '-_'), '='),
  2417.  
  2418.                     'document_id' => $member_document->document_id,
  2419.                     'document' => $document_details,
  2420.  
  2421.                 );
  2422.  
  2423.                 array_push($results, $member_document_details);
  2424.  
  2425.             }
  2426.  
  2427.             return $this->response(array('success' => 'true', 'total_rows' => (int) $l, 'result' => $results));
  2428.  
  2429.         } catch (Exception $e) {
  2430.             return $this->error_response($e->getMessage());
  2431.         }
  2432.  
  2433.     }
  2434.  
  2435.     public function records_member_certificates_get($member_id, $from = null, $limit = null, $page_number = 1) {
  2436.  
  2437.         if($limit == null) $limit = $this->config->item('mobile_api_pagination_limit');
  2438.         if($from == null) {
  2439.             $from = date("Y-m-d H:i:s", 0);
  2440.         } else {
  2441.             $from = urldecode($from);
  2442.         }
  2443.  
  2444.         $from = date("Y-m-d H:i:s", strtotime($from)+1);
  2445.  
  2446.         try {
  2447.  
  2448.             $requesting_member = Member::find_valid_registered_by_id(
  2449.                 $this->member_id
  2450.             );
  2451.  
  2452.             if(!$requesting_member->is_trainer()  && !$requesting_member->is_admin()  && !$requesting_member->is_super_admin() && !$requesting_member->is_site_manager()) {
  2453.                 return $this->error_response("User roles not valid");
  2454.             }
  2455.  
  2456.             $member = Member::find_valid_registered_by_id(
  2457.                 $member_id
  2458.             );
  2459.  
  2460.             $organisation = Organisation::find_valid_by_id(
  2461.                 $this->current_organisation_id
  2462.             );
  2463.  
  2464.             $page = new Page();
  2465.             $page->set_per_page($limit);
  2466.             $page->set_current_page_number($page_number);
  2467.  
  2468.             $cert_search = new EnrolmentMobileFilteredSearch();
  2469.             $cert_search->set_page($page)
  2470.                 ->set_order('updated_at', 'DESC')
  2471.                 ->set_is_completed(1)
  2472.                 ->set_is_successful(1)
  2473.                 ->set_has_certificate(1)
  2474.                 ->set_is_active(1)
  2475.                 ->set_is_deleted(0)
  2476.                 ->set_is_course_active(1)
  2477.                 ->set_is_course_deleted(0)
  2478.                 ->set_date_filter('updated')
  2479.                 ->set_date_from($from)
  2480.                 ->set_member($member)
  2481.                 ->set_organisation($member->organisation);
  2482.  
  2483.             $cert_search->execute();
  2484.  
  2485.             $results = array();
  2486.  
  2487.             $l = $cert_search->get_row_per_current_page();
  2488.  
  2489.             for($i = 0; $i < $l; $i++){
  2490.  
  2491.                 $cert = $cert_search[$i];
  2492.  
  2493.                 $course = $cert->course;
  2494.  
  2495.                 $course_details = array(
  2496.                     'id' => $course->id,
  2497.                     'created_at' => $course->created_at,
  2498.                     'updated_at' => $course->updated_at,
  2499.                     'name'  => $course->name,
  2500.                     'is_active' => $course->is_active,
  2501.                     'is_deleted' => $course->is_deleted,
  2502.                     'module_count' => $course->module_count,
  2503.                     'has_certificate'  => $course->has_certificate,
  2504.                     'expiry_months' => $course->expiry_months
  2505.  
  2506.                 );
  2507.  
  2508.                 $cert_details = array(
  2509.                     'id' => $cert->id,
  2510.                     'created_at' => $cert->created_at,
  2511.                     'updated_at' => $cert->updated_at,
  2512.                     'started_at' => $cert->started_at,
  2513.                     'completed_at' => $cert->completed_at,
  2514.                     'succeeded_at' => $cert->succeeded_at,
  2515.  
  2516.                     'is_started' => $cert->is_started,
  2517.                     'is_completed' => $cert->is_completed,
  2518.                     'is_successful' => $cert->is_successful,
  2519.                     'is_failed' => $cert->is_failed,
  2520.                     'is_manual' => $cert->is_manual,
  2521.                     'is_active' => $cert->is_active,
  2522.                     'is_deleted' => $cert->is_deleted,
  2523.  
  2524.                     'expire_at' => $cert->expire_at,
  2525.                     'is_expired' => $cert->is_expired,
  2526.  
  2527.                     'course_id' => $cert->course_id,
  2528.                     'course' => $course_details,
  2529.  
  2530.                 );
  2531.  
  2532.                 array_push($results, $cert_details);
  2533.  
  2534.             }
  2535.  
  2536.             return $this->response(array('success' => 'true', 'total_rows' => (int) $l, 'result' => $results));
  2537.  
  2538.         } catch (Exception $e) {
  2539.             return $this->error_response($e->getMessage());
  2540.         }
  2541.  
  2542.     }
  2543.  
  2544.     public function image_get($key, $width = null, $height = null) {
  2545.  
  2546.         try {
  2547.  
  2548.             $member = Member::find_valid_registered_by_id(
  2549.                 $this->member_id
  2550.             );
  2551.  
  2552.             $key = base64_decode(str_pad(strtr($key, '-_', '+/'), strlen($key) % 4, '=', STR_PAD_RIGHT));
  2553.  
  2554.             $ext = substr(strrchr($key,'.'),1);
  2555.  
  2556.             $image_temp_name = 'member_'.$member->id.'_at_'.time().'_image'.$ext;
  2557.  
  2558.             $image_temp = new SplFileObject('/tmp/'.$image_temp_name, 'w+');
  2559.  
  2560.             $key = new AcademyHQ\S3\Key($key);
  2561.  
  2562.             $aws = \Aws\Common\Aws::factory(APPPATH.'config/aws.php');
  2563.             $s3_client = $aws->get('S3');
  2564.  
  2565.             $image_download = new \AcademyHQ\S3\Image\Factory($s3_client, AWS_S3_ASSETS_BUCKET);
  2566.  
  2567.             $image = $image_download->get_by_key($key, $image_temp);
  2568.  
  2569.  
  2570.             if(((isset($width) && $width != -1) && $height == -1)) {
  2571.  
  2572.                 $resizer_nocrop = new \AcademyHQ\S3\Image\ResizerWithoutCropping($image);
  2573.  
  2574.                 $info = @getimagesize($image->get_image()->getRealPath());
  2575.  
  2576.                 if($width < $info[0]) {
  2577.  
  2578.                     $resizer_nocrop->set_width($width);
  2579.  
  2580.                     $resizer_nocrop->set_height($info[1]*($width/$info[0]));
  2581.  
  2582.                 }
  2583.  
  2584.                 $display_file = $resizer_nocrop->resize_image();
  2585.  
  2586.             } else {
  2587.  
  2588.                 $resizer = new \AcademyHQ\S3\Image\Resizer($image);
  2589.  
  2590.                 if(isset($width) && $width != -1) {
  2591.                     $resizer->set_width($width);
  2592.                 }
  2593.                 if(isset($height) && $height != -1) {
  2594.                     $resizer->set_height($height);
  2595.                 }
  2596.  
  2597.                 $display_file = $resizer->resize_image();
  2598.  
  2599.             }
  2600.  
  2601.  
  2602.             //header('HTTP/1.1: ' . 200);
  2603.             //header('Status: ' . 200);
  2604.             header("Content-Type: image/".$ext);
  2605.             //header("Content-Length: " . $display_file->getSize());
  2606.  
  2607.             $display_file->fpassthru();
  2608.  
  2609.             $image_temp = null;
  2610.  
  2611.             unlink('/tmp/'.$image_temp_name);
  2612.  
  2613.         } catch (Exception $e) {
  2614.             return $this->error_response($e->getMessage());
  2615.         }
  2616.  
  2617.     }
  2618.  
  2619.  
  2620. }
Add Comment
Please, Sign In to add comment