Răsfoiți Sursa

#1519 Location improvements

Alex Trofimov 5 ani în urmă
părinte
comite
39589b24f2

+ 10 - 0
inc/classes/BxDolForm.php

@@ -932,6 +932,11 @@ class BxDolForm extends BxDol implements iBxDolReplaceable
         return false;
     }
 
+    function getTemplate ()
+    {
+        return $this->oTemplate;
+    }
+
     function getId ()
     {
         return $this->id;
@@ -968,6 +973,11 @@ class BxDolForm extends BxDol implements iBxDolReplaceable
         return $this->_aSpecificValues;
     }
 
+    function setSpecificValue($sName, $sVal)
+    {
+        $this->_aSpecificValues[$sName] = $sVal;
+    }
+
     function getAuthorId()
     {
         return $this->_iAuthorId;

+ 156 - 0
inc/classes/BxDolLocationField.php

@@ -0,0 +1,156 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaCore UNA Core
+ * @{
+ */
+
+/**
+ * This class allow different implementations for location field.
+ *
+ * Add record to sys_objects_location_field table, like you are doing this for Comments or Voting objects:
+ * - object: your object name, usually it is in the following format - vendor prefix, underscore, module prefix;
+ * - module: module name
+ * - title: translatable title
+ * - class_name: user defined class name which is derived from BxDolLocationField.
+ * - class_file: the location of the user defined class, leave it empty if class is located in system folders.
+ */
+class BxDolLocationField extends BxDolFactory implements iBxDolFactoryObject
+{
+	protected $_oDb;
+	protected $_sObject;
+    protected $_aObject;
+
+    /**
+     * Constructor
+     */
+    protected function __construct($aObject)
+    {
+        parent::__construct();
+
+        $this->_aObject = $aObject;
+        $this->_sObject = $aObject['object'];
+
+        $this->_oDb = new BxDolLocationFieldQuery($this->_aObject);
+    }
+
+   /**
+     * Get object instance by object name
+     * @param $sObject object name
+     * @return object instance or false on error
+     */
+    public static function getObjectInstance($sObject)
+    {
+        if(isset($GLOBALS['bxDolClasses']['BxDolLocationField!' . $sObject]))
+            return $GLOBALS['bxDolClasses']['BxDolLocationField!' . $sObject];
+
+        $aObject = BxDolLocationFieldQuery::getLocationFieldObject($sObject);
+        if (!$aObject || !is_array($aObject))
+            return false;
+
+        $sClass = 'BxDolLocationField';
+        if(!empty($aObject['class_name'])) {
+            $sClass = $aObject['class_name'];
+            if(!empty($aObject['class_file']))
+                require_once(BX_DIRECTORY_PATH_ROOT . $aObject['class_file']);
+        }        
+
+        $o = new $sClass($aObject);
+        return ($GLOBALS['bxDolClasses']['BxDolLocationField!' . $sObject] = $o);
+    }
+
+    /**
+     * Get current object name
+     */
+    public function getObjectName()
+    {
+        return $this->_aObject['object'];
+    }
+
+    public function genInputLocation (&$aInput, $oForm)
+    {        
+        $isManualInput = (int)(isset($aInput['manual_input']) && $aInput['manual_input']);
+        if (!$isManualInput) {
+            $aVars = array();
+            $aInputField = $aInput;
+
+            $aLocationIndexes = BxDolForm::$LOCATION_INDEXES;
+            foreach ($aLocationIndexes as $sKey)
+                $aVars[$sKey] = $this->getLocationVal($aInput, $sKey, $oForm);
+
+            $aInputField['caption'] = _t('_sys_location_undefined');
+
+            if ($this->getLocationVal($aInput, 'lat', $oForm) && $this->getLocationVal($aInput, 'lng', $oForm))
+                $aInputField['checked'] = true;
+            else
+                $aInputField['checked'] = $oForm->getCleanValue($aInput['name'] . '_lat') && $oForm->getCleanValue($aInput['name'] . '_lng') ? 1 : 0;
+
+            $sLocationString = _t('_sys_location_undefined');
+            if ($aVars['country']) {
+                $aCountries = BxDolFormQuery::getDataItems('Country');
+                $sLocationString = ($aVars['street_number'] ? $aVars['street_number'] . ', ' : '') . ($aVars['street'] ? $aVars['street'] . ', ' : '') . ($aVars['city'] ? $aVars['city'] . ', ' : '') . ($aVars['state'] ? $aVars['state'] . ', ' : '') . $aCountries[$aVars['country']];
+            }
+            elseif ($aVars['lat'] || $aVars['lng']) {
+                $sLocationString = $aVars['lat'] . ', ' . $aVars['lng'];
+            }
+
+            $aVars = array (
+                'name' => $aInput['name'],
+                'input' => $oForm->genInputSwitcher($aInputField),
+                'id_status' => $oForm->getInputId($aInput) . '_status',
+                'location_string' => $sLocationString,
+            );
+
+            $sRet = $oForm->getTemplate()->parseHtmlByName('form_field_location_plain_auto.html', $aVars);
+        }
+        else {
+            // TODO: translations for placeholders
+            $aFields = array(
+                'lat' => array('type' => 'hidden'),
+                'lng' => array('type' => 'hidden'),
+                'street_number' => array('type' => 'text', 'ph' => 'Number'),
+                'street' => array('type' => 'text', 'ph' => 'Street'),
+                'city' => array('type' => 'text', 'ph' => 'City / Disctrict'),
+                'state' => array('type' => 'text', 'ph' => 'State / Province'),
+                'zip' => array('type' => 'text', 'ph' => 'Postal Code'),
+                'country' => array('type' => 'select'),
+            );
+
+            $sRet = '';
+            foreach ($aFields as $sKey => $a) {
+                $aInputField = $aInput;
+                $aInputField['name'] = $aInput['name'] . '_' . $sKey;
+                $aInputField['type'] = $a['type'];
+                $aInputField['value'] = $this->getLocationVal($aInput, $sKey, $oForm);            
+                $aInputField['attrs']['placeholder'] = empty($a['ph']) ? '' : _t($a['ph']);
+                if (isset($aInputField['attrs']['class']))
+                    $aInputField['attrs']['class'] .= ' bx-form-input-location-' . $sKey;
+                else
+                    $aInputField['attrs']['class'] = 'bx-form-input-location-' . $sKey;
+                if ('country' == $sKey) {
+                    $aInputField['values'] = BxDolFormQuery::getDataItems('Country');
+                    $sRet .= $oForm->genInputSelect($aInputField);
+                }
+                else {
+                    $sRet .= $oForm->genInputStandard($aInputField);
+                }
+            }
+        }
+        return $sRet;
+    }
+
+    protected function getLocationVal ($aInput, $sIndex, $oForm) 
+    {
+        $aSpecificValues = $oForm->getSpecificValues();
+
+        $s = $aInput['name'] . '_' . $sIndex;
+        if (isset($aSpecificValues[$s]))
+            return $aSpecificValues[$s];
+
+        return $oForm->getCleanValue($s);
+    }
+}
+
+/** @} */

+ 76 - 0
inc/classes/BxDolLocationFieldGoogle.php

@@ -0,0 +1,76 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaCore UNA Core
+ * @{
+ */
+
+class BxDolLocationFieldGoogle extends BxDolLocationField
+{
+    public function genInputLocation (&$aInput, $oForm)
+    {
+        $aVars = $this->_getInputLocationVars($aInput, $oForm);
+        return $oForm->getTemplate()->parseHtmlByName('form_field_location_google.html', $aVars);
+    }
+
+    protected function _getInputLocationVars(&$aInput, $oForm)
+    {
+        $isManualInput = (int)(isset($aInput['manual_input']) && $aInput['manual_input']);
+        $sIdStatus = $oForm->getInputId($aInput) . '_status';
+        $sIdInput = $oForm->getInputId($aInput) . '_location';
+
+        $aVars = array (
+            'key' => trim(getParam('sys_maps_api_key')),
+            'lang' => bx_lang_name(),
+            'name' => $aInput['name'],
+            'id_status' => $sIdStatus,
+            'id_input' => $sIdInput,
+            'manual_input' => $isManualInput,            
+            'bx_if:manual_input' => array(
+                'condition' => $isManualInput,
+                'content' => array(),
+            ),
+            'bx_if:auto_input' => array(
+                'condition' => !$isManualInput,
+                'content' => array(
+                    'id_status' => $sIdStatus,
+                    'location_string' => _t('_sys_location_undefined'),
+                ),
+            ),
+            'api_field_name_short' => 'short_name',
+            'api_field_name_long' => 'long_name',
+            'api_field_name_2_length' => json_encode(array()),
+        );
+
+        $aLocationIndexes = BxDolForm::$LOCATION_INDEXES;
+        foreach ($aLocationIndexes as $sKey)
+            $aVars[$sKey] = $this->getLocationVal($aInput, $sKey, $oForm);
+
+        if ($aVars['country']) {
+            $aCountries = BxDolFormQuery::getDataItems('Country');
+            $s = ($aVars['street_number'] ? $aVars['street_number'] . ', ' : '') . ($aVars['street'] ? $aVars['street'] . ', ' : '') . ($aVars['city'] ? $aVars['city'] . ', ' : '') . ($aVars['state'] ? $aVars['state'] . ', ' : '') . $aCountries[$aVars['country']];
+            $aVars['bx_if:auto_input']['content']['location_string'] = $s;
+        }
+
+        if ($isManualInput) {
+            $aAttrs = empty($aInput['attrs']) ? array() : $aInput['attrs'];
+			$aInput['type'] = 'text';
+            $aInput['attrs']['id'] = $sIdInput;
+			$aInput['attrs'] = array_merge($aAttrs, $aInput['attrs']);
+            $aVars['input'] = $oForm->genInputStandard($aInput);
+        } 
+        else {
+            if ($this->getLocationVal($aInput, 'lat', $oForm) && $this->getLocationVal($aInput, 'lng', $oForm))
+                $aInput['checked'] = true;
+            else
+                $aInput['checked'] = $oForm->getCleanValue($aInput['name'] . '_lat') && $oForm->getCleanValue($aInput['name'] . '_lng') ? 1 : 0;
+            $aVars['input'] = $oForm->genInputSwitcher($aInput);
+        }
+
+        return $aVars;
+    }
+}
+
+/** @} */

+ 33 - 0
inc/classes/BxDolLocationFieldQuery.php

@@ -0,0 +1,33 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaCore UNA Core
+ * @{
+ */
+
+class BxDolLocationFieldQuery extends BxDolDb
+{
+
+    public function __construct($aObject = array())
+    {
+        parent::__construct();
+        $this->_aObject = $aObject;
+    }
+
+    static public function getLocationFieldObject($sObject)
+    {
+        $oDb = BxDolDb::getInstance();
+
+        $sQuery = $oDb->prepare("SELECT * FROM `sys_objects_location_field` WHERE `object` = ?", $sObject);
+
+        $aObject = $oDb->getRow($sQuery);
+        if(!$aObject || !is_array($aObject))
+            return false;
+
+        return $aObject;
+    }
+}
+
+/** @} */

+ 12 - 7
inc/classes/BxDolMetatags.php

@@ -693,18 +693,23 @@ class BxDolMetatags extends BxDolFactory implements iBxDolFactoryObject
      */
     public function locationsString($iId, $bHTML = true, $aParams = array())
     {
+        $s = '';
         bx_import('BxDolForm');
         $aCountries = BxDolFormQuery::getDataItems('Country');
         $aLocation = $this->locationGet($iId);
-        if(!$aLocation || !$aLocation['country'] || !isset($aCountries[$aLocation['country']]))
-            return '';
-
-        $s = '';
+        if(!$aLocation || !$aLocation['country'] || !isset($aCountries[$aLocation['country']])) {
+            if ($aLocation['lat'] || $aLocation['lng'])
+                $s = _t('_sys_location_country', $aLocation['lat'] . ', ' . $aLocation['lng']);
+            else
+                return '';
+        }
         
-        $sCountryUrl = '<a href="' . BX_DOL_URL_ROOT . 'searchKeyword.php?type=location_country&keyword=' . $aLocation['country'] . '">' . $aCountries[$aLocation['country']] . '</a>';
+        if (!$s) {
+            $sCountryUrl = '<a href="' . BX_DOL_URL_ROOT . 'searchKeyword.php?type=location_country&keyword=' . $aLocation['country'] . '">' . $aCountries[$aLocation['country']] . '</a>';
             
-        if(empty($aLocation['state']) || empty($aLocation['city']) || (isset($aParams['country_only']) && $aParams['country_only']))
-            $s = _t('_sys_location_country', $sCountryUrl);
+            if(empty($aLocation['state']) || empty($aLocation['city']) || (isset($aParams['country_only']) && $aParams['country_only']))
+                $s = _t('_sys_location_country', $sCountryUrl);
+        }
 
         if (!$s) {
             $sCityUrl = '<a href="' . BX_DOL_URL_ROOT . 'searchKeyword.php?type=location_country_city&keyword=' . $aLocation['country'] . '&state=' . rawurlencode($aLocation['state']) . '&city=' . rawurlencode($aLocation['city']) . '">' . $aLocation['city'] . '</a>';

+ 1 - 1
inc/classes/BxDolMetatagsQuery.php

@@ -89,7 +89,7 @@ class BxDolMetatagsQuery extends BxDolDb
     public function locationsAdd($mixedContentId, $fLat, $fLng, $sCountryCode, $sState, $sCity, $sZip, $sStreet, $sStreetNumber)
     {
         $this->locationsDelete($mixedContentId);
-        if (!$fLat && !$fLng)
+        if (!$fLat && !$fLng && !$sCountryCode)
             return true;
 
         $sQuery = $this->prepare("INSERT INTO `{$this->_aObject['table_locations']}` SET `object_id` = ?, `lat` = ?, `lng` = ?, `country` = ?, `state` = ?, `city` = ?, `zip` = ?, `street` = ?, `street_number` = ?", $mixedContentId, $fLat, $fLng, $sCountryCode, $sState, $sCity, $sZip, $sStreet, $sStreetNumber);

+ 24 - 0
template/css/forms.css

@@ -673,3 +673,27 @@
 .select2-container {
     width:100% !important;
 }
+
+/* Location field */
+
+.bx-form-input-location-country,
+.bx-form-input-location-zip,
+.bx-form-input-location-state,
+.bx-form-input-location-city {
+    width:49%;
+}
+
+.bx-form-input-location-street {
+    width:83%;
+}
+
+.bx-form-input-location-street_number {
+    width:15%;
+}
+
+.bx-form-input-location-street_number,
+.bx-form-input-location-street,
+.bx-form-input-location-state,
+.bx-form-input-location-city {
+    margin-bottom:0.25rem;
+}

+ 5 - 1
template/form_field_location.html → template/form_field_location_google.html

@@ -103,12 +103,16 @@
     }
 
     $('input[name=__name__][type=checkbox]').on('change', function () {
+        var _self = this;
 
         var callbackOnLocationReset = function (error) {
             for(var sKey in oBxLocationHashMap) 
                 $('[name="' + oBxLocationHashMap[sKey].html + '"]').val('');
 
             $('#__id_status__').html("<bx_text_js:_sys_location_undefined />");
+
+            $(_self).prop("checked", false);
+            $(_self).parents('.bx-switcher-cont').removeClass('on').addClass('off');
         }
 
         var callbackOnLocationSucess = function (position) {
@@ -195,4 +199,4 @@
             fInitCallback();
     });
 
-</script>
+</script>

+ 38 - 0
template/form_field_location_plain_auto.html

@@ -0,0 +1,38 @@
+
+<div class="bx-form-input-location-cont bx-clearfix">
+    __input__
+    <div id="__id_status__" class="bx-def-margin-sec-left">__location_string__</div>
+</div>
+
+<input type="hidden" name="__name___lat" value="__lat__" />
+<input type="hidden" name="__name___lng" value="__lng__" />
+
+<script>
+    $('input[name=__name__][type=checkbox]').on('change', function () {
+        var _self = this;
+        var callbackOnLocationReset = function (error) {
+            $('[name="__name___lat"]').val('');
+            $('[name="__name___lng"]').val('');
+            $('#__id_status__').html("<bx_text_js:_sys_location_undefined />");
+            $(_self).prop("checked", false);
+            $(_self).parents('.bx-switcher-cont').removeClass('on').addClass('off');
+        }
+
+        var callbackOnLocationSucess = function (position) {
+            $('[name="__name___lat"]').val(position.coords.latitude);
+            $('[name="__name___lng"]').val(position.coords.longitude);
+            $('#__id_status__').html(position.coords.latitude + ', ' + position.coords.longitude);
+        }
+
+        if ($(this).is(':checked')) {
+            $('#__id_status__').html('<bx_text_js:_sys_location_determining />');
+            if (navigator.geolocation)
+                navigator.geolocation.getCurrentPosition(callbackOnLocationSucess, callbackOnLocationReset);
+            else
+                $('#__id_status__').html('<bx_text_js:_sys_location_geolocation_not_supported_by_browser />');
+        }
+        else {
+            callbackOnLocationReset();
+        }
+    });
+</script>

+ 4 - 84
template/scripts/BxBaseFormView.php

@@ -1709,97 +1709,17 @@ BLAH;
 
     function genInputLocation(&$aInput)
     {
-        $aVars = $this->_getInputLocationVars($aInput);
-        return $this->oTemplate->parseHtmlByName('form_field_location.html', $aVars);
-    }
-    
-    protected function _getInputLocationVars(&$aInput)
-    {
-        $isManualInput = (int)(isset($aInput['manual_input']) && $aInput['manual_input']);
-        $sIdStatus = $this->getInputId($aInput) . '_status';
-        $sIdInput = $this->getInputId($aInput) . '_location';
-
-        $aVars = array (
-            'key' => trim(getParam('sys_maps_api_key')),
-            'lang' => bx_lang_name(),
-            'name' => $aInput['name'],
-            'id_status' => $sIdStatus,
-            'id_input' => $sIdInput,
-            'manual_input' => $isManualInput,            
-            'bx_if:manual_input' => array(
-                'condition' => $isManualInput,
-                'content' => array(),
-            ),
-            'bx_if:auto_input' => array(
-                'condition' => !$isManualInput,
-                'content' => array(
-                    'id_status' => $sIdStatus,
-                    'location_string' => _t('_sys_location_undefined'),
-                ),
-            ),
-            'api_field_name_short' => 'short_name',
-            'api_field_name_long' => 'long_name',
-            'api_field_name_2_length' => json_encode(array()),
-        );
-
-        $aLocationIndexes = self::$LOCATION_INDEXES;
-        foreach ($aLocationIndexes as $sKey)
-            $aVars[$sKey] = $this->getLocationVal($aInput, $sKey);
-
-        if ($aVars['country']) {
-            $aCountries = BxDolFormQuery::getDataItems('Country');
-            $s = ($aVars['street_number'] ? $aVars['street_number'] . ', ' : '') . ($aVars['street'] ? $aVars['street'] . ', ' : '') . ($aVars['city'] ? $aVars['city'] . ', ' : '') . ($aVars['state'] ? $aVars['state'] . ', ' : '') . $aCountries[$aVars['country']];
-            $aVars['bx_if:auto_input']['content']['location_string'] = $s;
-        }
+        $o = BxDolLocationField::getObjectInstance('sys_plain');
+        if (!$o)
+            return _t('_sys_txt_error_occured');
 
-        if ($isManualInput) {
-            $aAttrs = empty($aInput['attrs']) ? array() : $aInput['attrs'];
-			$aInput['type'] = 'text';
-            $aInput['attrs']['id'] = $sIdInput;
-			$aInput['attrs'] = array_merge($aAttrs, $aInput['attrs']);
-            $aVars['input'] = $this->genInputStandard($aInput);
-        } 
-        else {
-            if ($this->getLocationVal($aInput, 'lat') && $this->getLocationVal($aInput, 'lng'))
-                $aInput['checked'] = true;
-            else
-                $aInput['checked'] = $this->getCleanValue($aInput['name'] . '_lat') && $this->getCleanValue($aInput['name'] . '_lng') ? 1 : 0;
-            $aVars['input'] = $this->genInputSwitcher($aInput);
-        }
-
-        return $aVars;
-    }
-    
-    public function setLocationVals ($aInput, $aVals)
-    {
-        $this->_aSpecificValues[$aInput['name'] . '_lat'] = $aVals['lat'];
-		$this->_aSpecificValues[$aInput['name'] . '_lng'] = $aVals['lng'];
-		$this->_aSpecificValues[$aInput['name'] . '_country'] = $aVals['country'];
-		$this->_aSpecificValues[$aInput['name'] . '_state'] = $aVals['state'];
-		$this->_aSpecificValues[$aInput['name'] . '_city'] = $aVals['city'];
-		$this->_aSpecificValues[$aInput['name'] . '_zip'] = $aVals['zip'];
-		$this->_aSpecificValues[$aInput['name'] . '_street'] = $aVals['street'];
-		$this->_aSpecificValues[$aInput['name'] . '_street_number'] = $aVals['street_number'];
+        return $o->genInputLocation($aInput, $this);
     }
     
     function genInputPassword(&$aInput)
     {
         return $this->oTemplate->parseHtmlByName('form_field_password.html', array('input' => $this->genInputStandard($aInput)));
     }
-
-    public function setLocationVal ($aInput, $sIndex, $sVal)
-    {
-        $s = $aInput['name'] . '_' . $sIndex;
-        $this->_aSpecificValues[$s] = $sVal;
-    }
-
-    protected function getLocationVal ($aInput, $sIndex) 
-    {
-        $s = $aInput['name'] . '_' . $sIndex;
-        if (isset($this->_aSpecificValues[$s]))
-            return $this->_aSpecificValues[$s];
-        return $this->getCleanValue($s);
-    }
     
     function genInputNestedForm(&$aInput)
     {