<?php
  //All data will be returned as JSON
  header('Content-Type: application/json');

  //Allow any domain to access the API.
  header("Access-Control-Allow-Origin: *");
  header('Access-Control-Allow-Credentials: true');
  header('Access-Control-Allow-Methods: GET,POST,OPTIONS,DELETE,PUT');
  
  //Do not allow caching of content
  header('Access-Control-Max-Age: 0');    // cache for 1 day

  include("lib/viewer_functions.php");
 include("plugins/geocoder/geocoder_CUSTOM.php");


  $GLOBALS['CHECK_FACEBOOK_ACCOUNT']   = 60 * 60 * 2; //How often we should confirm the Facebook oauth key is accurate.
  $GLOBALS['API_SEARCH_FIELDS']        = array('listings.`name`', "listings.`address_1`", 'listings.`type`', 'listings.`cuisine`', "reviews.`tip_content`");
  $GLOBALS['DEFAULT_EXPORT_FIELDS']    = ['members.total_shares', 'members.rank', 'members.photos', 'members.points', 'members.check_ins', 'members.reviews', 'members.badges', 'members.followers', 'members.following', 'members.coupons' ];
  $GLOBALS['API_SHORTERNED_URL']       = "https://urbanhal.al";
  $GLOBALS['API_MAX_SMS_PROMOTE']      = 100; //The number of times a single user can send promotional SMS messages.

  //Check if requied plugins are installed, throw errors if not.
  if(!isset($GLOBALS['WEBSITE_MEMBERSHIP_PLUGIN']))                            { trigger_error("Website membership plugin not installed.\r\n", E_USER_WARNING); exit; }
  if(!isset($GLOBALS['FACEBOOK_LOGIN_PLUGIN']))                                { trigger_error("Facebook login plugin not installed.\r\n", E_USER_WARNING); exit; }
  if(!@$GLOBALS['FACEBOOKAPI_APP_ID'])                                         { trigger_error("Facebook App ID not set in facebook login plugin.", E_USER_WARNING); exit; } 
  if(!@$GLOBALS['FACEBOOKAPI_APP_SECRET'])                                     { trigger_error("Facebook App Secret not set in facebook login plugin.", E_USER_WARNING); exit; } 
  if(!isset($_SERVER['HTTPS']) && !endsWith('cmsb.me', $_SERVER['HTTP_HOST'])) { echo "You can only access the API via HTTPS!\r\n"; trigger_error("You must access this API via HTTPS", E_USER_WARNING); exit; }



  include_once("api-functions.php");
  include_once('api-custom.php');

  /* --- DO NOT EDIT BELOW THIS LINE --- */

  //Plugin init.
  $errorsAndAlerts      = "";
  $success              = "";
  $user                 = array();
  $jsonData             = "";
  $schemas              = getSchemaTables();
  $password             = @$_REQUEST['_password'];
  $section              = @$_REQUEST['_section'];


  register_shutdown_function('shutDownFunction');
  error_reporting(0);

  //Get all of the section rules
  $sectionRules = api_getSectionRules();

  //Check if access to the section has been disabled.
  if(isset($sectionRules['disable']) && $sectionRules['disable'] == '1')     { $errorsAndAlerts .= "You cannot access this section.\n"; }

  //Error checking that applies to all CRUDU Functionality.
  if(!$section)                                                { $errorsAndAlerts .= "No section in request.\n"; }
  elseif(!in_array($section, $schemas))                        { $errorsAndAlerts .= "Section not found.\n"; }
  

  if(api_loginRequired($sectionRules)){
    list($user, $fbErrors) = api_validFacebookUser();
    if($fbErrors){
      $errorsAndAlerts .= $fbErrors;
    }  
  }

  //Ensure these values can never accidently be used by removing them. 
  unset($_REQUEST['_facebook_id']);
  unset($_REQUEST['_facebook_access_token']);


  //Get the default fields for this section.
  if($_REQUEST['_section']){
    $schemaFields = getSchemaFields($section);
  }else{
    $schemaFields = array();
  }

  if(function_exists('customErrorChecking')){
    $errorsAndAlerts .= customErrorChecking($user, $schemaFields);
  }

  if(function_exists('api_preRequestCustomFunctionality')) { api_preRequestCustomFunctionality($user, $schemaFields); }

  //CREATE FUNCTIONALITY
  if(isset($_REQUEST['create'])){

    //Check if create is disabled for this section.
    if( isset($sectionRules['disable_crud:values']) && in_array('create', $sectionRules['disable_crud:values']) ){
      $errorsAndAlerts .= "Disabled ablity to create records in this section.\r\n";
    }
    
    //Get the values
    $values = json_decode(@$_REQUEST['insertData'], true);
    if(!$values)                          { $errorsAndAlerts .= "No insert data sent.\n"; }
    if(!is_array($values))                { $errorsAndAlerts .= "Insert data not in array.\n"; }
    
    $errorsAndAlerts .= api_validateInsertData($values, $section);

    if(!$errorsAndAlerts){
      $values              = api_encryptPasswordFields($values);
      $values              = api_setUserAsCreator($user, $values);
      $num                 = mysql_insert($section, $values, true);
      $jsonData['success'] = "success";
      $jsonData['data']    = mysql_get($section, $num);   
    }

  //READ FUNCTIONALITY
  }elseif(isset($_REQUEST['read'])){

    //Check if read is disabled for this section.
    if( isset($sectionRules['disable_crud:values']) && in_array('read', $sectionRules['disable_crud:values']) ){
      $errorsAndAlerts .= "Disabled ablity to read records in this section.\r\n";
    }
    //Check that both limit and per page arn't set
    if($_REQUEST['_limit'] && $_REQUEST['_perPage']){ $errorsAndAlerts .=" You can only use one of perPage and limit. Not both.\n"; }

    if(!$errorsAndAlerts){
      // Get the fields to be returned if rules have been set.
      $displayFields = array();
      if($sectionRules['display_fields']){
        $displayFields = explode(",", $sectionRules['display_fields']);
        foreach ($displayFields as $key => $field) { $displayFields[$key] = trim($field); }
      }

      //Add the disaply fields set at the top of the page.
      foreach($GLOBALS['DEFAULT_EXPORT_FIELDS'] as $defaultExportField){
        if( ( $schemaFields[$defaultExportField] || ( startsWith('members.', $defaultExportField) && $schemaFields['membersNum'] ) || ( startsWith('listings.', $defaultExportField) && $schemaFields['listingsNum'] ) ) && !in_array($defaultExportField, $displayFields ) ){
          $displayFields[] = $defaultExportField;
        }
      }

      $sectionHasMembers = isset($schemaFields['membersNum']);
      if($sectionHasMembers){
        $uploadFields = [];
        $memberSchema =  getSchemaFields('members');
        foreach($memberSchema as $field => $data){
          if($data['type'] == 'upload'){
            $uploadFields[] = $field;
          }
        }
      }

      $sectionHasListings = isset($schemaFields['listingsNum']);
      if($sectionHasListings){
        $uploadFields = [];
        $listingsSchema =  getSchemaFields('listings');
        foreach($listingsSchema as $field => $data){
          if($data['type'] == 'upload'){
            $uploadFields[] = $field;
          }
        }
      }

      // load records from API
      $getRecordsOptions = array(
        'tableName'     => $section,
        'loadUploads'   => true,
        'allowSearch'   => true,
        'loadCreatedBy' => false,
      );

      if(@$_REQUEST['_section'] == 'listings' && @$_REQUEST['_latitude'] && @$_REQUEST['_longitude']){
        $kmOrMiles           = 'miles'; // can be 'miles' or 'km'
        $distanceFrom        = (isset($_REQUEST['_distance']))? intval($_REQUEST['_distance']) : 0 ;
        $getRecordsOptions   = array_merge(geocoder_getOptions($_REQUEST['_latitude'], $_REQUEST['_longitude'], $distanceFrom, $kmOrMiles, mysqli_real_escape_string(mysqli(),$_REQUEST['_section'])), $getRecordsOptions);
      }

      if($sectionHasMembers){
        //Add the left join to the getRecords call.
        $getRecordsOptions['leftJoin']['members'] = 'membersNum';
      }
      if($sectionHasListings){
        //Add the left join to the getRecords call.
        $getRecordsOptions['leftJoin']['listings'] = 'listingsNum';
      }
      if(@$schemaFields['badgesNum']){
        $getRecordsOptions['leftJoin']['badges'] = 'badgesNum';
      }
      
      if(@$schemaFields['couponNum']){
        $getRecordsOptions['leftJoin']['coupons'] = 'couponNum';
      }

      if(@$schemaFields['photo_uploadsNum']){
        $getRecordsOptions['leftJoin']['photo_uploads'] = 'photo_uploadsNum';
      }

      //DATA CLEAN UP
      if($sectionHasListings || $sectionHasMembers){
        //If we're getting either listing data or member data prefix all filter items with the current section.
        foreach($_REQUEST as $key => $value){
          if( !startsWith("_", $key) && !contains(".", $key) && $key != 'read' ){
            unset($_REQUEST[$key]);
            $_REQUEST[$section.".".$key] = $value;
          }
        }
      }



      //Get the limits / page / per page from request and set.
      if(!@$_REQUEST['_limit'] && !$_REQUEST['_perPage']){ $getRecordsOptions['limit'] = 50; }
      if(@$_REQUEST['_limit']){
        $getRecordsOptions['limit'] = @$_REQUEST['_limit'];
      }
      if(@$_REQUEST['_perPage']){
        $getRecordsOptions['perPage'] = @$_REQUEST['_perPage'];
      }
      if(@$_REQUEST['_page']){
        $getRecordsOptions['pageNum'] = @$_REQUEST['_page'];
      }
      if(@$_REQUEST['_orderBy']){
        list($field, $descAsc) = explode("_", @$_REQUEST['_orderBy']);
        $descAsc = ($descAsc == 'desc')? 'DESC' : 'ASC' ;
        $getRecordsOptions['orderBy'] = "`" . mysqli_real_escape_string(mysqli(),$field) . "` $descAsc";
      }

      // Get the linked records
      list($sectionData, $sectionMetaData) = getRecords($getRecordsOptions);

      if(@$schemaFields['followingNum'] && $sectionData){
        foreach($sectionData as $key => $data){
          $following  = mysql_get('members', $data['followingNum']);
          $following  = array_keys_prefix("following.", $following);
          $sectionData[$key] = array_merge($following, $data);
        } 
      }


      if( $sectionHasMembers ){
        foreach ($sectionData as $key => $record) {
          if(!$record['membersNum']){ continue; }
          foreach($uploadFields as $field){
            if(in_array("members.".$field, $displayFields) || !$displayFields){
              $sectionData[$key]['members.'.$field] = getUploadRecords('members', $field, $record['membersNum']);
            }
          }
        }
      }

      $jsonData['data'] = $sectionData;
      $jsonData['meta'] = $sectionMetaData;
      $jsonData['success'] = "Success\n";


    }


  //UPDATE FUNCTIONALITY
  }elseif(isset($_REQUEST['update'])){

    //Check if update is disabled for this section.
    if( isset($sectionRules['disable_crud:values']) && in_array('update', $sectionRules['disable_crud:values']) ){
      $errorsAndAlerts .= "Disabled ablity to update records in this section.\r\n";
    }
    //Get the values
    $values = json_decode(@$_REQUEST['insertData'], true);
    if(!$values)                          { $errorsAndAlerts .= "No insert data sent.\n"; }
    if(!is_array($values))                { $errorsAndAlerts .= "Insert data not in array.\n"; }
    
    //Basic error check values
    $errorsAndAlerts .= api_validateInsertData($values, $section);
    if(!@$_REQUEST['num']) { $errorsAndAlerts .= "You must pass the num of the record you want to update.\n"; }

    //Check if the user can only update their own records...
    if(@$sectionRules['ownRecordsOnly:values'] && $user){
      $errorsAndAlerts .= api_userOwnsRecord($user, $sectionRules, 'update');
    }

    //Special case for when the user updates their username.
    if($section =='members' && isset($_REQUEST['update'])){
      $recordSameAsUser = ($_REQUEST['num'] == $user['num']);
      if(isset($values['permalink'])) { unset($values['permalink']); } //Ensure the use can't update the permlink by updating it.

      if(isset($values['username']) && $recordSameAsUser){
        $cleanPermalink = _permalink_generate_formatInputText($values['username']);

        if(!mysql_count('members', "`username` = '" . mysqli_real_escape_string(mysqli(),$cleanPermalink) . "' AND `num` != '" . intval($user['num']) . "'")){
          mysql_delete('_permalinks', null, "`permalink` = '" . $cleanPermalink . "'"); //Remove the old permalinks that linked to this record.
          $errorsAndAlerts .= permalink_add($cleanPermalink, 'members', $user['num']);
          if(!$errorsAndAlerts){
            $values['permalink'] = $cleanPermalink;
            $values['username']  = $cleanPermalink;
            $values['card_code'] = '<iframe style="border:none;" src="'.htmlEncode($GLOBALS['API_SHORTERNED_URL'])."/".htmlEncode($cleanPermalink).'/?card" width="300" height="600" ></iframe>';
          }
        }else{
          $errorsAndAlerts .= "Another user has that username.\n";
        }
      }    
    }


    if(!$errorsAndAlerts){
      $num          = intval($_REQUEST['num']);
      $values       = api_encryptPasswordFields($values);
      $values       = api_setUserAsCreator($user, $values);

      mysql_update($section, $num, null, $values);
      $jsonData['success'] = "success";
      $jsonData['data']    = mysql_get($section, $num);   
    }

  //DELETE FUNCTIONALITY
  }elseif(isset($_REQUEST['delete'])){

    //Check if delete is disabled for this section.
    if( isset($sectionRules['disable_crud:values']) && in_array('delete', $sectionRules['disable_crud:values']) ){
      $errorsAndAlerts .= "Disabled ablity to delete records in this section.\r\n";
    }
    //Check that num value is sent.
    $num = intval($_REQUEST['num']);
    if(!$num){ $errorsAndAlerts .= "Num value not sent\n"; }

    //Check if the user can only delete their own records...
    if(@$sectionRules['ownRecordsOnly:values'] && $user){
      $errorsAndAlerts .= api_userOwnsRecord($user, $sectionRules, 'delete');
    }

    if(!$errorsAndAlerts){
      mysql_delete($section, $num);
      $jsonData['success'] = "success";
      $jsonData['data']    = array(); 
    }
  
  //NO FUNCTIONALITY FOUND
  }elseif(isset($_REQUEST['upload'])){

    //Check if upload is disabled for this section.
    if( isset($sectionRules['disable_crud:values']) && in_array('upload', $sectionRules['disable_crud:values']) ){
      $errorsAndAlerts .= "Disabled ablity to upload records in this section.\r\n";
    }
    
    //Get upload variables
    $schemaFields = getSchemaFields($section);
    $recordNum    = intval($_REQUEST['num']);
    $field        = @$_REQUEST['fieldName']; 
    $fileName     = @$_REQUEST['fileName']; 
    $data         = @$_REQUEST['uploadData'];
    $data         = base64_decode($data);

    //Carry out errorchecking
    if(!$recordNum)                                    { $errorsAndAlerts .= "Num value not sent\n"; }
    if(!$field)                                        { $errorsAndAlerts .= "You must send the field you want to add the upload to.\n"; }
    if(!$fileName)                                     { $errorsAndAlerts .= "You must pass over a fieldname.\r\n"; }
    elseif(@$schemaFields[$field]['type'] != 'upload') { $errorsAndAlerts .= "Field is not an upload type.\n"; }
    if(!$data)                                         { $errorsAndAlerts .= "No data sent in request, or data wasn't base64 encoded correctly.\n"; }

    //Check if the user can only delete their own records...
    if( @$sectionRules['ownRecordsOnly:values'] && $user ){
      $errorsAndAlerts .= api_userOwnsRecord($user, $sectionRules, 'upload');
    }

    //Don't attempt upload if we've already hit errors.
    if(!$errorsAndAlerts){

      $tmpFilepath = tempnam(DATA_DIR, 'temp_upload_');
      file_put_contents($tmpFilepath, $data);

      // remove temp file on shutdown (do this now so we don't leave an orphan file if we die() with an error
      unlink_on_shutdown($tmpFilepath);

      // fake uploadInfo (like $_FILE would have contained)
      $fakeUploadInfo = array(
        'name'     => $fileName,        // filename to use when adopting upload
        'tmp_name' => $tmpFilepath,     // filepath to current file
        'error'    => '',               //
        'size'     => 1,                // bypass 0-byte size error check
      );

      $errorsAndAlerts .= saveUpload($section, $field, $recordNum, "", $fakeUploadInfo, @$newUploadNums, true);
      $jsonData['meta'] = array();
      $jsonData['success'] = "Success\n";
    }


    if(!$errorsAndAlerts){
      $jsonData['success'] = 'success';
    }else{
      $jsonData['errors'] = $errorsAndAlerts;
    }

/* ====== CUSTOM FUNCTIONS FOR URBALHALAL.COM ====== */

  }elseif(isset($_REQUEST['sms_promote'])){

    if( startsWith("No section in request.\n", $errorsAndAlerts) ){
      $errorsAndAlerts = str_replace("No section in request.\n", "", $errorsAndAlerts);
    }

    if(@!$_REQUEST['numbers']) { $errorsAndAlerts .= "You must send the numbers in a comma seperated string you wish to message.\r\n"; } 
    if(@!$_REQUEST['names'])   { $errorsAndAlerts .= "You must send the names in a comma seperated string you wish to message.\r\n"; }
    if(@!$_REQUEST['emails'])  { $errorsAndAlerts .= "You must send the emails in a comma seperated string you wish to message.\r\n"; }

    if(!$errorsAndAlerts){
      $numbers = explode(",", $_REQUEST['numbers']);
      $names   = explode(",", $_REQUEST['names']);
      $emails  = explode(",", $_REQUEST['emails']);


      if(count($numbers) != count($names) && count($names) != count($emails) ){ $errorsAndAlerts .= "The number of name/email/numbers does not match up.<br>\r\n"; }
      if(!$errorsAndAlerts){
        foreach($numbers as $key => $number){
          $email = $emails[$key];
          $name  = $names[$key];
          if(!mysql_count('members', "facebook_email = '".mysqli_real_escape_string(mysqli(),$email)."'")){
            if(!mysql_count('pending_invite_messages', "`cell` = '".mysqli_real_escape_string(mysqli(),$number)."'") ){
              $date  = date('Y-m-d H:i:s');
              $insertArray = array(
                'createdDate'        => $date,
                'createdByUserNum'   => $user['num'],
                'updatedDate'        => $date,
                'updatedByUserNum'   => $user['num'],
                'date'               => $date,
                'name'               => $name,
                'cell'               => $number,
                'email'              => $email,
                'membersNum'         => $user['num'],
                'sent'               => '0',
                'ip_address_of_user' => general_getIP(),
              );
              mysql_insert('pending_invite_messages', $insertArray);
              $success .= "$name ($email) will be invited soon!\n";
            }
          }
        }
      }
    }
  }elseif(isset($_REQUEST['search'])){

    //Set search variables.
    $where     = "TRUE ";
    $query     = @$_REQUEST['_query'];
    $fields    = $GLOBALS['API_SEARCH_FIELDS'];
    $latitude  = @$_REQUEST['_latitude']; 
    $longitude = @$_REQUEST['_longitude'];
    $distance  = @$_REQUEST['_distance'];
    $page      = isset($_REQUEST['_page'])? intval($_REQUEST['_page']) : 1 ;
    $limitQty  = isset($_REQUEST['_perPage'])? intval($_REQUEST['_perPage']) : 25 ;
    $limit     = --$page * $limitQty;

    if(!$distance){
      $distance = 500;
    }

    if( startsWith("No section in request.\n", $errorsAndAlerts) ){
      $errorsAndAlerts = str_replace("No section in request.\n", "", $errorsAndAlerts);
    }

    //Error checking.
    if(!$fields) { $errorsAndAlerts .= "You must pass over a value in '_fields'"; }
    if(!$user)   { $errorsAndAlerts .= "You must be logged in to use this feature.\r\n"; }

    if(!$errorsAndAlerts){

      if($query){
        $searchWords = explode(' ', $query);
        $lastWord    = end($searchWords);
        $where       .= " AND ( ";
        foreach($fields as $key => $field){
          if($key != 0){ $where .= " OR "; }
          $where .= " ( ";
          foreach($searchWords as $key => $word){
            if($key != 0){ $where .= " OR "; }
            $where .= $field . " LIKE '%" . mysqli_real_escape_string(mysqli(),$word) . "%'"; 
          }
          $where .= ") ";
        }
        $where .= ") ";
      }
   
      //$where = "TRUE ";
      $listingsSchema  = getSchemaFields('listings');
      foreach($listingsSchema as $field => $fieldData){
        if(isset($_REQUEST[$field]) && in_array($fieldData['type'], array('none', 'list', 'checkbox', 'textbox', 'textfield', 'date') ) ){
          $values = explode(",", $_REQUEST[$field]);
          $where  .= "AND ( ";
          foreach($values as $key => $value){
            if( $key > 0 ) { $where .= " OR "; }
            $where .= "listings.`".mysqli_real_escape_string(mysqli(),mysqli(),$field)."` = '".mysqli_real_escape_string(mysqli(),$value)."'";  
          }
          $where .= " ) ";
        }elseif( isset($_REQUEST[$field."_match"]) && in_array($fieldData['type'], array('none', 'list', 'checkbox', 'textbox', 'textfield', 'date')) ){
          $values = explode(",", $_REQUEST[$field."_match"]);
          $where  .= "AND ( ";
          foreach($values as $key => $value){
            if($key > 0) { $where .= " OR "; }
            $where .= " listings.`".mysqli_real_escape_string(mysqli(),$field)."` = '".mysqli_real_escape_string(mysqli(),$value)."'"; 
          }  
          $where .= " ) ";
        }elseif( isset($_REQUEST[$field."_keyword"])&& in_array($fieldData['type'], array('none', 'list', 'checkbox', 'textbox', 'textfield', 'date')) ){
          $values = explode(",", $_REQUEST[$field."_keyword"]);
          $where  .= "AND ( ";
          foreach($values as $key => $value){
            if($key > 0) { $where .= " OR "; }
            $where .= " listings.`".mysqli_real_escape_string(mysqli(),$field)."` LIKE '%".mysqli_real_escape_string(mysqli(),$value)."%'";
          }
          $where .= " ) ";
        }elseif( isset($_REQUEST[$field."_prefix"]) && in_array($fieldData['type'], array('none', 'list', 'checkbox', 'textbox', 'textfield', 'date')) ){
          $values = explode(",", $_REQUEST[$field."_prefix"]);
          $where  .= "AND ( ";
          foreach($values as $key => $value){
            if($key > 0) { $where .= " OR "; }
            $where .= " listings.`".mysqli_real_escape_string(mysqli(),$field)."` LIKE '".mysqli_real_escape_string(mysqli(),$value)."%'";
          }
          $where .= " ) ";
        }elseif( isset($_REQUEST[$field."_empty"]) && in_array($fieldData['type'], array('none', 'list', 'checkbox', 'textbox', 'textfield', 'date')) ){
          $where .= "AND ( listings.`".mysqli_real_escape_string(mysqli(),$field)."` = '' OR  listings.`".mysqli_real_escape_string(mysqli(),$field."_empty")."` IS NULL ) ";   
        }elseif( isset($_REQUEST[$field."_min"])&& in_array($fieldData['type'], array('none', 'list', 'checkbox', 'textbox', 'textfield', 'date')) ){
          $where .= "AND listings.`".mysqli_real_escape_string(mysqli(),$field)."` >= '".mysqli_real_escape_string(mysqli(),$_REQUEST[$field."_min"])."'";  
        }elseif( isset($_REQUEST[$field."_max"]) && in_array($fieldData['type'], array('none', 'list', 'checkbox', 'textbox', 'textfield', 'date')) ){
          $where .= "AND listings.`".mysqli_real_escape_string(mysqli(),$field)."` <= '".mysqli_real_escape_string(mysqli(),$_REQUEST[$field."_max"])."'";  
        }
      }

      $selectOptions = "";
      $menuSchema    = getSchemaFields('menu');
      foreach($menuSchema as $field => $details){
        if($details['type'] != 'upload' && $details['type'] != 'separator'){
          $selectOptions .= ", menu.`$field` AS `menu.$field` \r\n";
        }
      }

      $menuSchema    = getSchemaFields('reviews');
      foreach($menuSchema as $field => $details){
        if($details['type'] != 'upload' && $details['type'] != 'separator'){
          $selectOptions .= ", reviews.`$field` AS `reviews.$field` \r\n";
        }
      }

      $menuSchema    = getSchemaFields('members');
      foreach($menuSchema as $field => $details){
        if($details['type'] != 'upload' && $details['type'] != 'separator'){
          $selectOptions .= ", members.`$field` AS `members.$field` \r\n";
        }
      }

      if($latitude && $longitude){
        $selectOptions .= ", ( ACOS( TRUNCATE( SIN(RADIANS(" . mysqli_real_escape_string(mysqli(),$latitude) . ")) * SIN(RADIANS(listings.latitude)) + COS(RADIANS(" . mysqli_real_escape_string(mysqli(),$latitude) . ")) * COS(RADIANS(listings.latitude)) * COS(RADIANS(listings.longitude - " . mysqli_real_escape_string(mysqli(),$longitude) . ")) ,10) ) ) * 6371 AS _distance, ISNULL(listings.latitude) OR ISNULL(listings.longitude) AS _distanceIsNull";
        $orderBy       = "_distanceIsNull, _distance ASC";
        if($distance){

        }
      }else{
        $selectOptions .= "";
        $orderBy       = "listings.`createdDate` DESC";
      }

      $query = "SELECT SQL_CALC_FOUND_ROWS `listings`.* $selectOptions
      FROM `urbanhal_listings` as `listings`
      LEFT JOIN {$SETTINGS['mysql']['tablePrefix']}reviews as reviews
      ON listings.num = reviews.listingsNum
      LEFT JOIN {$SETTINGS['mysql']['tablePrefix']}menu as menu
      ON listings.num = menu.listingsNum
      LEFT JOIN {$SETTINGS['mysql']['tablePrefix']}members as members
      ON members.num = listings.membersNum
      WHERE ($where)
      GROUP BY listings.num
      ORDER BY $orderBy
      LIMIT $limit, $limitQty";

      $rows          = mysql_select_query($query);
    //  $totalRecords  = (int) mysql_select_found_rows();
      $timeFields    = array('monday_open', 'monday_close', 'tuesday_open', 'tuesday_close', 'wednesday_open', 'wednesday_close', 'thursday_open', 'thursday_close', 'friday_open', 'friday_close', 'saturday_open', 'saturday_close', 'sunday_open', 'sunday_close'); 
      $readableTimes = getListOptions('listings', 'monday_open');

      foreach ($rows as $key => $record) { $rows[$key]['_tableName'] = 'listings'; }
      foreach($rows as $key => $row){
        foreach($listingsSchema as $field => $details){
          if($details['type'] == 'upload'){
            $rows[$key][$field] = getUploadRecords('listings', $field, $row['num'], "", null);
          }
          if(in_array($field, $timeFields)){
            $rows[$key][$field] = $readableTimes[$row[$field]];
          }
        }
      }
      $jsonData['data'] = $rows;
    }

  }elseif(isset($_REQUEST['feed'])){

    $getRecordsOptions = [
      'tableName'   => 'feed',
      'loadUploads' => false,
      'allowSearch' => true,
    ];

    //Get the limits / page / per page from request and set.
    if(!@$_REQUEST['_limit'] && !$_REQUEST['_perPage']){ $getRecordsOptions['limit'] = 10; }
    if(@$_REQUEST['_limit']){
      $getRecordsOptions['limit'] = @$_REQUEST['_limit'];
    }
    if(@$_REQUEST['_perPage']){
      $getRecordsOptions['perPage'] = @$_REQUEST['_perPage'];
    }
    if(@$_REQUEST['_page']){
      $getRecordsOptions['page'] = @$_REQUEST['_page'];
    }
    if(@$_REQUEST['_orderBy']){
      list($field, $descAsc) = explode("_", @$_REQUEST['_orderBy']);
      $descAsc = ($descAsc == 'desc')? 'DESC' : 'ASC' ;
      $getRecordsOptions['orderBy'] = "`" . mysqli_real_escape_string(mysqli(),$field) . "` $descAsc";
    }

    // load records from 'feed'
    list($feedRecords, $feedMetaData) = getRecords(
      $getRecordsOptions
    );

    $rows = [];
    foreach($feedRecords as $key => $feed){
      $rows[$key]                = json_decode($feed['json'], true);
      $rows[$key]['_section']     = $feed['section'];
      $rows[$key]['_recordNum']   = $feed['recordNum'];
      $rows[$key]['_membersNum']  = $feed['membersNum'];
      $rows[$key]['_action_date'] = $feed['action_date'];

    }

    $jsonData['data'] = $rows;

/* ====== END CUSTOM FUNCTIONS FOR URBALHALAL.COM ====== */

  }else{
    $errorsAndAlerts .="No CRUD command sent\n";
  }

  $jsonData['success'] = $success;
  $jsonData['errors']  = $errorsAndAlerts;
  if(isset($user['password']))  { unset($user['password']); }
  if(isset($user['card_code'])) { unset($user['card_code']); }
  $jsonData['user']    = $user;

  //Log the command if it was carried out succesfully.
  if(!$errorsAndAlerts) { 
    if (function_exists('api_postRequestCustomFunctionality')) {
      $schemaFields = (isset($schemaFields))? $schemaFields : [] ;
      list($user, $jsonData['data'], $jsonData['errors'], $jsonData['success']) = api_postRequestCustomFunctionality($user, $jsonData['data'], $success, $schemaFields);
    } 
  }

  // Filter the data if display fields have been set
  if( isset($_REQUEST['read']) ){
    if($displayFields){
      $returnData = array();
      foreach($jsonData['data'] as $key => $record){
        unset($jsonData['data'][$key]);
        foreach($displayFields as $field){
          $jsonData['data'][$key][$field] = @$record[$field];
        }
      }
    // Otherwise return all data
    }
  }


  $jsonData['data']         = api_formatData($jsonData['data']);
  $jsonData['execute_time'] = showExecuteSeconds(true);
  //Write the command to the API log if requested.
  api_logCommand($user, $jsonData);
  //Display the returned data.
  echo json_encode($jsonData);
  exit;

