From 8ebfdc79d38671617b945b9f202ee604dadacd37 Mon Sep 17 00:00:00 2001 From: Jason Irish Date: Tue, 16 May 2017 11:58:39 -0500 Subject: [PATCH] SilverStripe alpha7 updates use dynamic/silverstripe-geocoder for geocoding --- .travis.yml | 16 +- _config/config.yml | 7 +- composer.json | 12 +- phpunit.xml | 21 -- phpunit.xml.dist | 14 ++ {code => src}/admin/LocationAdmin.php | 0 .../bulkloader/LocationCsvBulkLoader.php | 0 .../extensions/DistanceDataExtension.php | 19 +- {code => src}/form/LocatorForm.php | 23 +- {code => src}/objects/Location.php | 199 ++++++++++------- {code => src}/objects/LocationCategory.php | 21 +- src/pages/Locator.php | 158 +++++++++++++ .../pages/LocatorController.php | 210 +++--------------- tasks/EmailAddressTask.php | 4 + tasks/LocationPublishTask.php | 6 + .../{ => Dynamic/Locator}/Layout/Locator.ss | 0 templates/LocationXML.ss | 7 +- tests/LocationCategoryTest.php | 31 ++- .../{Locator_Test.php => LocatorBaseTest.php} | 2 +- tests/LocatorFormTest.php | 49 ++-- tests/LocatorTest.php | 27 ++- tests/Locator_Test.yml | 4 + 22 files changed, 457 insertions(+), 373 deletions(-) delete mode 100644 phpunit.xml create mode 100644 phpunit.xml.dist rename {code => src}/admin/LocationAdmin.php (100%) rename {code => src}/bulkloader/LocationCsvBulkLoader.php (100%) rename {code => src}/extensions/DistanceDataExtension.php (65%) rename {code => src}/form/LocatorForm.php (80%) rename {code => src}/objects/Location.php (54%) rename {code => src}/objects/LocationCategory.php (75%) create mode 100644 src/pages/Locator.php rename code/pages/Locator.php => src/pages/LocatorController.php (60%) rename templates/{ => Dynamic/Locator}/Layout/Locator.ss (100%) rename tests/{Locator_Test.php => LocatorBaseTest.php} (94%) diff --git a/.travis.yml b/.travis.yml index 4f693e1..2ff44cb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,13 +19,13 @@ env: matrix: include: - - php: 5.6 - env: DB=PGSQL - - php: 5.6 + - php: 7.0 env: DB=SQLITE - - php: 5.6 - env: COVERAGE=1 - php: 7.0 + env: DB=PGSQL + - php: 7.0 + env: COVERAGE=1 + - php: 5.6 before_script: @@ -34,7 +34,9 @@ before_script: - git clone git://github.com/silverstripe-labs/silverstripe-travis-support.git ~/travis-support - php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss - cd ~/builds/ss + - mv "$MODULE_PATH/phpunit.xml.dist" . +#Execute tests with or without coverage script: # Execute tests with no coverage. This is the fastest option - "if [ \"$COVERAGE\" = \"0\" ]; then vendor/bin/phpunit $MODULE_PATH/tests/; fi" @@ -42,8 +44,8 @@ script: # Execute tests with coverage. Do this for a small - "if [ \"$COVERAGE\" = \"1\" ]; then vendor/bin/phpunit --coverage-clover=coverage.clover $MODULE_PATH/tests/; fi" -after_script: +# Upload code coverage when tests pass +after_success: - "if [ \"$COVERAGE\" = \"1\" ]; then mv coverage.clover ~/build/$TRAVIS_REPO_SLUG/; fi" - cd ~/build/$TRAVIS_REPO_SLUG - - wget https://scrutinizer-ci.com/ocular.phar - "if [ \"$COVERAGE\" = \"1\" ]; then travis_retry codecov && travis_retry php ocular.phar code-coverage:upload --format=php-clover coverage.clover; fi" diff --git a/_config/config.yml b/_config/config.yml index ad59fd3..cd5c4be 100644 --- a/_config/config.yml +++ b/_config/config.yml @@ -1,8 +1,7 @@ --- Name: locator --- -Location: +Dynamic\Locator\Location: extensions: - - Addressable - - Geocodable - - DistanceDataExtension \ No newline at end of file + - Dynamic\Locator\DistanceDataExtension + - SilverStripe\Versioned\Versioned('Stage','Live') \ No newline at end of file diff --git a/composer.json b/composer.json index f8803c9..2023d0c 100644 --- a/composer.json +++ b/composer.json @@ -22,13 +22,21 @@ "require": { "silverstripe/framework": "^4.0", "silverstripe/cms": "^4.0", - "muskie9/data-to-arraylist": "^2.0" + "muskie9/data-to-arraylist": "^2.0", + "dynamic/silverstripe-geocoder": "^1.0" }, "suggest": { - "silverstripe-australia/addressable": "^1.1", "unclecheese/betterbuttons": "Adds new form actions and buttons to GridField detail form for usability enhancements.", "unclecheese/bootstrap-forms": "Allows the creation of forms compatible with the Twitter Bootstrap CSS framework in SilverStripe." }, + "autoload": { + "psr-4": { + "Dynamic\\Locator\\": "src/", + "Dynamic\\Locator\\Tests\\": "tests/" + } + }, + "minimum-stability": "dev", + "prefer-stable": true, "extra": { "installer-name": "locator", "branch-alias": { diff --git a/phpunit.xml b/phpunit.xml deleted file mode 100644 index f079734..0000000 --- a/phpunit.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - tests - - - - - - - - - sanitychecks - - - - - code - - - \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..907bfea --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,14 @@ + + + locator/tests + + + + + locator/src/ + + locator/tests/ + + + + diff --git a/code/admin/LocationAdmin.php b/src/admin/LocationAdmin.php similarity index 100% rename from code/admin/LocationAdmin.php rename to src/admin/LocationAdmin.php diff --git a/code/bulkloader/LocationCsvBulkLoader.php b/src/bulkloader/LocationCsvBulkLoader.php similarity index 100% rename from code/bulkloader/LocationCsvBulkLoader.php rename to src/bulkloader/LocationCsvBulkLoader.php diff --git a/code/extensions/DistanceDataExtension.php b/src/extensions/DistanceDataExtension.php similarity index 65% rename from code/extensions/DistanceDataExtension.php rename to src/extensions/DistanceDataExtension.php index e5a57bc..2b2fb0a 100644 --- a/code/extensions/DistanceDataExtension.php +++ b/src/extensions/DistanceDataExtension.php @@ -2,10 +2,11 @@ namespace Dynamic\Locator; -use SilverStripe\ORM\DataExtension, - SilverStripe\ORM\Queries\SQLSelect, - SilverStripe\ORM\DataQuery, - SilverStripe\Control\Controller; +use Dynamic\SilverStripeGeocoder\GoogleGeocoder; +use SilverStripe\ORM\DataExtension; +use SilverStripe\ORM\Queries\SQLSelect; +use SilverStripe\ORM\DataQuery; +use SilverStripe\Control\Controller; class DistanceDataExtension extends DataExtension { @@ -19,12 +20,12 @@ public function augmentSQL(SQLSelect $query, DataQuery $dataQuery = null) if ($this->owner->hasMethod('updateAddressValue')) { $address = $this->owner->updateAddressValue($address); } - if (class_exists('GoogleGeocoding')) { + if (class_exists(GoogleGeocoder::class)) { if ($address) { // on frontend - $coords = GoogleGeocoding::address_to_point($address); - - $Lat = $coords['lat']; - $Lng = $coords['lng']; + $geocoder = new GoogleGeocoder($address); + $response = $geocoder->getResult(); + $Lat = $response->getLatitude(); + $Lng = $response->getLongitude(); $query ->addSelect(array( diff --git a/code/form/LocatorForm.php b/src/form/LocatorForm.php similarity index 80% rename from code/form/LocatorForm.php rename to src/form/LocatorForm.php index af739ca..b503798 100644 --- a/code/form/LocatorForm.php +++ b/src/form/LocatorForm.php @@ -2,13 +2,15 @@ namespace Dynamic\Locator; -use SilverStripe\Forms\Form, - SilverStripe\Forms\FieldList, - SilverStripe\Forms\TextField, - SilverStripe\Forms\DropdownField, - SilverStripe\Forms\FormAction, - SilverStripe\Forms\RequiredFields, - SilverStripe\Control\Controller; +use SilverStripe\Core\Config\Config; +use SilverStripe\Dev\Debug; +use SilverStripe\Forms\Form; +use SilverStripe\Forms\FieldList; +use SilverStripe\Forms\TextField; +use SilverStripe\Forms\DropdownField; +use SilverStripe\Forms\FormAction; +use SilverStripe\Forms\RequiredFields; +use SilverStripe\Control\Controller; /** * Class LocatorForm @@ -59,8 +61,8 @@ public function __construct(Controller $controller, $name) $fields->push($categoriesField); } - if (Config::inst()->get('LocatorForm', 'show_radius')) { - $radiusArray = Config::inst()->get('LocatorForm', 'radius_array'); + if (Config::inst()->get(LocatorForm::class, 'show_radius')) { + $radiusArray = Config::inst()->get(LocatorForm::class, 'radius_array'); $this->extend('overrideRadiusArray', $radiusArray); $fields->push(DropdownField::create('Radius', '', $radiusArray) ->setEmptyString('radius') @@ -78,7 +80,7 @@ public function __construct(Controller $controller, $name) } /** - * @return Validator + * @return null|RequiredFields|\SilverStripe\Forms\Validator */ public function getValidator() { @@ -90,5 +92,4 @@ public function getValidator() $this->extend('updateRequiredFields', $validator); return $validator; } - } \ No newline at end of file diff --git a/code/objects/Location.php b/src/objects/Location.php similarity index 54% rename from code/objects/Location.php rename to src/objects/Location.php index eff54d4..9a1999e 100644 --- a/code/objects/Location.php +++ b/src/objects/Location.php @@ -2,18 +2,23 @@ namespace Dynamic\Locator; -use SilverStripe\ORM\DataObject, - SilverStripe\Security\PermissionProvider, - SilverStripe\Forms\FieldList, - SilverStripe\Forms\Tab, - SilverStripe\Forms\TabSet, - SilverStripe\Forms\HeaderField, - SilverStripe\Forms\TextField, - SilverStripe\Forms\EmailField, - SilverStripe\Forms\DropdownField, - SilverStripe\Forms\CheckboxField, - SilverStripe\Security\Permission, - SilverStripe\Dev\Deprecation; +use Dynamic\SilverStripeGeocoder\GoogleGeocoder; +use SilverStripe\Control\Email\Email; +use SilverStripe\Forms\CountryDropdownField; +use SilverStripe\Forms\ReadonlyField; +use SilverStripe\ORM\DataObject; +use SilverStripe\Security\PermissionProvider; +use SilverStripe\Forms\FieldList; +use SilverStripe\Forms\Tab; +use SilverStripe\Forms\TabSet; +use SilverStripe\Forms\HeaderField; +use SilverStripe\Forms\TextField; +use SilverStripe\Forms\EmailField; +use SilverStripe\Forms\DropdownField; +use SilverStripe\Forms\CheckboxField; +use SilverStripe\Security\Permission; +use SilverStripe\Dev\Deprecation; +use SilverStripe\i18n\i18n; /** * Class Location @@ -24,7 +29,6 @@ * @property string $Phone * @property string $Email * @property string $EmailAddress - * @property bool $ShowInLocator * @property int $Import_ID * @property int $CategoryID * @method LocationCategory $Category @@ -42,14 +46,13 @@ class Location extends DataObject implements PermissionProvider 'Phone' => 'Varchar(40)', 'Email' => 'Varchar(255)', 'EmailAddress' => 'Varchar(255)', - 'ShowInLocator' => 'Boolean', 'Import_ID' => 'Int', 'Address' => 'Varchar(255)', - 'Suburb' => 'Varchar(64)', + 'Address2' => 'Varchar(255)', + 'City' => 'Varchar(64)', 'State' => 'Varchar(64)', - 'Postcode' => 'Varchar(10)', + 'PostalCode' => 'Varchar(10)', 'Country' => 'Varchar(2)', - 'LatLngOverride' => 'Boolean', 'Lat' => 'Decimal(10,7)', 'Lng' => 'Decimal(10,7)', ); @@ -58,7 +61,7 @@ class Location extends DataObject implements PermissionProvider * @var array */ private static $has_one = array( - 'Category' => 'Dynamic\\Locator\\LocationCategory', + 'Category' => LocationCategory::class, ); /** @@ -73,17 +76,11 @@ class Location extends DataObject implements PermissionProvider */ private static $default_sort = 'Title'; - /** - * @var array - */ - private static $defaults = array( - 'ShowInLocator' => true, - ); - /** * @var string */ private static $singular_name = 'Location'; + /** * @var string */ @@ -104,9 +101,9 @@ class Location extends DataObject implements PermissionProvider private static $searchable_fields = array( 'Title', 'Address', - 'Suburb', + 'City', 'State', - 'Postcode', + 'PostalCode', 'Country', 'Website', 'Phone', @@ -132,13 +129,6 @@ class Location extends DataObject implements PermissionProvider 'Coords', ); - /** - * @var array - */ - private static $extensions = [ - 'VersionedDataObject', - ]; - /** * Coords status for $summary_fields * @@ -158,19 +148,15 @@ public function getCoords() public function fieldLabels($includerelations = true) { $labels = parent::fieldLabels($includerelations); - $labels['Title'] = 'Name'; - $labels['Suburb'] = 'City'; - $labels['Postcode'] = 'Postal Code'; - $labels['ShowInLocator'] = 'Show'; - $labels['ShowInLocator.NiceAsBoolean'] = 'Show'; + $labels['City'] = 'City'; + $labels['PostalCode'] = 'Postal Code'; $labels['Category.Name'] = 'Category'; $labels['Category.ID'] = 'Category'; $labels['Email'] = 'Email'; $labels['Featured.NiceAsBoolean'] = 'Featured'; $labels['Coords'] = 'Coords'; $labels['Import_ID'] = 'Import_ID'; - return $labels; } @@ -179,35 +165,33 @@ public function fieldLabels($includerelations = true) */ public function getCMSFields() { - $fields = FieldList::create( - new TabSet( - $name = 'Root', - new Tab( - $title = 'Main', - HeaderField::create('ContactHD', 'Contact Information'), - TextField::create('Title', 'Name'), - TextField::create('Phone'), - EmailField::create('Email', 'Email'), - TextField::create('Website') - ->setAttribute('placeholder', 'http://'), - DropdownField::create('CategoryID', 'Category', LocationCategory::get()->map('ID', 'Title')) - ->setEmptyString('-- select --'), - CheckboxField::create('Featured') - ->setDescription('Location will show at/near the top of the results list') - ) - ) - ); + $fields = parent::getCMSFields(); - // allow to be extended via DataExtension - $this->extend('updateCMSFields', $fields); - - $fields->removeByName([ - 'ShowInLocator', + $fields->removeByName(array( 'Import_ID', - ]); + )); + + //$fields->replaceField('Country', CountryDropdownField::create('Country')); / + /// CountryDropdownField is removed from SS4 + + $fields->replaceField('Lat', ReadonlyField::create('Lat')); + + $fields->replaceField('Lng', ReadonlyField::create('Lng')); - // override Suburb field name - //$fields->dataFieldByName('Suburb')->setTitle('City'); + $fields->dataFieldByName('Website') + ->setAttribute('placeholder', 'http://'); + + $fields->replaceField('Email', EmailField::create('Email')); + + $fields->dataFieldByName('Featured') + ->setDescription('Location will display near the top of the results list'); + + $fields->replaceField( + 'CategoryID', + DropdownField::create('CategoryID', 'Category', LocationCategory::get()->map())->setEmptyString('') + ); + // allow to be extended via DataExtension + $this->extend('updateLocationFields', $fields); return $fields; } @@ -222,21 +206,6 @@ public function validate() return $result; } - /** - * @return bool|string - */ - public function EmailAddress() - { - Deprecation::notice('3.0', 'Use "$Email" instead.'); - if ($this->Email) { - return $this->Email; - } elseif ($this->EmailAddress) { - return $this->EmailAddress; - } - - return false; - } - /** * @param null $member * @return bool @@ -286,4 +255,72 @@ public function providePermissions() ); } + /** + * Returns the full address as a simple string. + * + * @return string + */ + public function getFullAddress() { + $parts = array( + $this->Address, + $this->Address2, + $this->City, + $this->State, + $this->PostalCode, + $this->getCountryName() + ); + return implode(', ', array_filter($parts)); + } + /** + * Returns the country name (not the 2 character code). + * + * @return string + */ + public function getCountryName() { + //return \Zend_Locale::getTranslation($this->Country, 'territory', i18n::get_locale()); + return $this->Country; + } + /** + * @return bool + */ + public function hasAddress() { + return ( + $this->Address + && $this->City + && $this->State + && $this->PostalCode + ); + } + /** + * Returns TRUE if any of the address fields have changed. + * + * @param int $level + * @return bool + */ + public function isAddressChanged($level = 1) { + $fields = array('Address', 'Address2', 'City', 'State', 'PostalCode', 'Country'); + $changed = $this->getChangedFields(false, $level); + foreach ($fields as $field) { + if (array_key_exists($field, $changed)) return true; + } + return false; + } + /** + * + */ + public function onBeforeWrite() + { + parent::onBeforeWrite(); + if ($this->hasAddress()) { + if (!$this->isAddressChanged()) { + return; + } + if ($address = $this->getFullAddress()) { + $geocoder = new GoogleGeocoder($address); + $response = $geocoder->getResult(); + $this->Lat = $response->getLatitude(); + $this->Lng = $response->getLongitude(); + } + } + } } diff --git a/code/objects/LocationCategory.php b/src/objects/LocationCategory.php similarity index 75% rename from code/objects/LocationCategory.php rename to src/objects/LocationCategory.php index e4c6612..b6ae35b 100644 --- a/code/objects/LocationCategory.php +++ b/src/objects/LocationCategory.php @@ -2,7 +2,11 @@ namespace Dynamic\Locator; +use SilverStripe\Forms\GridField\GridField; +use SilverStripe\Forms\GridField\GridFieldAddExistingAutocompleter; +use SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor; use SilverStripe\ORM\DataObject; +use SilverStripe\Security\Permission; /** * Class LocationCategory @@ -24,14 +28,14 @@ class LocationCategory extends DataObject * @var array */ private static $has_many = array( - 'Locations' => 'Dynamic\\Locator\\LocationLocation', + 'Locations' => Location::class, ); /** * @var array */ private static $belogs_many_many = array( - 'Locators' => 'Dynamic\\Locator\\Locator', + 'Locators' => Locator::class, ); /** @@ -61,7 +65,7 @@ public function getCMSFields() // Locations $config = GridFieldConfig_RelationEditor::create(); $config->removeComponentsByType('GridFieldAddExistingAutocompleter'); - $config->addComponent(new GridFieldAddExistingSearchButton()); + $config->addComponent(new GridFieldAddExistingAutocompleter()); $config->removeComponentsByType('GridFieldAddNewButton'); $locations = $this->Locations(); $locationField = GridField::create('Locations', 'Locations', $locations, $config); @@ -78,7 +82,7 @@ public function getCMSFields() * @param null|Member $member * @return bool */ - public function canView($member = null) + public function canView($member = null, $context = []) { return true; } @@ -87,7 +91,7 @@ public function canView($member = null) * @param null|Member $member * @return bool|int */ - public function canEdit($member = null) + public function canEdit($member = null, $context = []) { return Permission::check('Location_EDIT', 'any', $member); } @@ -96,16 +100,17 @@ public function canEdit($member = null) * @param null|Member $member * @return bool|int */ - public function canDelete($member = null) + public function canDelete($member = null, $context = []) { return Permission::check('Location_DELETE', 'any', $member); } /** - * @param null|Member $member + * @param null $member + * @param array $context * @return bool|int */ - public function canCreate($member = null) + public function canCreate($member = null, $context = []) { return Permission::check('Location_CREATE', 'any', $member); } diff --git a/src/pages/Locator.php b/src/pages/Locator.php new file mode 100644 index 0000000..501a871 --- /dev/null +++ b/src/pages/Locator.php @@ -0,0 +1,158 @@ + 'Enum("m,km","m")', + ); + + /** + * @var array + */ + private static $many_many = array( + 'Categories' => 'Dynamic\\Locator\\LocationCategory', + ); + + /** + * @var string + */ + private static $singular_name = 'Locator'; + /** + * @var string + */ + private static $plural_name = 'Locators'; + /** + * @var string + */ + private static $description = 'Find locations on a map'; + + /** + * @var string + */ + private static $location_class = 'Dynamic\\Locator\\Location'; + + /** + * @return FieldList + */ + public function getCMSFields() + { + $fields = parent::getCMSFields(); + + // Settings + $fields->addFieldsToTab('Root.Settings', array( + HeaderField::create('DisplayOptions', 'Display Options', 3), + OptionsetField::create('Unit', 'Unit of measure', array('m' => 'Miles', 'km' => 'Kilometers')), + )); + + // Filter categories + $config = GridFieldConfig_RelationEditor::create(); + if (class_exists('GridFieldAddExistingSearchButton')) { + $config->removeComponentsByType('GridFieldAddExistingAutocompleter'); + $config->addComponent(new GridFieldAddExistingSearchButton()); + } + $categories = $this->Categories(); + $categoriesField = GridField::create('Categories', 'Categories', $categories, $config) + ->setDescription('only show locations from the selected category'); + + // Filter + $fields->addFieldsToTab('Root.Filter', array( + HeaderField::create('CategoryOptionsHeader', 'Location Filtering', 3), + $categoriesField, + )); + + $this->extend('updateCMSFields', $fields); + + return $fields; + } + + /** + * @param array $filter + * @param array $filterAny + * @param array $exclude + * @param null|callable $callback + * @return DataList|ArrayList + */ + public static function get_locations( + $filter = [], + $filterAny = [], + $exclude = [], + $callback = null + ) + { + $locationClass = Config::inst()->get('Dynamic\\Locator\\Locator', 'location_class'); + $locations = $locationClass::get()->filter($filter)->exclude($exclude); + + if (!empty($filterAny)) { + $locations = $locations->filterAny($filterAny); + } + if (!empty($exclude)) { + $locations = $locations->exclude($exclude); + } + + if ($callback !== null && is_callable($callback)) { + $locations->filterByCallback($callback); + } + + return $locations; + } + + /** + * @return DataList + */ + public static function get_all_categories() + { + return LocationCategory::get(); + } + + /** + * @return bool + */ + public function getPageCategories() + { + return self::locator_categories_by_locator($this->ID); + } + + /** + * @param int $id + * @return bool| + */ + public static function locator_categories_by_locator($id = 0) + { + if ($id == 0) { + return false; + } + + return Locator::get()->byID($id)->Categories(); + } +} diff --git a/code/pages/Locator.php b/src/pages/LocatorController.php similarity index 60% rename from code/pages/Locator.php rename to src/pages/LocatorController.php index 3b53a5c..df8d378 100644 --- a/code/pages/Locator.php +++ b/src/pages/LocatorController.php @@ -2,165 +2,21 @@ namespace Dynamic\Locator; -use SilverStripe\Forms\Form, - SilverStripe\Forms\FieldList, - SilverStripe\Forms\HeaderField, - SilverStripe\Forms\OptionsetField, - SilverStripe\Forms\CheckboxField, - SilverStripe\Forms\GridField\GridField, - SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor, - SilverStripe\ORM\DataList, - SilverStripe\ORM\ArrayList, - SilverStripe\Core\Config\Config, - SilverStripe\Control\Controller, - SilverStripe\View\Requirements, - SilverStripe\Control\HTTPRequest, - muskie9\DataToArrayList\ORM\DataToArrayListHelper; +use Dynamic\Locator\Locator; +use Dynamic\Locator\LocatorForm; +use Dynamic\SilverStripeGeocoder\GoogleGeocoder; +use muskie9\DataToArrayList\ORM\DataToArrayListHelper; +use SilverStripe\Control\Controller; +use SilverStripe\Core\Config\Config; +use SilverStripe\Dev\Debug; +use SilverStripe\ORM\ArrayList; +use SilverStripe\View\Requirements; +use SilverStripe\Control\HTTPRequest; /** - * Class Locator - * - * @property bool $AutoGeocode - * @property bool $ModalWindow - * @property string $Unit - * @method Categories|ManyManyList $Categories + * Class LocatorController */ -class Locator extends \Page -{ - - /** - * @var array - */ - private static $db = array( - 'Unit' => 'Enum("m,km","m")', - ); - - /** - * @var array - */ - private static $many_many = array( - 'Categories' => 'Dynamic\\Locator\\LocationCategory', - ); - - /** - * @var string - */ - private static $singular_name = 'Locator'; - /** - * @var string - */ - private static $plural_name = 'Locators'; - /** - * @var string - */ - private static $description = 'Find locations on a map'; - - /** - * @var string - */ - private static $location_class = 'Dynamic\\Locator\\Location'; - - /** - * @return FieldList - */ - public function getCMSFields() - { - $fields = parent::getCMSFields(); - - // Settings - $fields->addFieldsToTab('Root.Settings', array( - HeaderField::create('DisplayOptions', 'Display Options', 3), - OptionsetField::create('Unit', 'Unit of measure', array('m' => 'Miles', 'km' => 'Kilometers')), - )); - - // Filter categories - $config = GridFieldConfig_RelationEditor::create(); - if (class_exists('GridFieldAddExistingSearchButton')) { - $config->removeComponentsByType('GridFieldAddExistingAutocompleter'); - $config->addComponent(new GridFieldAddExistingSearchButton()); - } - $categories = $this->Categories(); - $categoriesField = GridField::create('Categories', 'Categories', $categories, $config) - ->setDescription('only show locations from the selected category'); - - // Filter - $fields->addFieldsToTab('Root.Filter', array( - HeaderField::create('CategoryOptionsHeader', 'Location Filtering', 3), - $categoriesField, - )); - - $this->extend('updateCMSFields', $fields); - - return $fields; - } - - /** - * @param array $filter - * @param array $filterAny - * @param array $exclude - * @param null|callable $callback - * @return DataList|ArrayList - */ - public static function get_locations( - $filter = [], - $filterAny = [], - $exclude = [], - $callback = null - ) - { - $locationClass = Config::inst()->get('Dynamic\\Locator\\Locator', 'location_class'); - $locations = $locationClass::get()->filter($filter)->exclude($exclude); - - if (!empty($filterAny)) { - $locations = $locations->filterAny($filterAny); - } - if (!empty($exclude)) { - $locations = $locations->exclude($exclude); - } - - if ($callback !== null && is_callable($callback)) { - $locations->filterByCallback($callback); - } - - return $locations; - } - - /** - * @return DataList - */ - public static function get_all_categories() - { - return LocationCategory::get(); - } - - /** - * @return bool - */ - public function getPageCategories() - { - return self::locator_categories_by_locator($this->ID); - } - - /** - * @param int $id - * @return bool| - */ - public static function locator_categories_by_locator($id = 0) - { - if ($id == 0) { - return false; - } - - return Locator::get()->byID($id)->Categories(); - } - - -} - -/** - * Class Locator_Controller - */ -class Locator_Controller extends \Page_Controller +class LocatorController extends \PageController { /** * @var array @@ -242,16 +98,16 @@ public function init() // prevent init of map if no query $request = Controller::curr()->getRequest(); + if ($this->getTrigger($request)) { // google maps api key - $key = Config::inst()->get('GoogleGeocoding', 'google_api_key'); + $key = Config::inst()->get(GoogleGeocoder::class, 'geocoder_api_key'); $locations = $this->getLocations(); if ($locations) { - Requirements::css('locator/css/map.css'); - Requirements::javascript('framework/thirdparty/jquery/jquery.js'); + Requirements::javascript('https://code.jquery.com/jquery-1.11.2.min.js'); Requirements::javascript('https://maps.google.com/maps/api/js?key=' . $key); Requirements::javascript('locator/thirdparty/jquery-store-locator-plugin/assets/js/libs/handlebars.min.js'); Requirements::javascript('locator/thirdparty/jquery-store-locator-plugin/assets/js/plugins/storeLocator/jquery.storelocator.js'); @@ -264,12 +120,12 @@ public function init() : 'featuredLocations: false'; // map config based on user input in Settings tab - $limit = Config::inst()->get('Locator_Controller', 'limit'); + $limit = Config::inst()->get(LocatorController::class, 'limit'); if ($limit < 1) $limit = -1; $load = 'fullMapStart: true, storeLimit: ' . $limit . ', maxDistance: true,'; - $listTemplatePath = Config::inst()->get('Locator_Controller', 'list_template_path'); - $infowindowTemplatePath = Config::inst()->get('Locator_Controller', 'info_window_template_path'); + $listTemplatePath = Config::inst()->get(LocatorController::class, 'list_template_path'); + $infowindowTemplatePath = Config::inst()->get(LocatorController::class, 'info_window_template_path'); $kilometer = ($this->data()->Unit == 'km') ? "lengthUnit: 'km'" : "lengthUnit: 'm'"; @@ -283,8 +139,8 @@ public function init() $link = Controller::join_links($this->Link(), 'xml.xml', $url); // containers - $map_id = Config::inst()->get('Locator_Controller', 'map_container'); - $list_class = Config::inst()->get('Locator_Controller', 'list_container'); + $map_id = Config::inst()->get(LocatorController::class, 'map_container'); + $list_class = Config::inst()->get(LocatorController::class, 'list_container'); // init map Requirements::customScript(" @@ -402,7 +258,7 @@ public function setLocations(HTTPRequest $request = null) $locations = $locations->sort('distance'); } - if (Config::inst()->get('LocatorForm', 'show_radius')) { + if (Config::inst()->get(LocatorForm::class, 'show_radius')) { if ($radius = (int)$request->getVar('Radius')) { $locations = $locations->filterByCallback(function ($location) use (&$radius) { return $location->distance <= $radius; @@ -413,7 +269,7 @@ public function setLocations(HTTPRequest $request = null) //allow for returning list to be set as $this->extend('updateListType', $locations); - $limit = Config::inst()->get('Locator_Controller', 'limit'); + $limit = Config::inst()->get(LocatorController::class, 'limit'); if ($limit > 0) { $locations = $locations->limit($limit); } @@ -424,15 +280,15 @@ public function setLocations(HTTPRequest $request = null) } /** - * @param SS_HTTPRequest $request + * @param HTTPRequest $request * @return bool */ - public function getTrigger(SS_HTTPRequest $request = null) + public function getTrigger(HTTPRequest $request = null) { if ($request === null) { $request = $this->getRequest(); } - $trigger = $request->getVar(Config::inst()->get('Locator_Controller', 'query_trigger')); + $trigger = $request->getVar(Config::inst()->get(LocatorController::class, 'query_trigger')); return isset($trigger); } @@ -444,11 +300,11 @@ public function getAddressSearchCoords() if (!$this->request->getVar('Address')) { return false; } - if (class_exists('GoogleGeocoding')) { - $coords = GoogleGeocoding::address_to_point(Controller::curr()->getRequest()->getVar('Address')); - - $lat = $coords['lat']; - $lng = $coords['lng']; + if (class_exists(GoogleGeocoder::class)) { + $geocoder = new GoogleGeocoder($this->request->getVar('Address')); + $response = $geocoder->getResult(); + $lat = $response->getLatitude(); + $lng = $response->getLongitude(); return "defaultLat: {$lat}, defaultLng: {$lng},"; } @@ -460,13 +316,13 @@ public function getAddressSearchCoords() * * Search form for locations, updates map and results list via AJAX * - * @return Form + * @return \SilverStripe\Forms\Form */ public function LocationSearch() { $form = LocatorForm::create($this, 'LocationSearch'); - if (class_exists('BootstrapForm') && $this->config()->get('bootstrapify')) { + if (class_exists(BootstrapForm::class) && $this->config()->get('bootstrapify')) { $form->Fields()->bootstrapify(); $form->Actions()->bootstrapify(); } @@ -477,4 +333,4 @@ public function LocationSearch() ->disableSecurityToken() ->loadDataFrom($this->request->getVars()); } -} +} \ No newline at end of file diff --git a/tasks/EmailAddressTask.php b/tasks/EmailAddressTask.php index 5114275..2ed17b8 100644 --- a/tasks/EmailAddressTask.php +++ b/tasks/EmailAddressTask.php @@ -1,5 +1,9 @@ - <% loop $Locations %>distance="$distance"<% end_if %> /><% end_loop %> - -<% end_if %> \ No newline at end of file + <% loop $Locations %>distance="$distance"<% end_if %>/> + <% end_loop %> + \ No newline at end of file diff --git a/tests/LocationCategoryTest.php b/tests/LocationCategoryTest.php index 90825ac..d4b88e8 100644 --- a/tests/LocationCategoryTest.php +++ b/tests/LocationCategoryTest.php @@ -1,5 +1,12 @@ objFromFixture('LocationCategory', 'service'); + $object = $this->objFromFixture(LocationCategory::class, 'service'); $fieldset = $object->getCMSFields(); - $this->assertTrue(is_a($fieldset, 'FieldList')); + $this->assertInstanceOf(FieldList::class, $fieldset); } /** @@ -26,7 +33,7 @@ public function testGetCMSFields() */ public function testCanView() { - $object = $this->objFromFixture('LocationCategory', 'service'); + $object = $this->objFromFixture(LocationCategory::class, 'service'); $this->assertTrue($object->canView()); } @@ -35,12 +42,12 @@ public function testCanView() */ public function testCanEdit() { - $object = $this->objFromFixture('LocationCategory', 'service'); + $object = $this->objFromFixture(LocationCategory::class, 'service'); - $admin = $this->objFromFixture('Member', 'locationedit'); + $admin = $this->objFromFixture(Member::class, 'locationedit'); $this->assertTrue($object->canEdit($admin)); - $member = $this->objFromFixture('Member', 'default'); + $member = $this->objFromFixture(Member::class, 'default'); $this->assertFalse($object->canEdit($member)); } @@ -49,12 +56,12 @@ public function testCanEdit() */ public function testCanDelete() { - $object = $this->objFromFixture('LocationCategory', 'service'); + $object = $this->objFromFixture(LocationCategory::class, 'service'); - $admin = $this->objFromFixture('Member', 'locationdelete'); + $admin = $this->objFromFixture(Member::class, 'locationdelete'); $this->assertTrue($object->canDelete($admin)); - $member = $this->objFromFixture('Member', 'default'); + $member = $this->objFromFixture(Member::class, 'default'); $this->assertFalse($object->canDelete($member)); } @@ -63,12 +70,12 @@ public function testCanDelete() */ public function testCanCreate() { - $object = $this->objFromFixture('LocationCategory', 'service'); + $object = $this->objFromFixture(LocationCategory::class, 'service'); - $admin = $this->objFromFixture('Member', 'locationcreate'); + $admin = $this->objFromFixture(Member::class, 'locationcreate'); $this->assertTrue($object->canCreate($admin)); - $member = $this->objFromFixture('Member', 'default'); + $member = $this->objFromFixture(Member::class, 'default'); $this->assertFalse($object->canCreate($member)); } } diff --git a/tests/Locator_Test.php b/tests/LocatorBaseTest.php similarity index 94% rename from tests/Locator_Test.php rename to tests/LocatorBaseTest.php index b9d3a95..1d32df6 100644 --- a/tests/Locator_Test.php +++ b/tests/LocatorBaseTest.php @@ -7,7 +7,7 @@ /** * Class Locator_Test */ -class Locator_Test extends FunctionalTest +class LocatorBaseTest extends FunctionalTest { /** diff --git a/tests/LocatorFormTest.php b/tests/LocatorFormTest.php index a7bfe07..25df9d3 100644 --- a/tests/LocatorFormTest.php +++ b/tests/LocatorFormTest.php @@ -1,39 +1,44 @@ first()), 'LocatorForm'); + $form = LocatorForm::create(LocatorController::create(Locator::get()->first()), 'LocatorForm'); - $this->assertInstanceOf('FieldList', $form->Fields()); - $this->assertInstanceOf('RequiredFields', $form->getValidator()); + $this->assertInstanceOf(FieldList::class, $form->Fields()); + $this->assertInstanceOf(RequiredFields::class, $form->getValidator()); } + /** + * + */ public function testUpdateRequiredFields() { - $form = LocatorFormExtendedForm::create(Locator_Controller::create(Locator::get()->first()), 'LocatorForm'); - - $this->assertEquals(['Foo'], $form->getValidator()->getRequired()); - } - -} + $form = LocatorForm::create(LocatorController::create(Locator::get()->first()), 'LocatorForm'); + $validator = $form->getValidator(); -class LocatorFormTestFormExtension extends Extension implements TestOnly -{ - public function updateRequiredFields(RequiredFields $validator) - { $validator->removeRequiredField('Address'); $validator->addRequiredField('Foo'); - } -} -class LocatorFormExtendedForm extends LocatorForm implements TestOnly -{ - - private static $extensions = [ - 'LocatorFormTestFormExtension', - ]; + $this->assertEquals(['Foo'], $form->getValidator()->getRequired()); + } } \ No newline at end of file diff --git a/tests/LocatorTest.php b/tests/LocatorTest.php index fc98a6a..8cf5a39 100644 --- a/tests/LocatorTest.php +++ b/tests/LocatorTest.php @@ -2,17 +2,16 @@ namespace Dynamic\Locator\Tests; -use Dynamic\Locator\Location, - Dynamic\Locator\Locator, - Dynamic\Locator\Locator_Controller, - SilverStripe\Core\Config\Config; +use Dynamic\Locator\Location; +use Dynamic\Locator\Locator; +use Dynamic\Locator\LocatorController; +use SilverStripe\Core\Config\Config; /** * Class LocatorTest */ -class LocatorTest extends Locator_Test +class LocatorTest extends LocatorBaseTest { - /** * */ @@ -27,9 +26,9 @@ public function testGetCMSFields() */ public function testLocations() { - $filter = Config::inst()->get('Dynamic\\Locator\\Locator_Controller', 'base_filter'); - $filterAny = Config::inst()->get('Dynamic\\Locator\\Locator_Controller', 'base_filter_any'); - $exclude = Config::inst()->get('Dynamic\\Locator\\Locator_Controller', 'base_exclude'); + $filter = Config::inst()->get(LocatorController::class, 'base_filter'); + $filterAny = Config::inst()->get(LocatorController::class, 'base_filter_any'); + $exclude = Config::inst()->get(LocatorController::class, 'base_exclude'); $locations = Locator::get_locations($filter, $filterAny, $exclude); $locations2 = Location::get()->filter($filter)->filterAny($filterAny)->exclude($exclude); $this->assertEquals($locations->count(), $locations2->count()); @@ -83,7 +82,7 @@ public function testInit() public function testIndex() { $locator = $this->objFromFixture('Dynamic\\Locator\\Locator', 'locator1'); - $controller = Locator_Controller::create($locator); + $controller = LocatorController::create($locator); $this->assertInstanceOf('SilverStripe\\View\\ViewableData', $controller->index($controller->request)); } @@ -93,7 +92,7 @@ public function testIndex() public function testXml() { $locator = $this->objFromFixture('Dynamic\\Locator\\Locator', 'locator1'); - $controller = Locator_Controller::create($locator); + $controller = LocatorController::create($locator); $this->assertInstanceOf('SilverStripe\\ORM\\FieldType\\DBHTMLText', $controller->xml($controller->request)); } @@ -103,7 +102,7 @@ public function testXml() public function testLocationSearch() { $locator = $this->objFromFixture('Dynamic\\Locator\\Locator', 'locator1'); - $object = Locator_Controller::create($locator); + $object = LocatorController::create($locator); $form = $object->LocationSearch(); $this->assertTrue(is_a($form, 'SilverStripe\\Forms\\Form')); @@ -122,8 +121,8 @@ public function testLocationSearch() */ public function testLocationInfoTemplates() { - $this->assertEquals('locator/templates/location-list-description.html', Config::inst()->get('Locator_Controller', 'list_template_path')); - $this->assertEquals('locator/templates/infowindow-description.html', Config::inst()->get('Locator_Controller', 'info_window_template_path')); + $this->assertEquals('locator/templates/location-list-description.html', Config::inst()->get(LocatorController::class, 'list_template_path')); + $this->assertEquals('locator/templates/infowindow-description.html', Config::inst()->get(LocatorController::class, 'info_window_template_path')); } } diff --git a/tests/Locator_Test.yml b/tests/Locator_Test.yml index 9c00744..6c0270a 100644 --- a/tests/Locator_Test.yml +++ b/tests/Locator_Test.yml @@ -34,6 +34,10 @@ SilverStripe\Security\Member: Surname: Location Email: delete@test.com Groups: =>SilverStripe\Security\Group.locationdelete + default: + FirstName: Default + Surname: Member + email: default@test.com Dynamic\Locator\LocationCategory: service: Name: Service