Newer
Older
smart-home-server / server / SHServ / Entities / Area.php
<?php

namespace SHServ\Entities;

use \SHServ\Entities\Device;

class Area extends \SHServ\Middleware\Entity {

	use \SHServ\Helpers\MetaImplementation;

	public static $table_name = "areas";
	protected static $fields = [
		"id", "alias", "display_name", "type", 
		"parent_id", "schema", "create_at", "update_at"
	];

	public function __construct(int $entity_id, array $data = []) {
		return parent::__construct(
			self::$table_name, 
			$entity_id, 
			$data
		);
	}

	public function get_parent_id(): Int {
		return $this -> parent_id; 
	}

	public function parent_area(): Area | null {
		if(!$this -> get_parent_id()) {
			return null;
		}

		return new Area($this -> get_parent_id());
	}

	public function get_inner_areas(Bool $recursive = false): Array {
		$area_ids = [ $this -> id() ];
		
		if($recursive) {
			$area_ids = array_merge($area_ids, $this -> get_recursive_inner_areas_ids($this -> id()));
		}

		$raw_areas = app() -> thin_builder -> select(
			self::$table_name,
			self::get_fields(),
			[[ "parent_id", "IN", $area_ids ]]
		);

		if(!$raw_areas) {
			return [];
		}

		$areas = [];

		foreach($raw_areas as $i => $raw_area) {
			$areas[] = new Area($raw_area["id"], $raw_area);
		}

		return $areas;
	}

	public function place_in_area(Area $parent_area): Array | bool {
		return $this -> place_in_area_by_id($parent_area -> id());
	}

	public function place_in_area_by_id(int $area_id): Array | bool {
		$this -> parent_id = $area_id;
		return $this -> update();
	}

	public function get_areas_by_type(String $type, Bool $recursive = false): Array {
		$area_ids = [ $this -> id() ];
		
		if($recursive) {
			$area_ids = array_merge($area_ids, $this -> get_recursive_inner_areas_ids($this -> id()));
		}

		$raw_areas = app() -> thin_builder -> select(
			self::$table_name,
			self::get_fields(),
			[
				[ "parent_id", "IN", $area_ids ], 
				"AND", 
				[ "type", "=", $type ]
			]
		);

		if(!$raw_areas) {
			return [];
		}

		$areas = [];

		foreach($raw_areas as $i => $raw_area) {
			$areas[] = new Area($raw_area["id"], $raw_area);
		}

		return $areas;
	}

	public function get_area_by_alias(String $alias, Bool $recursive = false): Area | null {
		$area_ids = [ $this -> id() ];
		
		if($recursive) {
			$area_ids = array_merge($area_ids, $this -> get_recursive_inner_areas_ids($this -> id()));
		}

		$raw_areas = app() -> thin_builder -> select(
			self::$table_name,
			self::get_fields(),
			[
				[ "parent_id", "IN", $area_ids], 
				"AND", 
				[ "alias", "=", $alias ]
			],
			[], "DESC",
			[ 1 ]
		);

		if(!$raw_areas) {
			return null;
		}

		return new Area($raw_areas[0]["id"], $raw_areas[0]);
	}

	protected function get_recursive_inner_areas_ids(Int $parent_id, Int $lvl = 0) {
		if($lvl >= 10) {
			return [];
		}

		$lvl++;

		$areas = app() -> thin_builder -> select(
			Area::$table_name,
			["id", "parent_id"],
			[["parent_id", "=", $parent_id]]
		);

		$result = [];

		if(!$areas) {
			return $result;
		}

		foreach($areas as $area) {
			$result[] = $area["id"];
			$result_next_lvl = $this -> get_recursive_inner_areas_ids($area["id"], $lvl);

			if($result_next_lvl) {
				$result = array_merge($result, $result_next_lvl);
			}
		}

		return $result;
	}

	public function get_inner_devices(Bool $recursive = false): Array {
		$area_ids = [ $this -> id() ];
		
		if($recursive) {
			$area_ids = array_merge($area_ids, $this -> get_recursive_inner_areas_ids($this -> id()));
		}
		
		$raw_devices = app() -> thin_builder -> select(
			Device::$table_name,
			Device::get_fields(),
			[["area_id", "IN", $area_ids]]
		);

		if(!$raw_devices) {
			return [];
		}

		$devices = [];
		foreach($raw_devices as $raw_device) {
			$devices[] = new Device($raw_device["id"], $raw_device);
		}

		return $devices;
	}

	public function get_device_by_alias(String $alias, Bool $recursive = false): Device | null {
		$area_ids = [ $this -> id() ];
		
		if($recursive) {
			$area_ids = array_merge($area_ids, $this -> get_recursive_inner_areas_ids($this -> id()));
		}

		$raw_devices = app() -> thin_builder -> select(
			Device::$table_name,
			Device::get_fields(),
			[
				[ "area_id", "IN", $area_ids ],
				"AND", 
				[ "alias", "=", $alias ]
			],
			[], "DESC", 
			[ 1 ]
		);

		if(!$raw_devices) {
			return null;
		}

		$raw_device = $raw_devices[0];
		return new Device($raw_device["id"], $raw_device);
	}

	public function get_devices_by_type(String $type, Bool $recursive = false): Array {
		$area_ids = [ $this -> id() ];
		
		if($recursive) {
			$area_ids = array_merge($area_ids, $this -> get_recursive_inner_areas_ids($this -> id()));
		}

		$raw_devices = app() -> thin_builder -> select(
			Device::$table_name,
			Device::get_fields(),
			[
				[ "area_id", "IN", $area_ids ],
				"AND",
				[ "device_type", "=", $type ] 
			]
		);

		if(!$raw_devices) {
			return [];
		}

		$devices = [];
		foreach($raw_devices as $raw_device) {
			$devices[] = new Device($raw_device["id"], $raw_device);
		}

		return $devices;
	}

	public function remove(): Bool {
		$result = app() -> thin_builder -> update(
			Device::$table_name,
			["area_id" => 0],
			[[ "area_id", "=", $this -> id() ]]
		);

		if(!$result) {
			return false;
		}

		$result = app() -> thin_builder -> update(
			self::$table_name,
			["parent_id" => 0],
			[[ "parent_id", "=", $this -> id() ]]
		);

		if(!$result) {
			return false;
		}

		return true;
	}
}