diff --git a/application/controllers/Booking.php b/application/controllers/Booking.php index 3d77b2ce..5800dd29 100755 --- a/application/controllers/Booking.php +++ b/application/controllers/Booking.php @@ -33,7 +33,7 @@ class Booking extends EA_Controller { $this->load->model('providers_model'); $this->load->model('admins_model'); $this->load->model('secretaries_model'); - $this->load->model('categories_model'); + $this->load->model('service_categories_model'); $this->load->model('services_model'); $this->load->model('customers_model'); $this->load->model('settings_model'); diff --git a/application/controllers/Categories.php b/application/controllers/Service_categories.php similarity index 67% rename from application/controllers/Categories.php rename to application/controllers/Service_categories.php index 06e78ad0..67168470 100644 --- a/application/controllers/Categories.php +++ b/application/controllers/Service_categories.php @@ -12,21 +12,21 @@ * ---------------------------------------------------------------------------- */ /** - * Categories controller. + * Service-categories controller. * - * Handles the categories related operations. + * Handles the service-categories related operations. * * @package Controllers */ -class Categories extends EA_Controller { +class Service_categories extends EA_Controller { /** - * Categories constructor. + * Service-categories constructor. */ public function __construct() { parent::__construct(); - $this->load->model('categories_model'); + $this->load->model('service_categories_model'); $this->load->model('roles_model'); $this->load->library('accounts'); @@ -35,9 +35,9 @@ class Categories extends EA_Controller { } /** - * Render the backend categories page. + * Render the backend service-categories page. * - * On this page admin users will be able to manage categories, which are eventually selected by customers during the + * On this page admin users will be able to manage service-categories, which are eventually selected by customers during the * booking process. */ public function index() @@ -73,11 +73,11 @@ class Categories extends EA_Controller { 'privileges' => $this->roles_model->get_permissions_by_slug($role_slug), ]); - $this->load->view('pages/categories'); + $this->load->view('pages/service_categories'); } /** - * Filter categories by the provided keyword. + * Filter service-categories by the provided keyword. */ public function search() { @@ -96,9 +96,9 @@ class Categories extends EA_Controller { $offset = 0; - $categories = $this->categories_model->search($keyword, $limit, $offset, $order_by); + $service_categories = $this->service_categories_model->search($keyword, $limit, $offset, $order_by); - json_response($categories); + json_response($service_categories); } catch (Throwable $e) { @@ -107,7 +107,7 @@ class Categories extends EA_Controller { } /** - * Create a category. + * Create a service-category. */ public function create() { @@ -118,22 +118,22 @@ class Categories extends EA_Controller { abort(403, 'Forbidden'); } - $category = request('category'); + $service_category = request('service_category'); - $this->categories_model->only($category, [ + $this->service_categories_model->only($service_category, [ 'name', 'description' ]); - $category_id = $this->categories_model->save($category); + $service_category_id = $this->service_categories_model->save($service_category); - $category = $this->categories_model->find($category_id); + $service_category = $this->service_categories_model->find($service_category_id); - $this->webhooks_client->trigger(WEBHOOK_CATEGORY_SAVE, $category); + $this->webhooks_client->trigger(WEBHOOK_CATEGORY_SAVE, $service_category); json_response([ 'success' => TRUE, - 'id' => $category_id + 'id' => $service_category_id ]); } catch (Throwable $e) @@ -143,7 +143,7 @@ class Categories extends EA_Controller { } /** - * Update a category. + * Update a service-category. */ public function update() { @@ -154,23 +154,23 @@ class Categories extends EA_Controller { abort(403, 'Forbidden'); } - $category = request('category'); + $service_category = request('service_category'); - $this->categories_model->only($category, [ + $this->service_categories_model->only($service_category, [ 'id', 'name', 'description' ]); - $category_id = $this->categories_model->save($category); + $service_category_id = $this->service_categories_model->save($service_category); - $category = $this->categories_model->find($category_id); + $service_category = $this->service_categories_model->find($service_category_id); - $this->webhooks_client->trigger(WEBHOOK_CATEGORY_SAVE, $category); + $this->webhooks_client->trigger(WEBHOOK_CATEGORY_SAVE, $service_category); json_response([ 'success' => TRUE, - 'id' => $category_id + 'id' => $service_category_id ]); } catch (Throwable $e) @@ -180,7 +180,7 @@ class Categories extends EA_Controller { } /** - * Remove a category. + * Remove a service-category. */ public function destroy() { @@ -191,13 +191,13 @@ class Categories extends EA_Controller { abort(403, 'Forbidden'); } - $category_id = request('category_id'); + $service_category_id = request('service_category_id'); - $category = $this->categories_model->find($category_id); + $service_category = $this->service_categories_model->find($service_category_id); - $this->categories_model->delete($category_id); + $this->service_categories_model->delete($service_category_id); - $this->webhooks_client->trigger(WEBHOOK_CATEGORY_DELETE, $category); + $this->webhooks_client->trigger(WEBHOOK_CATEGORY_DELETE, $service_category); json_response([ 'success' => TRUE, @@ -210,7 +210,7 @@ class Categories extends EA_Controller { } /** - * Find a category. + * Find a service-category. */ public function find() { @@ -221,11 +221,11 @@ class Categories extends EA_Controller { abort(403, 'Forbidden'); } - $category_id = request('category_id'); + $service_category_id = request('service_category_id'); - $category = $this->categories_model->find($category_id); + $service_category = $this->service_categories_model->find($service_category_id); - json_response($category); + json_response($service_category); } catch (Throwable $e) { diff --git a/application/controllers/api/v1/Categories_api_v1.php b/application/controllers/api/v1/Service_categories_api_v1.php similarity index 50% rename from application/controllers/api/v1/Categories_api_v1.php rename to application/controllers/api/v1/Service_categories_api_v1.php index 6793b0c4..bf298e69 100644 --- a/application/controllers/api/v1/Categories_api_v1.php +++ b/application/controllers/api/v1/Service_categories_api_v1.php @@ -12,13 +12,13 @@ * ---------------------------------------------------------------------------- */ /** - * Categories API v1 controller. + * Service-categories API v1 controller. * * @package Controllers */ -class Categories_api_v1 extends EA_Controller { +class Service_categories_api_v1 extends EA_Controller { /** - * Categories_api_v1 constructor. + * Service_categories_api_v1 constructor. */ public function __construct() { @@ -28,11 +28,11 @@ class Categories_api_v1 extends EA_Controller { $this->api->auth(); - $this->api->model('categories_model'); + $this->api->model('service_categories_model'); } /** - * Get a category collection. + * Get a service-category collection. */ public function index() { @@ -50,26 +50,26 @@ class Categories_api_v1 extends EA_Controller { $with = $this->api->request_with(); - $categories = empty($keyword) - ? $this->categories_model->get(NULL, $limit, $offset, $order_by) - : $this->categories_model->search($keyword, $limit, $offset, $order_by); + $service_categories = empty($keyword) + ? $this->service_categories_model->get(NULL, $limit, $offset, $order_by) + : $this->service_categories_model->search($keyword, $limit, $offset, $order_by); - foreach ($categories as &$category) + foreach ($service_categories as &$service_category) { - $this->categories_model->api_encode($category); + $this->service_categories_model->api_encode($service_category); if ( ! empty($fields)) { - $this->categories_model->only($category, $fields); + $this->service_categories_model->only($service_category, $fields); } if ( ! empty($with)) { - $this->categories_model->load($category, $with); + $this->service_categories_model->load($service_category, $with); } } - json_response($categories); + json_response($service_categories); } catch (Throwable $e) { @@ -78,9 +78,9 @@ class Categories_api_v1 extends EA_Controller { } /** - * Get a single category. + * Get a single service-category. * - * @param int|null $id Category ID. + * @param int|null $id Service-category ID. */ public function show(int $id = NULL) { @@ -90,28 +90,28 @@ class Categories_api_v1 extends EA_Controller { $with = $this->api->request_with(); - $category = $this->categories_model->find($id); + $service_category = $this->service_categories_model->find($id); - $this->categories_model->api_encode($category); + $this->service_categories_model->api_encode($service_category); if ( ! empty($fields)) { - $this->categories_model->only($category, $fields); + $this->service_categories_model->only($service_category, $fields); } if ( ! empty($with)) { - $this->categories_model->load($category, $with); + $this->service_categories_model->load($service_category, $with); } - if ( ! $category) + if ( ! $service_category) { response('', 404); return; } - json_response($category); + json_response($service_category); } catch (Throwable $e) { @@ -120,28 +120,28 @@ class Categories_api_v1 extends EA_Controller { } /** - * Create a category. + * Create a service-category. */ public function store() { try { - $category = request(); + $service_category = request(); - $this->categories_model->api_decode($category); + $this->service_categories_model->api_decode($service_category); - if (array_key_exists('id', $category)) + if (array_key_exists('id', $service_category)) { - unset($category['id']); + unset($service_category['id']); } - $category_id = $this->categories_model->save($category); + $service_category_id = $this->service_categories_model->save($service_category); - $created_category = $this->categories_model->find($category_id); + $created_service_category = $this->service_categories_model->find($service_category_id); - $this->categories_model->api_encode($created_category); + $this->service_categories_model->api_encode($created_service_category); - json_response($created_category, 201); + json_response($created_service_category, 201); } catch (Throwable $e) { @@ -150,15 +150,15 @@ class Categories_api_v1 extends EA_Controller { } /** - * Update a category. + * Update a service-category. * - * @param int $id Category ID. + * @param int $id Service-category ID. */ public function update(int $id) { try { - $occurrences = $this->categories_model->get(['id' => $id]); + $occurrences = $this->service_categories_model->get(['id' => $id]); if (empty($occurrences)) { @@ -169,17 +169,17 @@ class Categories_api_v1 extends EA_Controller { $original_category = $occurrences[0]; - $category = request(); + $service_category = request(); - $this->categories_model->api_decode($category, $original_category); + $this->service_categories_model->api_decode($service_category, $original_category); - $category_id = $this->categories_model->save($category); + $service_category_id = $this->service_categories_model->save($service_category); - $updated_category = $this->categories_model->find($category_id); + $updated_service_category = $this->service_categories_model->find($service_category_id); - $this->categories_model->api_encode($updated_category); + $this->service_categories_model->api_encode($updated_service_category); - json_response($updated_category); + json_response($updated_service_category); } catch (Throwable $e) { @@ -188,15 +188,15 @@ class Categories_api_v1 extends EA_Controller { } /** - * Delete a category. + * Delete a service-category. * - * @param int $id Category ID. + * @param int $id Service-category ID. */ public function destroy(int $id) { try { - $occurrences = $this->categories_model->get(['id' => $id]); + $occurrences = $this->service_categories_model->get(['id' => $id]); if (empty($occurrences)) { @@ -205,7 +205,7 @@ class Categories_api_v1 extends EA_Controller { return; } - $this->categories_model->delete($id); + $this->service_categories_model->delete($id); response('', 204); } diff --git a/application/core/EA_Controller.php b/application/core/EA_Controller.php index 3def9319..59cdf8d7 100644 --- a/application/core/EA_Controller.php +++ b/application/core/EA_Controller.php @@ -41,7 +41,7 @@ * * @property Admins_model $admins_model * @property Appointments_model $appointments_model - * @property Categories_model $categories_model + * @property Service_categories_model $service_categories_model * @property Consents_model $consents_model * @property Customers_model $customers_model * @property Providers_model $providers_model diff --git a/application/migrations/045_revert_rename_service_categories_table_to_categories.php b/application/migrations/045_revert_rename_service_categories_table_to_categories.php new file mode 100644 index 00000000..220196ca --- /dev/null +++ b/application/migrations/045_revert_rename_service_categories_table_to_categories.php @@ -0,0 +1,36 @@ + + * @copyright Copyright (c) Alex Tselegidis + * @license https://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link https://easyappointments.org + * @since v1.5.0 + * ---------------------------------------------------------------------------- */ + +class Migration_Revert_rename_service_categories_table_to_categories extends EA_Migration { + /** + * Upgrade method. + */ + public function up() + { + if ($this->db->table_exists('categories')) + { + $this->dbforge->rename_table('categories', 'service_categories'); + } + } + + /** + * Downgrade method. + */ + public function down() + { + if ($this->db->table_exists('service_categories')) + { + $this->dbforge->rename_table('service_categories', 'categories'); + } + } +} diff --git a/application/migrations/046_revert_rename_id_service_categories_column_of_services_table.php b/application/migrations/046_revert_rename_id_service_categories_column_of_services_table.php new file mode 100644 index 00000000..57a871d8 --- /dev/null +++ b/application/migrations/046_revert_rename_id_service_categories_column_of_services_table.php @@ -0,0 +1,70 @@ + + * @copyright Copyright (c) Alex Tselegidis + * @license https://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link https://easyappointments.org + * @since v1.5.0 + * ---------------------------------------------------------------------------- */ + +class Migration_Revert_rename_id_service_categories_column_of_services_table extends EA_Migration { + /** + * Upgrade method. + */ + public function up() + { + if ($this->db->field_exists('id_categories', 'services')) + { + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services') . '` DROP FOREIGN KEY `services_categories`'); + + $fields = [ + 'id_categories' => [ + 'name' => 'id_service_categories', + 'type' => 'INT', + 'constraint' => '11' + ] + ]; + + $this->dbforge->modify_column('services', $fields); + + $this->db->query(' + ALTER TABLE `' . $this->db->dbprefix('services') . '` + ADD CONSTRAINT `services_service_categories` FOREIGN KEY (`id_service_categories`) REFERENCES `' . $this->db->dbprefix('service_categories') . '` (`id`) + ON DELETE SET NULL + ON UPDATE CASCADE + '); + } + } + + /** + * Downgrade method. + */ + public function down() + { + if ($this->db->field_exists('id_service_categories', 'services')) + { + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services') . '` DROP FOREIGN KEY `services_service_categories`'); + + $fields = [ + 'id_service_categories' => [ + 'name' => 'id_categories', + 'type' => 'INT', + 'constraint' => '11' + ] + ]; + + $this->dbforge->modify_column('services', $fields); + + $this->db->query(' + ALTER TABLE `' . $this->db->dbprefix('services') . '` + ADD CONSTRAINT `services_categories` FOREIGN KEY (`id_categories`) REFERENCES `' . $this->db->dbprefix('categories') . '` (`id`) + ON DELETE SET NULL + ON UPDATE CASCADE + '); + } + } +} diff --git a/application/models/Categories_model.php b/application/models/Categories_model.php deleted file mode 100644 index 4a096c7e..00000000 --- a/application/models/Categories_model.php +++ /dev/null @@ -1,343 +0,0 @@ - - * @copyright Copyright (c) Alex Tselegidis - * @license https://opensource.org/licenses/GPL-3.0 - GPLv3 - * @link https://easyappointments.org - * @since v1.0.0 - * ---------------------------------------------------------------------------- */ - -/** - * Categories model. - * - * Handles all the database operations of the category resource. - * - * @package Models - */ -class Categories_model extends EA_Model { - /** - * @var array - */ - protected array $casts = [ - 'id' => 'integer', - ]; - - /** - * @var array - */ - protected array $api_resource = [ - 'id' => 'id', - 'name' => 'name', - 'description' => 'description', - ]; - - /** - * Save (insert or update) a category. - * - * @param array $category Associative array with the category data. - * - * @return int Returns the category ID. - * - * @throws InvalidArgumentException - */ - public function save(array $category): int - { - $this->validate($category); - - if (empty($category['id'])) - { - return $this->insert($category); - } - else - { - return $this->update($category); - } - } - - /** - * Validate the category data. - * - * @param array $category Associative array with the category data. - * - * @throws InvalidArgumentException - */ - public function validate(array $category) - { - // If a category ID is provided then check whether the record really exists in the database. - if ( ! empty($category['id'])) - { - $count = $this->db->get_where('categories', ['id' => $category['id']])->num_rows(); - - if ( ! $count) - { - throw new InvalidArgumentException('The provided category ID does not exist in the database: ' . $category['id']); - } - } - - // Make sure all required fields are provided. - if ( - empty($category['name']) - ) - { - throw new InvalidArgumentException('Not all required fields are provided: ' . print_r($category, TRUE)); - } - } - - /** - * Insert a new category into the database. - * - * @param array $category Associative array with the category data. - * - * @return int Returns the category ID. - * - * @throws RuntimeException - */ - protected function insert(array $category): int - { - $category['create_datetime'] = date('Y-m-d H:i:s'); - $category['update_datetime'] = date('Y-m-d H:i:s'); - - if ( ! $this->db->insert('categories', $category)) - { - throw new RuntimeException('Could not insert category.'); - } - - return $this->db->insert_id(); - } - - /** - * Update an existing category. - * - * @param array $category Associative array with the category data. - * - * @return int Returns the category ID. - * - * @throws RuntimeException - */ - protected function update(array $category): int - { - $category['update_datetime'] = date('Y-m-d H:i:s'); - - if ( ! $this->db->update('categories', $category, ['id' => $category['id']])) - { - throw new RuntimeException('Could not update service categories.'); - } - - return $category['id']; - } - - /** - * Remove an existing category from the database. - * - * @param int $category_id Category ID. - * - * @throws RuntimeException - */ - public function delete(int $category_id): void - { - $this->db->delete('categories', ['id' => $category_id]); - } - - /** - * Get a specific category from the database. - * - * @param int $category_id The ID of the record to be returned. - * - * @return array Returns an array with the category data. - * - * @throws InvalidArgumentException - */ - public function find(int $category_id): array - { - $category = $this->db->get_where('categories', ['id' => $category_id])->row_array(); - - if ( ! $category) - { - throw new InvalidArgumentException('The provided category ID was not found in the database: ' . $category_id); - } - - $this->cast($category); - - return $category; - } - - /** - * Get a specific field value from the database. - * - * @param int $category_id Category ID. - * @param string $field Name of the value to be returned. - * - * @return mixed Returns the selected category value from the database. - * - * @throws InvalidArgumentException - */ - public function value(int $category_id, string $field): mixed - { - if (empty($field)) - { - throw new InvalidArgumentException('The field argument is cannot be empty.'); - } - - if (empty($category_id)) - { - throw new InvalidArgumentException('The category ID argument cannot be empty.'); - } - - // Check whether the service exists. - $query = $this->db->get_where('categories', ['id' => $category_id]); - - if ( ! $query->num_rows()) - { - throw new InvalidArgumentException('The provided category ID was not found in the database: ' . $category_id); - } - - // Check if the required field is part of the category data. - $category = $query->row_array(); - - $this->cast($category); - - if ( ! array_key_exists($field, $category)) - { - throw new InvalidArgumentException('The requested field was not found in the category data: ' . $field); - } - - return $category[$field]; - } - - /** - * Get all services that match the provided criteria. - * - * @param array|string|null $where Where conditions - * @param int|null $limit Record limit. - * @param int|null $offset Record offset. - * @param string|null $order_by Order by. - * - * @return array Returns an array of service categories. - */ - public function get(array|string $where = NULL, int $limit = NULL, int $offset = NULL, string $order_by = NULL): array - { - if ($where !== NULL) - { - $this->db->where($where); - } - - if ($order_by !== NULL) - { - $this->db->order_by($order_by); - } - - $categories = $this->db->get('categories', $limit, $offset)->result_array(); - - foreach ($categories as &$category) - { - $this->cast($category); - } - - return $categories; - } - - /** - * Get the query builder interface, configured for use with the service categories table. - * - * @return CI_DB_query_builder - */ - public function query(): CI_DB_query_builder - { - return $this->db->from('categories'); - } - - /** - * Search service categories by the provided keyword. - * - * @param string $keyword Search keyword. - * @param int|null $limit Record limit. - * @param int|null $offset Record offset. - * @param string|null $order_by Order by. - * - * @return array Returns an array of service categories. - */ - public function search(string $keyword, int $limit = NULL, int $offset = NULL, string $order_by = NULL): array - { - $categories = $this - ->db - ->select() - ->from('categories') - ->group_start() - ->like('name', $keyword) - ->or_like('description', $keyword) - ->group_end() - ->limit($limit) - ->offset($offset) - ->order_by($order_by) - ->get() - ->result_array(); - - foreach ($categories as &$category) - { - $this->cast($category); - } - - return $categories; - } - - /** - * Load related resources to a category. - * - * @param array $category Associative array with the category data. - * @param array $resources Resource names to be attached. - * - * @throws InvalidArgumentException - */ - public function load(array &$category, array $resources) - { - // Service categories do not currently have any related resources. - } - - /** - * Convert the database category record to the equivalent API resource. - * - * @param array $category Category data. - */ - public function api_encode(array &$category) - { - $encoded_resource = [ - 'id' => array_key_exists('id', $category) ? (int)$category['id'] : NULL, - 'name' => $category['name'], - 'description' => array_key_exists('description', $category) ? $category['description'] : NULL - ]; - - $category = $encoded_resource; - } - - /** - * Convert the API resource to the equivalent database category record. - * - * @param array $category API resource. - * @param array|null $base Base category data to be overwritten with the provided values (useful for updates). - */ - public function api_decode(array &$category, array $base = NULL) - { - $decoded_resource = $base ?: []; - - if (array_key_exists('id', $category)) - { - $decoded_resource['id'] = $category['id']; - } - - if (array_key_exists('name', $category)) - { - $decoded_resource['name'] = $category['name']; - } - - if (array_key_exists('description', $category)) - { - $decoded_resource['description'] = $category['description']; - } - - $category = $decoded_resource; - } -} diff --git a/application/models/Service_categories_model.php b/application/models/Service_categories_model.php new file mode 100644 index 00000000..08209f52 --- /dev/null +++ b/application/models/Service_categories_model.php @@ -0,0 +1,369 @@ + + * @copyright Copyright (c) Alex Tselegidis + * @license https://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link https://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +/** + * Service-Categories model. + * + * Handles all the database operations of the service-category resource. + * + * @package Models + */ +class Service_categories_model extends EA_Model { + /** + * @var array + */ + protected array $casts = [ + 'id' => 'integer', + ]; + + /** + * @var array + */ + protected array $api_resource = [ + 'id' => 'id', + 'name' => 'name', + 'description' => 'description', + ]; + + /** + * Save (insert or update) a service-category. + * + * @param array $service_category Associative array with the service-category data. + * + * @return int Returns the service-category ID. + * + * @throws InvalidArgumentException + */ + public function save(array $service_category): int + { + $this->validate($service_category); + + if (empty($service_category['id'])) + { + return $this->insert($service_category); + } + else + { + return $this->update($service_category); + } + } + + /** + * Validate the service-category data. + * + * @param array $service_category Associative array with the service-category data. + * + * @throws InvalidArgumentException + */ + public function validate(array $service_category) + { + // If a service-category ID is provided then check whether the record really exists in the database. + if ( ! empty($service_category['id'])) + { + $count = $this->db->get_where('service_categories', ['id' => $service_category['id']])->num_rows(); + + if ( ! $count) + { + throw new InvalidArgumentException('The provided service-category ID does not exist in the database: ' . $service_category['id']); + } + } + + // Make sure all required fields are provided. + if ( + empty($service_category['name']) + ) + { + throw new InvalidArgumentException('Not all required fields are provided: ' . print_r($service_category, TRUE)); + } + } + + /** + * Insert a new service-category into the database. + * + * @param array $service_category Associative array with the service-category data. + * + * @return int Returns the service-category ID. + * + * @throws RuntimeException + */ + protected function insert(array $service_category): int + { + $service_category['create_datetime'] = date('Y-m-d H:i:s'); + $service_category['update_datetime'] = date('Y-m-d H:i:s'); + + if ( ! $this->db->insert('service_categories', $service_category)) + { + throw new RuntimeException('Could not insert service-category.'); + } + + return $this->db->insert_id(); + } + + /** + * Update an existing service-category. + * + * @param array $service_category Associative array with the service-category data. + * + * @return int Returns the service-category ID. + * + * @throws RuntimeException + */ + protected function update(array $service_category): int + { + $service_category['update_datetime'] = date('Y-m-d H:i:s'); + + if ( ! $this->db->update('service_categories', $service_category, ['id' => $service_category['id']])) + { + throw new RuntimeException('Could not update service categories.'); + } + + return $service_category['id']; + } + + /** + * Remove an existing service-category from the database. + * + * @param int $category_id Category ID. + * @param bool $force_delete Override soft delete. + * + * @throws RuntimeException + */ + public function delete(int $category_id, bool $force_delete = FALSE) + { + if ($force_delete) + { + $this->db->delete('service_categories', ['id' => $category_id]); + } + else + { + $this->db->update('service_categories', ['delete_datetime' => date('Y-m-d H:i:s')], ['id' => $category_id]); + } + } + + /** + * Get a specific service-category from the database. + * + * @param int $category_id The ID of the record to be returned. + * @param bool $with_trashed + * + * @return array Returns an array with the service-category data. + * + * @throws InvalidArgumentException + */ + public function find(int $category_id, bool $with_trashed = FALSE): array + { + if ( ! $with_trashed) + { + $this->db->where('delete_datetime IS NULL'); + } + + $service_category = $this->db->get_where('service_categories', ['id' => $category_id])->row_array(); + + if ( ! $service_category) + { + throw new InvalidArgumentException('The provided service-category ID was not found in the database: ' . $category_id); + } + + $this->cast($service_category); + + return $service_category; + } + + /** + * Get a specific field value from the database. + * + * @param int $category_id Category ID. + * @param string $field Name of the value to be returned. + * + * @return mixed Returns the selected service-category value from the database. + * + * @throws InvalidArgumentException + */ + public function value(int $category_id, string $field): mixed + { + if (empty($field)) + { + throw new InvalidArgumentException('The field argument is cannot be empty.'); + } + + if (empty($category_id)) + { + throw new InvalidArgumentException('The service-category ID argument cannot be empty.'); + } + + // Check whether the service exists. + $query = $this->db->get_where('service_categories', ['id' => $category_id]); + + if ( ! $query->num_rows()) + { + throw new InvalidArgumentException('The provided service-category ID was not found in the database: ' . $category_id); + } + + // Check if the required field is part of the service-category data. + $service_category = $query->row_array(); + + $this->cast($service_category); + + if ( ! array_key_exists($field, $service_category)) + { + throw new InvalidArgumentException('The requested field was not found in the service-category data: ' . $field); + } + + return $service_category[$field]; + } + + /** + * Get all services that match the provided criteria. + * + * @param array|string|null $where Where conditions + * @param int|null $limit Record limit. + * @param int|null $offset Record offset. + * @param string|null $order_by Order by. + * @param bool $with_trashed + * + * @return array Returns an array of service categories. + */ + public function get(array|string $where = NULL, int $limit = NULL, int $offset = NULL, string $order_by = NULL, bool $with_trashed = FALSE): array + { + if ($where !== NULL) + { + $this->db->where($where); + } + + if ($order_by !== NULL) + { + $this->db->order_by($order_by); + } + + if ( ! $with_trashed) + { + $this->db->where('delete_datetime IS NULL'); + } + + $service_categories = $this->db->get('service_categories', $limit, $offset)->result_array(); + + foreach ($service_categories as &$service_category) + { + $this->cast($service_category); + } + + return $service_categories; + } + + /** + * Get the query builder interface, configured for use with the service categories table. + * + * @return CI_DB_query_builder + */ + public function query(): CI_DB_query_builder + { + return $this->db->from('service_categories'); + } + + /** + * Search service categories by the provided keyword. + * + * @param string $keyword Search keyword. + * @param int|null $limit Record limit. + * @param int|null $offset Record offset. + * @param string|null $order_by Order by. + * @param bool $with_trashed + * + * @return array Returns an array of service categories. + */ + public function search(string $keyword, int $limit = NULL, int $offset = NULL, string $order_by = NULL, bool $with_trashed = FALSE): array + { + if ( ! $with_trashed) + { + $this->db->where('delete_datetime IS NULL'); + } + + $service_categories = $this + ->db + ->select() + ->from('service_categories') + ->group_start() + ->like('name', $keyword) + ->or_like('description', $keyword) + ->group_end() + ->limit($limit) + ->offset($offset) + ->order_by($order_by) + ->get() + ->result_array(); + + foreach ($service_categories as &$service_category) + { + $this->cast($service_category); + } + + return $service_categories; + } + + /** + * Load related resources to a service-category. + * + * @param array $service_category Associative array with the service-category data. + * @param array $resources Resource names to be attached. + * + * @throws InvalidArgumentException + */ + public function load(array &$service_category, array $resources) + { + // Service categories do not currently have any related resources. + } + + /** + * Convert the database service-category record to the equivalent API resource. + * + * @param array $service_category Category data. + */ + public function api_encode(array &$service_category) + { + $encoded_resource = [ + 'id' => array_key_exists('id', $service_category) ? (int)$service_category['id'] : NULL, + 'name' => $service_category['name'], + 'description' => array_key_exists('description', $service_category) ? $service_category['description'] : NULL + ]; + + $service_category = $encoded_resource; + } + + /** + * Convert the API resource to the equivalent database service-category record. + * + * @param array $service_category API resource. + * @param array|null $base Base service-category data to be overwritten with the provided values (useful for updates). + */ + public function api_decode(array &$service_category, array $base = NULL) + { + $decoded_resource = $base ?: []; + + if (array_key_exists('id', $service_category)) + { + $decoded_resource['id'] = $service_category['id']; + } + + if (array_key_exists('name', $service_category)) + { + $decoded_resource['name'] = $service_category['name']; + } + + if (array_key_exists('description', $service_category)) + { + $decoded_resource['description'] = $service_category['description']; + } + + $service_category = $decoded_resource; + } +} diff --git a/application/models/Services_model.php b/application/models/Services_model.php index e5f95e32..8d9ec8a9 100644 --- a/application/models/Services_model.php +++ b/application/models/Services_model.php @@ -27,7 +27,7 @@ class Services_model extends EA_Model { 'price' => 'float', 'attendants_number' => 'integer', 'is_private' => 'boolean', - 'id_categories' => 'integer', + 'id_service_categories' => 'integer', ]; /** @@ -45,7 +45,7 @@ class Services_model extends EA_Model { 'availabilitiesType' => 'availabilities_type', 'attendantsNumber' => 'attendants_number', 'isPrivate' => 'is_private', - 'categoryId' => 'id_categories', + 'serviceCategoryId' => 'id_service_categories', ]; /** @@ -99,18 +99,18 @@ class Services_model extends EA_Model { throw new InvalidArgumentException('Not all required fields are provided: ' . print_r($service, TRUE)); } - // If a category was provided then make sure it really exists in the database. - if ( ! empty($service['id_categories'])) + // If a category was provided then make sure it really exists in the database. + if ( ! empty($service['id_service_categories'])) { - $count = $this->db->get_where('categories', ['id' => $service['id_categories']])->num_rows(); + $count = $this->db->get_where('categories', ['id' => $service['id_service_categories']])->num_rows(); if ( ! $count) { - throw new InvalidArgumentException('The provided category ID was not found in the database: ' . $service['id_categories']); + throw new InvalidArgumentException('The provided category ID was not found in the database: ' . $service['id_service_categories']); } } - // Make sure the duration value is valid. + // Make sure the duration value is valid. if ( ! empty($service['duration'])) { if ((int)$service['duration'] < EVENT_MINIMUM_DURATION) @@ -136,7 +136,7 @@ class Services_model extends EA_Model { throw new InvalidArgumentException('The provided availabilities type is invalid: ' . $service['availabilities_type']); } - // Validate the attendants number value. + // Validate the attendants number value. if (empty($service['attendants_number']) || (int)$service['attendants_number'] < 1) { throw new InvalidArgumentException('The provided attendants number is invalid: ' . $service['attendants_number']); @@ -190,25 +190,39 @@ class Services_model extends EA_Model { * Remove an existing service from the database. * * @param int $service_id Service ID. + * @param bool $force_delete Override soft delete. * * @throws RuntimeException */ - public function delete(int $service_id): void + public function delete(int $service_id, bool $force_delete = FALSE) { - $this->db->delete('services', ['id' => $service_id]); + if ($force_delete) + { + $this->db->delete('services', ['id' => $service_id]); + } + else + { + $this->db->update('services', ['delete_datetime' => date('Y-m-d H:i:s')], ['id' => $service_id]); + } } /** * Get a specific service from the database. * * @param int $service_id The ID of the record to be returned. + * @param bool $with_trashed * * @return array Returns an array with the service data. * * @throws InvalidArgumentException */ - public function find(int $service_id): array + public function find(int $service_id, bool $with_trashed = FALSE): array { + if ( ! $with_trashed) + { + $this->db->where('delete_datetime IS NULL'); + } + $service = $this->db->get_where('services', ['id' => $service_id])->row_array(); if ( ! $service) @@ -271,10 +285,11 @@ class Services_model extends EA_Model { * @param int|null $limit Record limit. * @param int|null $offset Record offset. * @param string|null $order_by Order by. + * @param bool $with_trashed * * @return array Returns an array of services. */ - public function get(array|string $where = NULL, int $limit = NULL, int $offset = NULL, string $order_by = NULL): array + public function get(array|string $where = NULL, int $limit = NULL, int $offset = NULL, string $order_by = NULL, bool $with_trashed = FALSE): array { if ($where !== NULL) { @@ -286,6 +301,11 @@ class Services_model extends EA_Model { $this->db->order_by($order_by); } + if ( ! $with_trashed) + { + $this->db->where('delete_datetime IS NULL'); + } + $services = $this->db->get('services', $limit, $offset)->result_array(); foreach ($services as &$service) @@ -313,10 +333,11 @@ class Services_model extends EA_Model { $services = $this ->db ->distinct() - ->select('services.*, categories.name AS category_name, categories.id AS category_id') + ->select('services.*, service_categories.name AS service_category_name, service_categories.id AS service_category_id') ->from('services') ->join('services_providers', 'services_providers.id_services = services.id', 'inner') - ->join('categories', 'categories.id = services.id_categories', 'left') + ->join('service_categories', 'service_categories.id = services.id_service_categories', 'left') + ->where('services.delete_datetime IS NULL') ->order_by('name ASC') ->get() ->result_array(); @@ -346,11 +367,17 @@ class Services_model extends EA_Model { * @param int|null $limit Record limit. * @param int|null $offset Record offset. * @param string|null $order_by Order by. + * @param bool $with_trashed * * @return array Returns an array of services. */ - public function search(string $keyword, int $limit = NULL, int $offset = NULL, string $order_by = NULL): array + public function search(string $keyword, int $limit = NULL, int $offset = NULL, string $order_by = NULL, bool $with_trashed = FALSE): array { + if ( ! $with_trashed) + { + $this->db->where('delete_datetime IS NULL'); + } + $services = $this ->db ->select() @@ -395,7 +422,7 @@ class Services_model extends EA_Model { 'category' => $this ->db ->get_where('categories', [ - 'id' => $service['id_categories'] ?? $service['categoryId'] ?? NULL + 'id' => $service['id_service_categories'] ?? $service['serviceCategoryId'] ?? NULL ]) ->row_array(), default => throw new InvalidArgumentException('The requested appointment relation is not supported: ' . $resource), @@ -420,7 +447,7 @@ class Services_model extends EA_Model { 'location' => $service['location'], 'availabilitiesType' => $service['availabilities_type'], 'attendantsNumber' => (int)$service['attendants_number'], - 'categoryId' => $service['id_categories'] !== NULL ? (int)$service['id_categories'] : NULL + 'serviceCategoryId' => $service['id_service_categories'] !== NULL ? (int)$service['id_service_categories'] : NULL ]; $service = $encoded_resource; @@ -481,9 +508,9 @@ class Services_model extends EA_Model { $decoded_resource['attendants_number'] = $service['attendantsNumber']; } - if (array_key_exists('categoryId', $service)) + if (array_key_exists('serviceCategoryId', $service)) { - $decoded_resource['id_categories'] = $service['categoryId']; + $decoded_resource['id_service_categories'] = $service['serviceCategoryId']; } $service = $decoded_resource; diff --git a/application/views/components/backend_header.php b/application/views/components/backend_header.php index a67911b6..951a57c0 100755 --- a/application/views/components/backend_header.php +++ b/application/views/components/backend_header.php @@ -53,7 +53,7 @@ = lang('services') ?> - + = lang('categories') ?> diff --git a/application/views/components/booking_type_step.php b/application/views/components/booking_type_step.php index e87ab41c..4e1ba3bc 100644 --- a/application/views/components/booking_type_step.php +++ b/application/views/components/booking_type_step.php @@ -23,7 +23,7 @@ $has_category = FALSE; foreach ($available_services as $service) { - if ( ! empty($service['category_id'])) + if ( ! empty($service['service_category_id'])) { $has_category = TRUE; break; @@ -36,14 +36,14 @@ foreach ($available_services as $service) { - if ( ! empty($service['category_id'])) + if ( ! empty($service['service_category_id'])) { - if ( ! isset($grouped_services[$service['category_name']])) + if ( ! isset($grouped_services[$service['service_category_name']])) { - $grouped_services[$service['category_name']] = []; + $grouped_services[$service['service_category_name']] = []; } - $grouped_services[$service['category_name']][] = $service; + $grouped_services[$service['service_category_name']][] = $service; } } @@ -52,7 +52,7 @@ $grouped_services['uncategorized'] = []; foreach ($available_services as $service) { - if ($service['category_id'] == NULL) + if ($service['service_category_id'] == NULL) { $grouped_services['uncategorized'][] = $service; } @@ -61,7 +61,7 @@ foreach ($grouped_services as $key => $group) { $group_label = $key !== 'uncategorized' - ? $group[0]['category_name'] + ? $group[0]['service_category_name'] : 'Uncategorized'; if (count($group) > 0) diff --git a/application/views/pages/categories.php b/application/views/pages/service_categories.php old mode 100755 new mode 100644 similarity index 77% rename from application/views/pages/categories.php rename to application/views/pages/service_categories.php index 39d6d62d..07c00978 --- a/application/views/pages/categories.php +++ b/application/views/pages/service_categories.php @@ -4,8 +4,8 @@