<?php
namespace SHServ\Controllers;
use \SHServ\Models\Areas;
use \SHServ\Entities\Area;
/**
* Контроллер реализующий REST API для работы с абстрактным описанием физических областей.
* Подчёркиваю, это Areas, а не Spaces. Реализована логика работы именно с физическим областями, а не абстрактным пространством.
*/
class AreasRESTAPIController extends \SHServ\Middleware\Controller {
/**
* Получить список пространств в системе. Всех или у родительского пространства
* @param Int $area_id Area ID
* @return String JSON. Вернёт массив областей в поле `areas` и количество в поле `total`
*/
public function areas_list($area_id = 0) {
$areas_model = new Areas();
if(!$area_id) {
$areas = $areas_model -> get_all();
} else {
$parent_area = new Area(intval($area_id));
if(!$parent_area) {
return $this -> utils() -> response_error("parent_area_not_found");
}
$areas = $parent_area -> get_inner_areas();
}
$response = [];
foreach($areas as $i => $area) {
$response[] = $area -> to_array();
}
return $this -> utils() -> response_success([
"areas" => $response,
"total" => count($response)
]);
}
/**
* Добавить новую физическую область
* @param String $type Произвольный тип области. Это может быть например комната, этаж, здание, или двор. Ограничений нет, но тип должен описывать именно физическую область.
* @param String $alias Псевдоним для обращения к области из кода. Обязательно должен быть уникальным.
* @param String $display_name Отображаемое название/имя области
* @return String JSON. Возвращает поля созданной `area` и `alias` или ошибку.
*/
public function new_area($type, $alias, $display_name) {
$areas_model = new Areas();
if(!$areas_model -> alias_is_uniq($alias)) {
return $this -> utils() -> response_error("alias_already_exists", ["alias"]);
}
if(!strlen($type)) {
return $this -> utils() -> response_error("empty_field", ["type"]);
}
if(!strlen($display_name)) {
return $this -> utils() -> response_error("empty_field", ["display_name"]);
}
$area = $areas_model -> create_new_area($type, $alias, $display_name);
if(!$area) {
return $this -> utils() -> response_error("area_not_exists");
}
return $this -> utils() -> response_success([
"alias" => $area -> alias,
"area" => $area -> to_array()
]);
}
/**
* Удалить область. При этом все помещённые в неё устройства и child области будут отвязаны
* @param Int $area_id Area ID
* @return String JSON. Вернёт ошибку или положительный результат
*/
public function remove_area($area_id) {
if($area_id != intval($area_id) or intval($area_id) <= 1) {
return $this -> utils() -> response_error("invalid_id", ["area_id"]);
}
$area = new Area(intval($area_id));
if(!$area) {
return $this -> utils() -> response_error("area_not_exists");
}
if(!$area -> remove()) {
return $this -> utils() -> response_error("undefined_error");
}
return $this -> utils() -> response_success();
}
/**
* Поместить/вложить одну область в другую. Например комнату можна поместить в этаж, этаж в здание, а здание в глобальную область типа "дом/комплекс/т.п.".
* @param Int $target_area_id Area ID целевой области, которую хотим поместить
* @param Int $place_in_area_id Area ID родительской области в которую хотим поместить целевую область
* @return String JSON. Вернёт ошибку или положительный результат
*/
public function place_in_area($target_area_id, $place_in_area_id) {
if($target_area_id != intval($target_area_id) or intval($target_area_id) <= 1) {
return $this -> utils() -> response_error("invalid_id", ["target_area_id"]);
}
if($place_in_area_id != intval($place_in_area_id) or intval($place_in_area_id) <= 1) {
return $this -> utils() -> response_error("invalid_id", ["place_in_area_id"]);
}
$target_area = new Area(intval($target_area_id));
$place_area = new Area(intval($place_in_area_id));
if(!$target_area or !$place_area) {
return $this -> utils() -> response_error("area_not_exists");
}
if(!$target_area -> place_in_area($place_area)) {
return $this -> utils() -> response_error("undefined_error");
}
return $this -> utils() -> response_success();
}
/**
* Переименовать область
* @param Int $area_id Area ID области, которую переименовываем
* @param String $display_name Новое название/имя области
* @return String JSON. Возвращает поля `area` с данными об изменённой области и `alias`.
*/
public function update_display_name($area_id, $display_name) {
if($area_id != intval($area_id) or intval($area_id) <= 1) {
return $this -> utils() -> response_error("invalid_id");
}
if(!strlen($display_name)) {
return $this -> utils() -> response_error("empty_field", ["display_name"]);
}
$area = new Area(intval($area_id));
if(!$area) {
return $this -> utils() -> response_error("area_not_exists");
}
$area -> display_name = $display_name;
return $area -> update()
? $this -> utils() -> response_success([
"alias" => $area -> alias,
"area" => $area -> to_array()
])
: $this -> utils() -> response_error("undefined_error");
}
/**
* Измениеть псевдоним для обращения к области из кода.
* ОСТОРОЖНО! если область уже учавствует в написанных скриптах, это сломает работу скриптов.
* @param Int $area_id Area ID
* @param String $new_alias Новый уникальный псевдоним области
* @return String JSON. Возвращает поля `area` с данными об изменённой области и `alias`.
*/
public function update_alias($area_id, $new_alias) {
if($area_id != intval($area_id) or intval($area_id) <= 1) {
return $this -> utils() -> response_error("invalid_id", ["area_id"]);
}
if(!strlen($new_alias)) {
return $this -> utils() -> response_error("empty_field", ["new_alias"]);
}
$areas_model = new Areas();
if(!$areas_model -> alias_is_uniq($new_alias)) {
return $this -> utils() -> response_error("alias_already_exists", ["alias"]);
}
$area = new Area(intval($area_id));
if(!$area) {
return $this -> utils() -> response_error("area_not_exists");
}
$area -> alias = $new_alias;
return $area -> update()
? $this -> utils() -> response_success([
"alias" => $area -> alias,
"area" => $area -> to_array()
])
: $this -> utils() -> response_error("undefined_error");
}
/**
* Перезагрузить все устройства, что помещены в указанную область.
* @param Int $area_id Area ID области в которой нужно перезагрузить все устройства.
* @return String JSON. При положительном ответе вернётся `total` - количество устройств, что были перезагружены,
* и `results` - ассоциативный массив с ключами вида `area_alias:device_alias` и телом ответа от устройства в качестве значения.
*/
public function reboot_devices($area_id = 0) {
$area = new Area(intval($area_id));
if(!$area) {
return $this -> utils() -> response_error("area_not_exists");
}
$devices = $area -> get_inner_devices(true);
$results = [];
foreach($devices as $device) {
$results["{$area -> alias}:{$device -> alias}"] = $device -> device_api() -> reboot();
}
return $this -> utils() -> response_success([
"results" => $results,
"total" => count($results)
]);
}
/**
* Получить список устройств, что помещены в указанную область.
* @param Int $area_id Area ID
* @return String JSON. Возвращает массив устройств в поле `devices` и количество устрйоств в поле `total`
*/
public function devices_list($area_id) {
if($area_id != intval($area_id) or intval($area_id) <= 1) {
return $this -> utils() -> response_error("invalid_id", ["area_id"]);
}
$area = new Area(intval($area_id));
if(!$area) {
return $this -> utils() -> response_error("area_not_exists");
}
$devices = $area -> get_inner_devices(true);
return $this -> utils() -> response_success([
"devices" => array_map(function($device) {
return $device -> to_array();
}, $devices),
"total" => count($devices)
]);
}
/**
* Отвязать указанную область от области в которую она почещена. Устройства, что помещены в эту область в ней останутся.
* @param Int $area_id Area ID
* @return String JSON. Вернётся ошибка или положительный ответ.
*/
public function unassign_from_area($area_id) {
if($area_id != intval($area_id) or intval($area_id) <= 1) {
return $this -> utils() -> response_error("invalid_id", ["area_id"]);
}
$area = new Area(intval($area_id));
if(!$area) {
return $this -> utils() -> response_error("area_not_exists");
}
return $area -> place_in_area_by_id(0)
? $this -> utils() -> response_success()
: $this -> utils() -> response_error("undefined_error");
}
/**
* Получить список существующих в БД пользовательских типов областей. Это может быть полезно для выведения подсказок пользователю при добавлении новой области,
* чтоб помогать не плодить множества одинаковых по смыслу, но разных по названию, типов.
* @return String JSON Вернёт поле `types` с массивом типов
*/
public function exists_types() {
return $this -> utils() -> response_success([
"types" => (new Areas()) -> get_exists_types()
]);
}
}