tastyigniter / ti-ext-local
This extension allows your customers find and view menu items of their nearest location.
Fund package maintenance!
tastyigniter
Open Collective
Installs: 9 084
Dependents: 4
Suggesters: 0
Security: 0
Stars: 4
Watchers: 4
Forks: 23
Open Issues: 2
Type:tastyigniter-package
Requires
- tastyigniter/core: ^v4.0
- tastyigniter/ti-ext-automation: ^v4.0
- tastyigniter/ti-ext-cart: ^v4.0
- tastyigniter/ti-ext-reservation: ^v4.0
Requires (Dev)
- igniterlabs/ti-ext-importexport: v4.x-dev
- larastan/larastan: ^2.4.0
- laravel/pint: ^1.2
- pestphp/pest-plugin-laravel: ^3.0
- rector/rector: ^1.2
- sampoyigi/testbench: ^1.0
Suggests
- igniterlabs/ti-ext-importexport: For importing and exporting menu items.
This package is auto-updated.
Last update: 2025-03-07 14:06:52 UTC
README
Introduction
The TastyIgniter Local extension enhances your TastyIgniter application with location-based features. It allows you to manage multiple locations, set delivery areas, define opening hours, and much more.
Features
- Nearby Location Search: Allow customers to find the nearest location to their address.
- Delivery Areas (Zones) Boundary: Define delivery boundaries and charges for each location.
- Location Opening Hours: Set specific opening hours for each location.
- Location Reviews: Enable customers to leave reviews for each location.
- Custom Location Settings: Add custom fields to locations to store additional information.
Installation
You can install the extension via composer using the following command:
composer require tastyigniter/ti-ext-local:"^4.0" -W
Run the database migrations to create the required tables:
php artisan igniter:up
Getting started
If you only have one restaurant location, you can switch to single location mode by setting the IGNITER_LOCATION_MODE
environment variable to single
in your .env
file.
IGNITER_LOCATION_MODE=single
By default, the location mode is set to multiple
which allows you to manage multiple locations.
GeoCoder
The Local extension uses the Igniter\Flame\Geolite\Facades\Geocoder
facade to geocode addresses. You can configure the geocoder provider by setting the
Default Geocoder field to the desired provider in the Manage > Settings > General admin settings page.
Google Maps API Key
To use the Google Maps geocoder provider, you need to set the Google Maps API key in the Manage > Settings > General admin settings page. Follow the instructions on the page to get your API key.
Review Settings
You can enable or disable reviews by navigating to the Manage > Settings > Review settings admin settings page.
Usage
Locations
Creating locations
To create a location, navigate to Manage > Settings > Locations in the admin area. Click on the New button, fill in the required details such as name, address, and description, and save your changes.
Setting current location
To set the current location, use the Location
facade's setCurrent
method. Pass the location model instance as the argument. This will store the location in session and make it the current location for the user.
use Igniter\Local\Facades\Location; Location::setCurrent($location); // Then check if the location is open if (Location::isOpened()) { // Do something... }
After setting the current location, you can retrieve the current location later using the Location
facade's current
method.
$location = Location::current();
Setting user coordinates
To set the user's coordinates, use the Location
facade's updateUserPosition
method. Pass the Igniter\Flame\Geolite\Model\Location
instance as the argument. This will store the user's coordinates in session.
use Igniter\Flame\Geolite\Facades\Geocoder; use Igniter\Local\Facades\Location; $userLocation = Geocoder::geocode($userAddress)->first(); Location::updateUserPosition($userLocation);
Searching nearby locations
To search for nearby locations, use the Location
facade's searchByCoordinates
method. Pass the Igniter\Flame\Geolite\Model\Coordinates
object as the argument.
use Igniter\Flame\Geolite\Facades\Geocoder; use Igniter\Local\Facades\Location; $userLocation = Geocoder::geocode($userAddress)->first(); $locations = Location::searchByCoordinates($userLocation->getCoordinates());
Retrieving minimum order total
To retrieve the minimum order total for a location, use the minimumOrderTotal
method on the Location
facade. The method accepts the order type as an argument and returns the minimum order total for the current location.
$minimumOrderTotal = Location::minimumOrderTotal($orderType);
Checking minimum order total
After retrieving the minimum order total of the current location, you can check if the order total meets the minimum order total using the checkMinimumOrderTotal
method on the Location
facade.
if (Location::checkMinimumOrderTotal($orderTotal)) { // Do something... }
Location-aware controller action
To make the admin controller list and form action classes aware of the current location, use the Igniter\Local\Http\Actions\LocationAwareController
action class in your controller.
class MyController extends \Admin\Classes\AdminController { public array $implement = ['Igniter\Local\Http\Actions\LocationAwareController']; public array $locationConfig = [ 'applyScopeOnListQuery' => true, 'applyScopeOnFormQuery' => true, 'addAbsenceConstraint' => true, ] }
In the example above, the applyScopeOnListQuery
and applyScopeOnFormQuery
options will apply the location scope to the list and form queries respectively. This way you can filter records based on the current admin user's location. The addAbsenceConstraint
option when set to true
will add a constraint to the query to include records that are not associated with any location and when set to false
will exclude records that are not associated with any location.
Location settings
To add custom fields to the location settings form, you must define a registerLocationSettings
method on your extension class. This method should return an array of settings definition to be added to the location settings form.
public function registerLocationSettings() { return [ 'custom' => [ 'label' => 'Custom settings', 'description' => 'Custom settings description', 'icon' => 'fa fa-sliders', 'priority' => 0, 'form' => 'author.extension::/models/customsettings', 'request' => \Author\Extension\Http\Requests\CustomRequest::class, ], ]; }
The settings definition array should contain the following keys:
label
: The label of the settings section.description
: The description of the settings section.icon
: The icon class of the settings section.url
: The URL used to link to the settings section. Optional.priority
: The priority of the settings section.permissions
: The permissions required to access the settings section.form
: An array of form fields or path to the form definition file to be used for the settings section.request
: The form request class to be used for the settings section.
Delivery areas
Adding delivery areas
To add a delivery area, navigate to Restaurant > Settings > Delivery Areas in the admin area. Click on the Add button, fill in the required details such as name, boundary, and charges, and save your changes.
Defining delivery area boundary
To define a delivery area boundary, use the MapView form widget in your delivery area form. This widget allows you to draw the boundary on a map. You can also define area boundary using address components such as country, state, city, and postal code.
You can programmatically set the boundary using the boundaries
attribute on the Igniter\Local\Models\LocationArea
model instance.
$locationArea->type = 'address'; // or 'circle' or 'polygon' $locationArea->boundaries = [ 'polygon' => [ [ [0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0], [0.0, 0.0], ], ], 'circle' => [ 'center' => [0.0, 0.0], 'radius' => 1000, ], 'vertices' => [ [0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0], ], 'components' => [ ['type' => 'locality', 'value' => 'London', 'priority' => 0], ], ]; $locationArea->save();
Checking a point in boundary
After defining the boundary, you can check if a point is within the boundary using the checkBoundary
method on the Igniter\Local\Models\LocationArea
model instance.
$userLocation = Geocoder::geocode($userAddress)->first(); $locationArea->checkBoundary($userLocation->getCoordinates());
You can search all delivery areas using the searchDeliveryArea
method on the Igniter\Local\Models\Location
model instance.
use Igniter\Local\Models\Location; $location = Location::find(1); $locationArea = $location->searchDeliveryArea($userLocation->getCoordinates());
Using the Location
facade's checkDeliveryCoverage
method, you can check if a point is within the boundaries of the current location. The $userLocation
argument can be an instance of Igniter\Flame\Geolite\Model\Location
or null to use the user's coordinates stored in session.
$locationArea = Location::checkDeliveryCoverage($userLocation);
Defining delivery area charges
To set delivery charges for a delivery area, use the delivery area form. You can set a fixed charge or a charge based on the order total.
You can programmatically set the delivery charges using the conditions
attribute on the Igniter\Local\Models\LocationArea
model instance.
$locationArea->conditions = [ [ 'priority' => 1, 'amount' => 5.0, 'type' => 'all', // or 'above' or 'below' 'total' => 0, ], [ 'priority' => 2, 'amount' => 5.0, 'type' => 'below', 'total' => 50.0, ], ]; $locationArea->save();
Retrieving delivery area charge
After setting the delivery charges, you can retrieve the matching delivery charge for an order based on the order total using the deliveryAmount
method on the Igniter\Local\Classes\CoveredArea
class.
use Igniter\Local\Classes\CoveredArea; $coveredArea = new CoveredArea($locationArea); $deliveryAmount = $coveredArea->deliveryAmount($orderTotal);
Using the Location
facade's deliveryAmount
method, you can retrieve the matching delivery charge for the current location based on the order total.
$deliveryAmount = Location::deliveryAmount($orderTotal);
Setting user delivery area
To set the user's delivery area, use the Location
facade's updateNearbyArea
method. Pass the Igniter\Local\Models\LocationArea
instance as the argument. This will store the user's delivery area in session.
use Igniter\Local\Facades\Location; Location::updateNearbyArea($locationArea);
Delivery cart condition
A delivery cart condition class that allows you to apply delivery charges to the cart based on the delivery area and order total. This condition is added to your cart automatically when the delivery order type is selected.
You can retrieve the delivery fee applied to the cart using the getCondition
method on the Cart
facade.
use Igniter\Cart\Facades\Cart; $deliveryCondition = Cart::getCondition('delivery'); $deliveryFee = $deliveryCondition->getValue();
Working hours
Creating working hours
To create working hours, navigate to Restaurant > Settings > Schedules in the admin panel. Click on the Add button, fill in the required details such as day, open time, and close time, and save your changes.
You can programmatically set the location's working hours using the addOpeningHours
method on the Igniter\Local\Models\Location
model instance. The first argument is an array of working hours where the key is the type of working hours (e.g., opening, delivery, collection) and the value is an array of working hours.
$location->addOpeningHours([ 'opening' => [ 'type' => '24_7', // or 'daily' or 'timesheet' or 'flexible' 'days' => [], 'open' => null, 'close' => null, 'timesheet' => [], 'flexible' => [], ], 'delivery' => [ 'type' => 'daily', 'days' => [0, 1, 2, 3, 4, 5, 6], 'open' => '00:00', 'close' => '23:59', 'timesheet' => [], 'flexible' => [], ], 'collection' => [ 'type' => 'timesheet', 'days' => [], 'open' => null, 'close' => null, 'timesheet' => [ 0 => [ 'day' => 0, 'hours' => [ ['open' => '09:00', 'close' => '12:00'], ['open' => '13:00', 'close' => '17:00'], ], 'status' => 1, ] ], 'flexible' => [], ], ]);
Generating timeslots
To generate timeslots for a location, use the Location
facade. This will generate timeslots for the location based on the working hours and location settings. The getTimeslot
method returns a collection of timeslots where the key is the date string and value is an array of timeslots.
use Igniter\Local\Facades\Location; $openingTimeslots = Location::openingSchedule()->getTimeslot(); $deliveryTimeslots = Location::deliverySchedule()->getTimeslot(); $collectionTimeslots = Location::collectionSchedule()->getTimeslot(); // For custom types $customTimeslots = Location::workingSchedule('custom')->getTimeslot();
To generate timeslots for a specific day, pass a DateTime
instance as an argument to the generateTimeslot
method. This will return a collection of timeslots for the specified day where the key is the timestamp and value is a DateTime
instance.
use Igniter\Local\Facades\Location; $openingTimeslots = Location::openingSchedule()->generateTimeslot($dateTime); $deliveryTimeslots = Location::deliverySchedule()->generateTimeslot($dateTime); $collectionTimeslots = Location::collectionSchedule()->generateTimeslot($dateTime); // For custom types $customTimeslots = Location::workingSchedule('custom')->generateTimeslot($dateTime);
Checking availability
Checking a location is open
To check if the current location is open at the current time, use the isOpen
method of the WorkingSchedule class. This method returns a boolean value indicating whether the location is open.
if (Location::deliverySchedule()->isOpen()) { // Do something... }
Checking a location is opening soon
To check if a location is opening soon, use the isOpening
method of the WorkingSchedule class. This method returns a boolean value indicating whether the location is opening soon.
if (Location::deliverySchedule()->isOpening()) { // Do something... }
Checking a location is closed
To check if the current location is closed at the current time, use the isClosed
method of the WorkingSchedule class. This method returns a boolean value indicating whether the location is closed.
if (Location::deliverySchedule()->isClosed()) { // Do something... }
Checking a location is opening at a specific time
To check if a location is open at a specific time, use the isOpenAt
method of the WorkingSchedule class. Pass a DateTime
object as the argument. This method returns a boolean value indicating whether the location is open at the specified time.
if (Location::deliverySchedule()->isOpenAt($dateTime)) { // Do something... }
Checking when next a location is open
To check when next a location is open, use the nextOpenAt
method of the WorkingSchedule class. This method accepts a DateTime
object as argument and returns a DateTime
object indicating when the location will next open.
$nextOpenAt = Location::deliverySchedule()->nextOpenAt($dateTime);
Checking a location is closed at a specific time
To check if a location is closed at a specific time, use the isClosedAt
method of the WorkingSchedule class. Pass a DateTime
object as the argument. This method returns a boolean value indicating whether the location is closed at the specified time.
if (Location::deliverySchedule()->isClosedAt($dateTime)) { // Do something... }
Setting exceptions
To set exceptions for the location's working hours, use the setExceptions
method of the WorkingSchedule class. Pass an array of exceptions as the argument. The array should have the date string as the key and an array of times as the value.
use Igniter\Local\Facades\Location; Location::deliverySchedule()->setExceptions([ '2022-01-01' => [ ['01:00', '04:59'], ['18:00', '23:59'], ], '2022-12-25' => [], ]);
Setting user order schedule time
To set the user's order fulfilment time, use the Location
facade's updateScheduleTimeSlot
method. The first argument is a DateTime
object, and the second argument is a boolean value indicating whether the user is ordering for ASAP. This will store the user's order time in session.
use Igniter\Local\Facades\Location; Location::updateScheduleTimeSlot($dateTime, $isAsap);
Reviews
Reviewing orders and reservations
To enable users to review orders and reservations, navigate to Manage > Settings > Review settings in the admin area and enable the Allow Reviews option.
Programmatically, you can create reviews for an order or reservation using the Igniter\Local\Models\Review
model instance.
use Igniter\Local\Models\Review; use Igniter\Cart\Models\Order; // use Igniter\Reservation\Models\Reservation; $record = Order::find(1); // $record = Reservation::find(1); $review = $record->leaveReview([ 'quality' => 5, 'delivery' => 5, 'service' => 5, 'review_text' => 'Great food and service!', ]);
Review chase automation rule
This extension provides a review chase automation rule that sends an email to customers to remind them to leave a review after an order. To enable this rule, navigate to Tools > Automations in the admin area and enable the Send a message to leave a review after 24 hours rule.
Review count automation condition
A review count automation condition class that allows you to trigger automation rules based on the number of reviews an order or reservation has. This condition can be added to your automation rules to trigger actions based on the review count. The following attribute is available:
review_count
: The number of reviews an order or reservation has. Usually set to0
or1
.
Form Widgets
Star Rating
The starrating
form widget allows you to display a star rating input in your forms.
Add the following code to your form definition file:
'my_field' => [ 'label' => 'Star Rating', 'type' => 'starrating', ],
The following options are available for the starrating
form widget type:
hints
: (array) An array of hints to display below the star rating input. Optional.
Map Area
The maparea
form widget allows you to manage your delivery areas.
Add the following code to your form definition file:
'my_field' => [ 'label' => 'Map Area', 'type' => 'maparea', 'form' => 'locationarea', 'request' => \Igniter\Local\Http\Requests\LocationAreaRequest::class, ],
The following options are available for the maparea
form widget type:
form
: (string) This is either an array or path to the form definition file to be used for the map area form. Required.modelClass
: (string) The model class to be used for the map area form. Required.prompt
: (string) The label for the add button. Optional.sortable
: (bool) Whether to enable sorting of the map area items. Optional.formName
: (string) The form name to be used for the map area form. Optional.addLabel
: (string) The prefix for the add map area form titleeditLabel
: (string) The prefix for the edit map area form titledeleteLabel
: (string) The prefix for the delete map area form title
Map View
The mapview
form widget allows you to draw a boundary on a map. You can use it in your delivery area form to define the delivery boundary.
Add the following code to your form definition file:
'my_field' => [ 'label' => 'Map View', 'type' => 'mapview', 'zoom' => 14, 'height' => 640, ],
The following options are available for the mapview
form widget type:
zoom
: (int) The initial zoom level of the map. Optional.height
: (int) The height of the map in pixels. Optional.center
: (array) The initial center of the map. An array of latitude and longitude.['lat' => 0.0, 'lng' => 0.0]
Optional.
Working Schedule Editor
The scheduleeditor
form widget allows you to manage your location's working hours.
Add the following code to your form definition file:
'my_field' => [ 'label' => 'Working Schedule', 'type' => 'scheduleeditor', 'form' => 'workingschedule', ],
The following options are available for the scheduleeditor
form widget type:
form
: (string) This is either an array or path to the form definition file to be used for the working schedule form. Required.formTitle
: (string) The title of the schedule editor form. Optional.popupSize
: (string) The size of the modal dialog. Optional. Available options aremodal-sm
,modal-md
,modal-lg
,modal-xl
.request
: (string) The form request class to be used for validating the schedule editor form. Optional.
Location Settings Editor
The settingseditor
form widget allows you to add custom fields to the location settings form.
Add the following code to your form definition file:
'my_field' => [ 'label' => 'Location Settings', 'type' => 'settingseditor', ],
No options are available for the settingseditor
form widget type.
Mail templates
The Local extension registers the following mail templates:
igniter.local::mail.review_chase
- Review chase email template to remind customers to leave a review after an order.
You can send the above mail template using the mailSend
method on the SendsMailTemplate model trait attached to Igniter\Cart\Models\Order
model:
use Igniter\Cart\Models\Order; $order = Order::find(1); $order->mailSend('igniter.local::mail.review_chase', 'customer');
Permissions
The Local extension registers the following permissions:
Admin.Locations
: Control who can manage locations in the admin area.Admin.Reviews
: Control who can manage reviews in the admin area.
For more on restricting access to the admin area, see the TastyIgniter Permissions documentation.
Events
The Local extension provides the following events:
Event | Description | Parameters |
---|---|---|
location.current.updated |
When the current location is updated. | The Location model instance |
location.position.updated |
When the user's coordinates are updated. | The Location class instance, the UserLocation user position instance and previous UserLocation user position instance |
location.orderType.updated |
When the location's order type is updated. | The Location class instance, the order type string and previous order type string |
location.timeslot.updated |
When the location's order fulfilment time is updated. | The Location class instance |
location.area.updated |
When the location's delivery area is updated. | The Location class instance and the CoveredArea class instance |
igniter.workingSchedule.created |
When a working schedule is created. | The Location model instance and the WorkingSchedule instance |
igniter.workingSchedule.timeslotValid |
When a working schedule timeslot is validated. | The WorkingSchedule instance and the DateTime instance |
Here is an example of hooking an event in the boot
method of an extension class:
use Illuminate\Support\Facades\Event; public function boot() { Event::listen('location.current.updated', function ($location) { // Do something... }); }
Changelog
Please see CHANGELOG for more information on what has changed recently.
Reporting issues
If you encounter a bug in this extension, please report it using the Issue Tracker on GitHub.
Contributing
Contributions are welcome! Please read TastyIgniter's contributing guide.
Security vulnerabilities
For reporting security vulnerabilities, please see our our security policy.
License
TastyIgniter Local extension is open-source software licensed under the MIT license.