فهرست منبع

School Bells app added (#135)

* Add Bulk Import Extensions app

* Fix Win/Mac browser issue

On Mac, when uploading CSV, filetype is set correctly. On Windows - no

* Fix bugs, added few options

* Restore README.rst

* Call ACL app added

* School bells app added

Co-authored-by: Igor Olhovskiy <[email protected]>
Igor Olhovskiy 5 سال پیش
والد
کامیت
77b02d5c0e

+ 17 - 0
school_bells/README.md

@@ -0,0 +1,17 @@
+# School Bells App
+
+Idea of app to give periodic signals to phones or SIP-Speakers with `cron`-style way
+
+---
+## Install HOW TO
+1. `# cd /usr/src/`
+2. `# git clone https://github.com/fusionpbx/fusionpbx-apps`
+3. `# cd fusionpbx-apps/`
+4. `# cp -R school_bells /var/www/fusionpbx/app/`
+5. Add `* * * * * php //var/www/fusionpbx/app/school_bells/school_bells_cron.php` to your *crontab*
+6. Go to GUI
+7. Upgrades -> *SCHEMA*; *APP DEFAULTS*; *MENU DEFAULTS*; *PERMISSION DEFAULTS*
+8. Log out and back in
+9. *Apps* -> *School Bells*
+---
+By initial design, app allows you or to ring extension for a certain amount of time (via Ring Timeout parameter), or playback recoding after extension answers.

+ 110 - 0
school_bells/app_config.php

@@ -0,0 +1,110 @@
+<?php
+
+	//application details
+		$apps[$x]['name'] = "School Bell";
+		$apps[$x]['uuid'] = "aadeda26-f3b5-4114-96f4-a7591f069fdf";
+		$apps[$x]['category'] = "Switch";
+		$apps[$x]['subcategory'] = "";
+		$apps[$x]['version'] = "";
+		$apps[$x]['license'] = "Mozilla Public License 1.1";
+		$apps[$x]['url'] = "http://www.fusionpbx.com";
+		$apps[$x]['description']['en-us'] = "Provide an ability to set up bells scheduler for schools";
+		$apps[$x]['description']['es-cl'] = "";
+		$apps[$x]['description']['de-de'] = "";
+		$apps[$x]['description']['de-ch'] = "";
+		$apps[$x]['description']['de-at'] = "";
+		$apps[$x]['description']['fr-fr'] = "";
+		$apps[$x]['description']['fr-ca'] = "";
+		$apps[$x]['description']['fr-ch'] = "";
+		$apps[$x]['description']['pt-pt'] = "";
+		$apps[$x]['description']['pt-br'] = "";
+
+	//permission details
+		$y = 0;
+		$apps[$x]['permissions'][$y]['name'] = "school_bell_view";
+		$apps[$x]['permissions'][$y]['menu']['uuid'] = "fd29e39c-c936-f5fc-8e2b-611681b266b5";
+		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
+		$apps[$x]['permissions'][$y]['groups'][] = "admin";
+		$y += 1;
+		$apps[$x]['permissions'][$y]['name'] = "school_bell_add";
+		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
+		$apps[$x]['permissions'][$y]['groups'][] = "admin";
+		$y += 1;
+		$apps[$x]['permissions'][$y]['name'] = "school_bell_edit";
+		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
+		$apps[$x]['permissions'][$y]['groups'][] = "admin";
+		$y += 1;
+		$apps[$x]['permissions'][$y]['name'] = "school_bell_delete";
+		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
+		$apps[$x]['permissions'][$y]['groups'][] = "admin";
+		$y += 1;
+
+	//schema details
+		$y = 0; //table array index
+		$z = 0; //field array index
+		$apps[$x]['db'][$y]['table']['name'] = "v_school_bells";
+		$apps[$x]['db'][$y]['table']['parent'] = "";
+		
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "domain_uuid";
+		$apps[$x]['db'][$y]['fields'][$z]['type']['pgsql'] = "uuid";
+		$apps[$x]['db'][$y]['fields'][$z]['type']['sqlite'] = "text";
+		$apps[$x]['db'][$y]['fields'][$z]['type']['mysql'] = "char(36)";
+		$apps[$x]['db'][$y]['fields'][$z]['key']['type'] = "foreign";
+		$apps[$x]['db'][$y]['fields'][$z]['key']['reference']['table'] = "v_domains";
+		$apps[$x]['db'][$y]['fields'][$z]['key']['reference']['field'] = "domain_uuid";
+		$z += 1;
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "school_bell_uuid";
+		$apps[$x]['db'][$y]['fields'][$z]['type']['pgsql'] = "uuid";
+		$apps[$x]['db'][$y]['fields'][$z]['type']['sqlite'] = "text";
+		$apps[$x]['db'][$y]['fields'][$z]['type']['mysql'] = "char(36)";
+		$apps[$x]['db'][$y]['fields'][$z]['key']['type'] = "primary";
+		$z += 1;
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "school_bell_name";
+		$apps[$x]['db'][$y]['fields'][$z]['type'] = "text";
+		$z += 1;
+		//$apps[$x]['db'][$y]['fields'][$z]['name'] = "school_bell_function_code";
+		//$apps[$x]['db'][$y]['fields'][$z]['type'] = "text";
+		//$z += 1;
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "school_bell_leg_a_type";
+		$apps[$x]['db'][$y]['fields'][$z]['type'] = "text";
+		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "By now only loopback";
+		$z += 1;
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "school_bell_leg_a_data";
+		$apps[$x]['db'][$y]['fields'][$z]['type'] = "text";
+		$z += 1;
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "school_bell_leg_b_type";
+		$apps[$x]['db'][$y]['fields'][$z]['type'] = "text";
+		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "By now - recording";
+		$z += 1;
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "school_bell_leg_b_data";
+		$apps[$x]['db'][$y]['fields'][$z]['type'] = "text";
+		$z += 1;
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "school_bell_ring_timeout";
+		$apps[$x]['db'][$y]['fields'][$z]['type'] = "numeric";
+		$z += 1;
+		// Next will go cron-type of description. But limited to only 1 selection
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "school_bell_min";
+		$apps[$x]['db'][$y]['fields'][$z]['type'] = "numeric";
+		$z += 1;
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "school_bell_hour";
+		$apps[$x]['db'][$y]['fields'][$z]['type'] = "numeric";
+		$z += 1;
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "school_bell_dom";
+		$apps[$x]['db'][$y]['fields'][$z]['type'] = "numeric";
+		$z += 1;
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "school_bell_mon";
+		$apps[$x]['db'][$y]['fields'][$z]['type'] = "numeric";
+		$z += 1;
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "school_bell_dow";
+		$apps[$x]['db'][$y]['fields'][$z]['type'] = "numeric";
+		$z += 1;
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "school_bell_timezone";
+		$apps[$x]['db'][$y]['fields'][$z]['type'] = "text";
+		$z += 1;
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "school_bell_enabled";
+		$apps[$x]['db'][$y]['fields'][$z]['type'] = "text";
+		$z += 1;
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "school_bell_description";
+		$apps[$x]['db'][$y]['fields'][$z]['type'] = "text";
+?>
+

+ 75 - 0
school_bells/app_languages.php

@@ -0,0 +1,75 @@
+<?php
+$text['title-school_bells']['en-us'] = "School Bells";
+$text['title-school_bells-add']['en-us'] = "Add School Bell";
+$text['title-school_bells-edit']['en-us'] = "Edit School Bell";
+
+
+$text['header-school_bells']['en-us'] = "School Bells";
+
+$text['description-school_bells']['en-us'] = "Scheduled periodic signals using PBX system in cron-like style";
+
+$text['label-school_bell_name']['en-us'] = "Name";
+
+$text['label-school_bell_leg_a_data']['en-us'] = "Called Extension";
+
+$text['label-school_bell_leg_b_data']['en-us'] = "Call Answer Action";
+
+$text['label-school_bell_schedule_time']['en-us'] = "Schedule";
+
+$text['label-school_bell_description']['en-us'] = "Description";
+
+$text['label-school_bells-add']['en-us'] = "Add School Bell";
+$text['label-school_bells-add-note']['en-us'] = "Add new signal";
+
+$text['label-school_bells-edit']['en-us'] = "Edit School Bell";
+$text['label-school_bells-edit-note']['en-us'] = "Edit existing signal";
+
+$text['label-school_bell_ring_timeout']['en-us'] = "Ring timeout";
+
+$text['label-school_bell_schedule']['en-us'] = "Schedule";
+
+$text['label-school_bell_min']['en-us'] = "Minute";
+
+$text['label-school_bell_hour']['en-us'] = "Hour";
+
+$text['label-school_bell_dow']['en-us'] = "Day of the week";
+
+$text['label-school_bell_dom']['en-us'] = "Day of the month";
+
+$text['label-school_bell_mon']['en-us'] = "Month";
+
+$text['label-school_bell_enabled']['en-us'] = "Enabled";
+
+$text['label-school_bell_timezone']['en-us'] = "Timezone";
+
+$text['label-school_bell_description']['en-us'] = "Description";
+
+$text['description-school_bell_ring_timeout']['en-us'] = "Timeout for extension to ring";
+
+$text['description-school_bell_name']['en-us'] = "Name of this schedule";
+
+$text['description-school_bell_leg_a_data']['en-us'] = "Which extension should be called on schedule. Normally it is your PAGE extension";
+
+$text['description-school_bell_leg_b_data']['en-us'] = "Select recording to be played on extension answers";
+
+$text['description-school_bell_schedule']['en-us'] = "Adjust schedule of this signal";
+
+$text['description-school_bell_min']['en-us'] = "Specify minutes of hour. * means every minute";
+
+$text['description-school_bell_hour']['en-us'] = "Specify hour of the day. * means every hour";
+
+$text['description-school_bell_dom']['en-us'] = "Specify day of the month. * means every day";
+
+$text['description-school_bell_dow']['en-us'] = "Specify day of the week. * means every day of the week";
+
+$text['description-school_bell_mon']['en-us'] = "Specify month. * means every month";
+
+$text['description-school_bell_enabled']['en-us'] = "Enables or disables schedule";
+
+$text['description-school_bell_timezone']['en-us'] = "Timezone of this schedule";
+
+$text['description-school_bell_description']['en-us'] = "Description of this schedule";
+
+$text['description-school_bells_schedule_templates']['en-us'] = "System uses cron-type of scheduling. For more information, refer to CRON documentation";
+
+?>

+ 19 - 0
school_bells/app_menu.php

@@ -0,0 +1,19 @@
+<?php
+
+$apps[$x]['menu'][0]['title']['en-us'] = "School Bells";
+$apps[$x]['menu'][0]['title']['pt-br'] = "";
+$apps[$x]['menu'][0]['title']['es-cl'] = "";
+$apps[$x]['menu'][0]['title']['fr-fr'] = "";
+$apps[$x]['menu'][0]['title']['fr-ca'] = "";
+$apps[$x]['menu'][0]['title']['pl'] = "";
+$apps[$x]['menu'][0]['title']['sv-se'] = "";
+$apps[$x]['menu'][0]['title']['uk'] = "";
+$apps[$x]['menu'][0]['title']['de-at'] = "";
+$apps[$x]['menu'][0]['uuid'] = "71a52fe5-cb91-4ff6-9cee-896b0c687465";
+$apps[$x]['menu'][0]['parent_uuid'] = "fd29e39c-c936-f5fc-8e2b-611681b266b5";
+$apps[$x]['menu'][0]['category'] = "internal";
+$apps[$x]['menu'][0]['path'] = "/app/school_bells/school_bells.php";
+$apps[$x]['menu'][0]['groups'][] = "superadmin";
+$apps[$x]['menu'][0]['groups'][] = "admin";
+
+?>

+ 119 - 0
school_bells/resources/classes/school_bell_selector.php

@@ -0,0 +1,119 @@
+<?php
+class school_bell_selector {
+
+    private $min, $hou, $day;
+
+    function __construct($time12h = False) {
+
+        # Fill min
+        $this->min = array();
+        $this->min[-1] = "*";
+        for ($i = 0; $i <= 59; $i++) {
+            $this->min[$i] = sprintf("%1$02d", $i);
+        }
+        
+        # Fill hou
+        $this->hou = array();
+        $this->hou[-1] = "*";
+        if ($time12h) {
+            $this->hou[0] = "12 AM";
+            for ($i = 1; $i <= 12; $i++) {
+                $this->hou[$i] = sprintf("%1$02d", $i) . " AM";
+            }
+            for  ($i = 13; $i <= 23; $i++) {
+                $this->hou[$i] = sprintf("%1$02d", $i - 12) . " PM";
+            }
+        } else {
+            for ($i = 0; $i <= 23; $i++) {
+                $this->hou[$i] = sprintf("%1$02d", $i);
+            }
+        }
+
+        $this->day = array();
+        $this->day[-1] = "*";
+        for ($i = 1; $i <= 31; $i++) {
+            $this->day[$i] = sprintf("%1$02d", $i);
+        }
+
+        # Fill dow
+        if ($time12h) {
+            $this->dow = array(
+                -1  => '*',
+                0   => 'Sunday',
+                1   => 'Monday',
+                2   => 'Tuesday',
+                3   => 'Wednesday',
+                4   => 'Thursday',
+                5   => 'Friday',
+                6   => 'Saturday'
+            );
+        } else {
+            $this->dow = array(
+                -1  => '*',
+                1   => 'Monday',
+                2   => 'Tuesday',
+                3   => 'Wednesday',
+                4   => 'Thursday',
+                5   => 'Friday',
+                6   => 'Saturday',
+                0   => 'Sunday'
+            );
+        }
+
+        # Fill month
+        $this->mon = array(
+            -1  => '*',
+            1   => 'January',
+            2   => 'February',
+            3   => 'March',
+            4   => 'April',
+            5   => 'May',
+            6   => 'June',
+            7   => 'July',
+            8   => 'August',
+            9   => 'September',
+            10  => 'October',
+            11  => 'November',
+            12  => 'December'
+        );
+    }
+
+    private function _option_string($option_item, $draw_item, $selected_item) {
+
+        if ($option_item == $selected_item) {
+            return "<option selected value='" . $option_item . "'>" . $draw_item . "</option>\n";
+        }
+        return "<option value='" . $option_item . "'>" . $draw_item . "</option>\n";
+    }
+
+    private function _draw_selected($selector_name ,$range_array, $selected) {
+        $selector_text = "<select name = '$selector_name' id = '$selector_name' class='formfld'>\n";
+
+        foreach ($range_array as $option_item => $draw_item) {
+            $selector_text .= $this->_option_string($option_item, $draw_item, $selected);
+        }
+        $selector_text .= "</select>";
+        return $selector_text;
+    }
+
+    public function draw_min($name, $selected = '') {
+        return $this->_draw_selected($name, $this->min, $selected);
+    }
+
+    public function draw_hou($name, $selected = '') {
+        return $this->_draw_selected($name, $this->hou, $selected);
+    }
+
+    public function draw_dom($name, $selected = '') {
+        return $this->_draw_selected($name ,$this->day, $selected);
+    }
+
+    public function draw_mon($name, $selected = '') {
+        return $this->_draw_selected($name ,$this->mon, $selected);
+    }
+
+    public function draw_dow($name, $selected = '') {
+        return $this->_draw_selected($name, $this->dow, $selected);
+    }
+}
+?>

+ 90 - 0
school_bells/root.php

@@ -0,0 +1,90 @@
+<?php
+/*
+	FusionPBX
+	Version: MPL 1.1
+
+	The contents of this file are subject to the Mozilla Public License Version
+	1.1 (the "License"); you may not use this file except in compliance with
+	the License. You may obtain a copy of the License at
+	http://www.mozilla.org/MPL/
+
+	Software distributed under the License is distributed on an "AS IS" basis,
+	WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+	for the specific language governing rights and limitations under the
+	License.
+
+	The Original Code is FusionPBX
+
+	The Initial Developer of the Original Code is
+	Mark J Crane <[email protected]>
+	Portions created by the Initial Developer are Copyright (C) 2008-2012
+	the Initial Developer. All Rights Reserved.
+
+	Contributor(s):
+	Mark J Crane <[email protected]>
+*/
+
+// make sure the PATH_SEPARATOR is defined
+	umask(2);
+	if (!defined("PATH_SEPARATOR")) {
+		if (strpos($_ENV["OS"], "Win") !== false) {
+			define("PATH_SEPARATOR", ";");
+		} else {
+			define("PATH_SEPARATOR", ":");
+		}
+	}
+
+	if (!isset($output_format)) $output_format = (PHP_SAPI == 'cli') ? 'text' : 'html';
+
+	// make sure the document_root is set
+	$_SERVER["SCRIPT_FILENAME"] = str_replace("\\", '/', $_SERVER["SCRIPT_FILENAME"]);
+	if(PHP_SAPI == 'cli'){
+		chdir(pathinfo(realpath($_SERVER["PHP_SELF"]), PATHINFO_DIRNAME));
+		$script_full_path = str_replace("\\", '/', getcwd() . '/' . $_SERVER["SCRIPT_FILENAME"]);
+		$dirs = explode('/', pathinfo($script_full_path, PATHINFO_DIRNAME));
+		if (file_exists('/project_root.php')) {
+			$path = '/';
+		} else {
+			$i    = 1;
+			$path = '';
+			while ($i < count($dirs)) {
+				$path .= '/' . $dirs[$i];
+				if (file_exists($path. '/project_root.php')) {
+					break;
+				}
+				$i++;
+			}
+		}
+		$_SERVER["DOCUMENT_ROOT"] = $path;
+	}else{
+		$_SERVER["DOCUMENT_ROOT"]   = str_replace($_SERVER["PHP_SELF"], "", $_SERVER["SCRIPT_FILENAME"]);
+	}
+	$_SERVER["DOCUMENT_ROOT"]   = realpath($_SERVER["DOCUMENT_ROOT"]);
+// try to detect if a project path is being used
+	if (!defined('PROJECT_PATH')) {
+		if (is_dir($_SERVER["DOCUMENT_ROOT"]. '/fusionpbx')) {
+			define('PROJECT_PATH', '/fusionpbx');
+		} elseif (file_exists($_SERVER["DOCUMENT_ROOT"]. '/project_root.php')) {
+			define('PROJECT_PATH', '');
+		} else {
+			$dirs = explode('/', str_replace('\\', '/', pathinfo($_SERVER["PHP_SELF"], PATHINFO_DIRNAME)));
+			$i    = 1;
+			$path = $_SERVER["DOCUMENT_ROOT"];
+			while ($i < count($dirs)) {
+				$path .= '/' . $dirs[$i];
+				if (file_exists($path. '/project_root.php')) {
+					break;
+				}
+				$i++;
+			}
+			if(!file_exists($path. '/project_root.php')){
+				die("Failed to locate the Project Root by searching for project_root.php please contact support for assistance");
+			}
+			$project_path = str_replace($_SERVER["DOCUMENT_ROOT"], "", $path);
+			define('PROJECT_PATH', $project_path);
+		}
+		$_SERVER["PROJECT_ROOT"] = realpath($_SERVER["DOCUMENT_ROOT"] . PROJECT_PATH);
+		set_include_path(get_include_path() . PATH_SEPARATOR . $_SERVER["PROJECT_ROOT"]);
+	}
+
+?>

+ 574 - 0
school_bells/school_bell_edit.php

@@ -0,0 +1,574 @@
+<?php
+/*
+	FusionPBX
+	Version: MPL 1.1
+
+	The contents of this file are subject to the Mozilla Public License Version
+	1.1 (the "License"); you may not use this file except in compliance with
+	the License. You may obtain a copy of the License at
+	http://www.mozilla.org/MPL/
+
+	Software distributed under the License is distributed on an "AS IS" basis,
+	WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+	for the specific language governing rights and limitations under the
+	License.
+
+	The Original Code is FusionPBX
+
+	The Initial Developer of the Original Code is
+	Mark J Crane <[email protected]>
+	Portions created by the Initial Developer are Copyright (C) 2008-2018
+	the Initial Developer. All Rights Reserved.
+
+	Contributor(s):
+	Mark J Crane <[email protected]>
+	Igor Olhovskiy <[email protected]>
+*/
+//includes
+	require_once "root.php";
+	require_once "resources/require.php";
+	require_once "resources/check_auth.php";
+
+//check permissions
+	if (permission_exists('school_bell_edit') || permission_exists('school_bell_add')) {
+		//access granted
+	} else {
+		echo "access denied";
+		exit;
+	}
+
+//add multi-lingual support
+	$language = new text;
+	$text = $language->get();
+
+// Get timezones
+	$timezone_identifiers_list = timezone_identifiers_list();
+//action add or update
+	if (isset($_REQUEST["id"])) {
+		$action = "update";
+		$school_bell_uuid = check_str($_REQUEST["id"]);
+	} else {
+		$action = "add";
+	}
+
+//get http post variables and set them to php variables
+	if (count($_POST) > 0) {
+		$school_bell_name = check_str($_POST["school_bell_name"]);
+		$school_bell_leg_a_type = check_str($_POST["school_bell_leg_a_type"]);
+		$school_bell_leg_a_data = check_str($_POST["school_bell_leg_a_data"]);
+		$school_bell_leg_b_type = check_str($_POST["school_bell_leg_b_type"]);
+		$school_bell_leg_b_data = check_str($_POST["school_bell_leg_b_data"]);
+		$school_bell_ring_timeout = (int)check_str($_POST["school_bell_ring_timeout"]);
+		$school_bell_min = (int)check_str($_POST["school_bell_min"]);
+		$school_bell_hour = (int)check_str($_POST["school_bell_hour"]);
+		$school_bell_dom = (int)check_str($_POST["school_bell_dom"]);
+		$school_bell_mon = (int)check_str($_POST["school_bell_mon"]);
+		$school_bell_dow = (int)check_str($_POST["school_bell_dow"]);
+		$school_bell_timezone = check_str($_POST["school_bell_timezone"]);
+		$school_bell_enabled = check_str($_POST["school_bell_enabled"]);
+		$school_bell_description = check_str($_POST["school_bell_description"]);
+	
+			// Filter values:
+		if (strlen($school_bell_leg_a_type) == 0) {
+			$school_bell_leg_a_type = "loopback/";
+		}
+
+		if (strlen($school_bell_leg_b_data) > 0) {
+			$school_bell_leg_b_type = $_SESSION['switch']['recordings']['dir']."/".$_SESSION['domain_name']."/".$school_bell_leg_b_data;
+		}
+
+		// Set default ring timeout to 3 sec
+		if ($school_bell_ring_timeout < 0) {
+			$school_bell_ring_timeout = 3;
+		}
+
+		if ($school_bell_min != -1 && ($school_bell_min > 59 || $school_bell_min < 0)) {
+			$school_bell_min = 0;
+		}
+
+		if ($school_bell_hour != -1 && ($school_bell_hour < 0 || $school_bell_hour > 23)) {
+			$school_bell_hour = 0;
+		}
+
+		if ($school_bell_dom != -1 && ($school_bell_dom < 1 || $school_bell_dom > 31)) {
+			$school_bell_dom = 1;
+		}
+
+		if ($school_bell_mon != -1 && ($school_bell_mon < 1 || $school_bell_mon > 12)) {
+			$school_bell_mon = 1;
+		}
+
+		if ($school_bell_dow != -1 && ($school_bell_dow < 0 || $school_bell_dow > 6)) {
+			$school_bell_dow = 0;
+		}
+
+		if (!in_array($school_bell_timezone, $timezone_identifiers_list)) {
+			$school_bell_timezone = date_default_timezone_get();
+		}
+
+		if (strlen($school_bell_enabled) == 0) {
+			$school_bell_enabled = 'true';
+		}
+	}
+//handle the http post
+	if (count($_POST) > 0 && strlen($_POST["persistformvar"]) == 0) {
+	
+		$msg = '';
+	
+		//check for all required data
+		if (strlen($school_bell_name) == 0) { 
+			$msg .= $text['label-school_bell_name']."<br>\n"; 
+		}
+		if (strlen($school_bell_leg_a_data) == 0) {
+			$msg .= $text['label-school_bell_leg_a_data']."<br>\n"; 
+		}
+
+		if (strlen($msg) > 0 && strlen($_POST["persistformvar"]) == 0) {
+			require_once "resources/header.php";
+			require_once "resources/persist_form_var.php";
+			echo "<div align='center'>\n";
+			echo "<table><tr><td>\n";
+			echo $msg."<br />";
+			echo "</td></tr></table>\n";
+			persistformvar($_POST);
+			echo "</div>\n";
+			require_once "resources/footer.php";
+			return;
+		}
+
+	//add or update the database
+		if (($_POST["persistformvar"] != "true") > 0) {
+
+			if ($action == "add") {
+
+				$school_bell_uuid = uuid();
+
+				$sql = "INSERT INTO v_school_bells";
+				$sql .= " (";
+				$sql .= "domain_uuid, ";
+				$sql .= "school_bell_uuid, ";
+				$sql .= "school_bell_name, ";
+				$sql .= "school_bell_leg_a_type, ";
+				$sql .= "school_bell_leg_a_data, ";
+				$sql .= "school_bell_leg_b_type, ";
+				$sql .= "school_bell_leg_b_data, ";
+				$sql .= "school_bell_ring_timeout, ";
+				$sql .= "school_bell_min, ";
+				$sql .= "school_bell_hour, ";
+				$sql .= "school_bell_dom, ";
+				$sql .= "school_bell_mon, ";
+				$sql .= "school_bell_dow, ";
+				$sql .= "school_bell_timezone, ";
+				$sql .= "school_bell_enabled, ";
+				$sql .= "school_bell_description ";
+				$sql .= ") ";
+				$sql .= "VALUES ";
+				$sql .= "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+
+				$insert_array = array(
+					'domain_uuid' => $domain_uuid,
+					'school_bell_uuid' => $school_bell_uuid,
+					'school_bell_name' => $school_bell_name,
+					'school_bell_leg_a_type' => $school_bell_leg_a_type,
+					'school_bell_leg_a_data' => $school_bell_leg_a_data,
+					'school_bell_leg_b_type' => $school_bell_leg_b_type,
+					'school_bell_leg_b_data' => $school_bell_leg_b_data,
+					'school_bell_ring_timeout' => $school_bell_ring_timeout,
+					'school_bell_min' => $school_bell_min,
+					'school_bell_hour' => $school_bell_hour,
+					'school_bell_dom' => $school_bell_dom,
+					'school_bell_mon' => $school_bell_mon,
+					'school_bell_dow' => $school_bell_dow,
+					'school_bell_timezone' => $school_bell_timezone,
+					'school_bell_enabled' => $school_bell_enabled,
+					'school_bell_description' => $school_bell_description
+				);
+
+				$prep_statement = $db->prepare(check_sql($sql));
+				$prep_statement->execute(array_values($insert_array));
+
+				unset($sql, $prep_statement, $insert_array);
+
+				messages::add($text['label-add-complete']);
+				header("Location: school_bells.php");
+				return;
+			} //if ($action == "add")
+
+			if ($action == "update") {
+
+				$sql = "UPDATE v_school_bells SET ";
+				$sql .= "school_bell_name = :school_bell_name, ";
+				$sql .= "school_bell_leg_a_type = :school_bell_leg_a_type, ";
+				$sql .= "school_bell_leg_a_data = :school_bell_leg_a_data, ";
+				$sql .= "school_bell_leg_b_type = :school_bell_leg_b_type, ";
+				$sql .= "school_bell_leg_b_data = :school_bell_leg_b_data, ";
+				$sql .= "school_bell_ring_timeout = :school_bell_ring_timeout, ";
+				$sql .= "school_bell_min = :school_bell_min, ";
+				$sql .= "school_bell_hour = :school_bell_hour, ";
+				$sql .= "school_bell_dom = :school_bell_dom, ";
+				$sql .= "school_bell_mon = :school_bell_mon, ";
+				$sql .= "school_bell_dow = :school_bell_dow, ";
+				$sql .= "school_bell_timezone = :school_bell_timezone, ";
+				$sql .= "school_bell_enabled = :school_bell_enabled, ";
+				$sql .= "school_bell_description = :school_bell_description";
+				$sql .= " WHERE domain_uuid = :domain_uuid";
+				$sql .= " AND school_bell_uuid = :school_bell_uuid";
+
+				$prep_statement = $db->prepare(check_sql($sql));
+
+				$prep_statement->bindValue('school_bell_name', $school_bell_name);
+				$prep_statement->bindValue('school_bell_leg_a_type', $school_bell_leg_a_type);
+				$prep_statement->bindValue('school_bell_leg_a_data', $school_bell_leg_a_data);
+				$prep_statement->bindValue('school_bell_leg_b_type', $school_bell_leg_b_type);
+				$prep_statement->bindValue('school_bell_leg_b_data', $school_bell_leg_b_data);
+				$prep_statement->bindValue('school_bell_ring_timeout', $school_bell_ring_timeout);
+				$prep_statement->bindValue('school_bell_min', $school_bell_min);
+				$prep_statement->bindValue('school_bell_hour', $school_bell_hour);
+				$prep_statement->bindValue('school_bell_dom', $school_bell_dom);
+				$prep_statement->bindValue('school_bell_mon', $school_bell_mon);
+				$prep_statement->bindValue('school_bell_dow', $school_bell_dow);
+				$prep_statement->bindValue('school_bell_timezone', $school_bell_timezone);
+				$prep_statement->bindValue('school_bell_enabled', $school_bell_enabled);
+				$prep_statement->bindValue('school_bell_description', $school_bell_description);
+				$prep_statement->bindValue('domain_uuid', $domain_uuid);
+				$prep_statement->bindValue('school_bell_uuid', $school_bell_uuid);
+				
+				if ($prep_statement) {
+					$prep_statement->execute();
+				}
+				unset($sql, $prep_statement);
+
+				messages::add($text['label-update-complete']);
+				header("Location: school_bells.php");
+				return;
+			} //if ($action == "update")
+		} //if ($_POST["persistformvar"] != "true")
+	} //(count($_POST)>0 && strlen($_POST["persistformvar"]) == 0)
+
+//pre-populate the form
+	if (count($_GET) > 0 && $_POST["persistformvar"] != "true") {
+		$school_bell_uuid = $_GET["id"];
+		$sql = "SELECT * FROM v_school_bells";
+		$sql .= " WHERE domain_uuid = :domain_uuid";
+		$sql .= " AND school_bell_uuid = :school_bell_uuid";
+		$sql .= " LIMIT 1";
+
+		$prep_statement = $db->prepare(check_sql($sql));
+
+		$prep_statement->bindValue('domain_uuid', $domain_uuid);
+		$prep_statement->bindValue('school_bell_uuid', $school_bell_uuid);
+
+		$prep_statement->execute();
+		$result = $prep_statement->fetchAll();
+
+		foreach ($result as &$row) {
+			$school_bell_name = $row["school_bell_name"];
+			$school_bell_leg_a_type = $row["school_bell_leg_a_type"];
+			$school_bell_leg_a_data = $row["school_bell_leg_a_data"];
+			$school_bell_leg_b_type = $row["school_bell_leg_b_type"];
+			$school_bell_leg_b_data = $row["school_bell_leg_b_data"];
+			$school_bell_min = $row["school_bell_min"];
+			$school_bell_hour = $row["school_bell_hour"];
+			$school_bell_dom = $row["school_bell_dom"];
+			$school_bell_mon = $row["school_bell_mon"];
+			$school_bell_dow = $row["school_bell_dow"];
+			$school_bell_timezone = $row["school_bell_timezone"];
+			$school_bell_enabled = $row["school_bell_enabled"];
+			$school_bell_description = $row["school_bell_description"];
+			break; //limit to 1 row ? Should be only 1 result at all
+		}
+		unset ($prep_statement, $sql);
+	}
+
+	//get the recordings
+	$sql = "SELECT recording_name, recording_filename FROM v_recordings";
+	$sql .= " WHERE domain_uuid = :domain_uuid";
+	$sql .= " ORDER BY recording_name ASC";
+	$prep_statement = $db->prepare(check_sql($sql));
+	$prep_statement->bindValue('domain_uuid', $domain_uuid);
+	$prep_statement->execute();
+	$recordings = $prep_statement->fetchAll(PDO::FETCH_ASSOC);
+
+	//get the phrases
+	// $sql = "SELECT * FROM v_phrases ";
+	// $sql .= " WHERE (domain_uuid = :domain_uuid OR domain_uuid IS NULL) ";
+	// $prep_statement = $db->prepare(check_sql($sql));
+	// $prep_statement->bindValue('domain_uuid', $domain_uuid);
+	// $prep_statement->execute();
+	// $phrases = $prep_statement->fetchAll(PDO::FETCH_NAMED);
+
+	//get the sound files
+	$file = new file;
+	$sound_files = $file->sounds();
+
+	$school_bell_selector = new school_bell_selector($_SESSION['domain']['time_format']['text'] == '12h');
+
+	// One of defaults
+	if (strlen($school_bell_timezone) == 0) {
+		$school_bell_timezone = date_default_timezone_get();
+	}
+
+//show the header
+	require_once "resources/header.php";
+
+//show the content
+
+	echo "<form method='post' name='frm' action=''>\n";
+	echo "<table width='100%' border='0' cellpadding='0' cellspacing='0'>\n";
+	echo "<tr>\n";
+	if ($action == "add") {
+		echo "<td align='left' width='30%' nowrap='nowrap'><b>".$text['label-school_bells-add']."</b></td>\n";
+	}
+	if ($action == "update") {
+		echo "<td align='left' width='30%' nowrap='nowrap'><b>".$text['label-school_bells-edit']."</b></td>\n";
+	}
+	echo "<td width='70%' align='right'>";
+	echo "	<input type='button' class='btn' name='' alt='".$text['button-back']."' onclick=\"window.location='school_bells.php'\" value='".$text['button-back']."'>";
+	echo "	<input type='submit' name='submit' class='btn' value='".$text['button-save']."'>\n";
+	echo "</td>\n";
+	echo "</tr>\n";
+	echo "<tr>\n";
+	echo "<td align='left' colspan='2'>\n";
+	if ($action == "add") {
+		echo $text['label-school_bells-add-note']."<br /><br />\n";
+	}
+	if ($action == "update") {
+		echo $text['label-school_bells-edit-note']."<br /><br />\n";
+	}
+	echo "</td>\n";
+	echo "</tr>\n";
+
+	// Show name
+	echo "<tr>\n";
+	echo "<td class='vncellreq' valign='top' align='left' nowrap='nowrap'>\n";
+	echo "	".$text['label-school_bell_name']."\n";
+	echo "</td>\n";
+	echo "<td class='vtable' align='left'>\n";
+	echo "	<input class='formfld' type='text' name='school_bell_name' maxlength='255' value=\"".escape($school_bell_name)."\" required='required'>\n";
+	echo "<br />\n";
+	echo $text['description-school_bell_name']."\n";
+	echo "</td>\n";
+	echo "</tr>\n";
+
+	// Show school_bell_leg_a_data
+	echo "<tr>\n";
+	echo "<td class='vncellreq' valign='top' align='left' nowrap='nowrap'>\n";
+	echo "	".$text['label-school_bell_leg_a_data']."\n";
+	echo "</td>\n";
+	echo "<td class='vtable' align='left'>\n";
+	echo "	<input class='formfld' type='text' name='school_bell_leg_a_data' maxlength='255' value=\"".escape($school_bell_leg_a_data)."\" required='required'>\n";
+	echo "<br />\n";
+	echo $text['description-school_bell_leg_a_data']."\n";
+	echo "</td>\n";
+	echo "</tr>\n";
+
+	// Show ring timeout
+	echo "<tr>\n";
+	echo "<td class='vncellreq' valign='top' align='left' nowrap='nowrap'>\n";
+	echo "	".$text['label-school_bell_ring_timeout']."\n";
+	echo "</td>\n";
+	echo "<td class='vtable' align='left'>\n";
+	echo "	<input class='formfld' type='number' name='school_bell_ring_timeout' min='0' max='3600' value=\"".escape($school_bell_ring_timeout)."\">\n";
+	echo "<br />\n";
+	echo $text['description-school_bell_ring_timeout']."\n";
+	echo "</td>\n";
+	echo "</tr>\n";
+
+	// Show school_bell_leg_b_data
+	echo "<tr>\n";
+	echo "<td class='vncellreq' valign='top' align='left' nowrap>\n";
+	echo "	".$text['label-school_bell_leg_b_data']."\n";
+	echo "</td>\n";
+	echo "<td class='vtable' align='left'>\n";
+	echo "<select name='school_bell_leg_b_data' id='school_bell_leg_b_data' class='formfld'>\n";
+	echo "	<option></option>\n";
+	//recordings
+	$tmp_selected = false;
+	if (is_array($recordings)) {
+		echo "<optgroup label='Recordings'>\n";
+		foreach ($recordings as &$row) {
+			$recording_name = $row["recording_name"];
+			$recording_filename = $row["recording_filename"];
+			if ($school_bell_leg_b_data == $_SESSION['switch']['recordings']['dir']."/".$_SESSION['domain_name']."/".$recording_filename && strlen($school_bell_leg_b_data) > 0) {
+				$tmp_selected = true;
+				echo "	<option value='".escape($_SESSION['switch']['recordings']['dir'])."/".escape($_SESSION['domain_name'])."/".escape($recording_filename)."' selected='selected'>".escape($recording_name)."</option>\n";
+			}
+			else if ($school_bell_leg_b_data == $recording_filename && strlen($school_bell_leg_b_data) > 0) {
+				$tmp_selected = true;
+				echo "	<option value='".escape($recording_filename)."' selected='selected'>".escape($recording_name)."</option>\n";
+			}
+			else {
+				echo "	<option value='".escape($recording_filename)."'>".escape($recording_name)."</option>\n";
+			}
+		}
+		echo "</optgroup>\n";
+	}
+
+	if (if_group("superadmin")) {
+		if (!$tmp_selected && strlen($school_bell_leg_b_data) > 0) {
+			echo "<optgroup label='Selected'>\n";
+			if (file_exists($_SESSION['switch']['recordings']['dir']."/".$_SESSION['domain_name']."/".$school_bell_leg_b_data)) {
+				echo "	<option value='".escape($_SESSION['switch']['recordings']['dir'])."/".escape($_SESSION['domain_name'])."/".escape($school_bell_leg_b_data)."' selected='selected'>".escape($school_bell_leg_b_data)."</option>\n";
+			}
+			else if (substr($school_bell_leg_b_data, -3) == "wav" || substr($school_bell_leg_b_data, -3) == "mp3") {
+				echo "	<option value='".escape($school_bell_leg_b_data)."' selected='selected'>".escape($school_bell_leg_b_data)."</option>\n";
+			}
+			else {
+				echo "	<option value='".escape($school_bell_leg_b_data)."' selected='selected'>".escape($school_bell_leg_b_data)."</option>\n";
+			}
+			echo "</optgroup>\n";
+		}
+		unset($tmp_selected);
+	}
+
+	echo "	</select>\n";
+	if (if_group("superadmin")) {
+		echo "<input type='button' id='btn_select_to_input_".escape($destination_id)."' class='btn' name='' alt='back' onclick='changeToInput".escape($destination_id)."(document.getElementById(\"".escape($destination_id)."\"));this.style.visibility = \"hidden\";' value='&#9665;'>";
+		unset($destination_id);
+	}
+	echo "	<br />\n";
+	echo $text['description-school_bell_leg_b_data']."\n";
+	echo "</td>\n";
+	echo "</tr>\n";
+
+	// End school_bell_leg_b_data
+	// Show divider
+	echo "<tr><td colspan='2'><br /></td></tr>\n";
+
+	// Show Min
+	echo "<tr>\n";
+	echo "<td class='vncell' valign='top' align='left' nowrap='nowrap'>\n";
+	echo "	".$text['label-school_bell_min']."\n";
+	echo "</td>\n";
+	echo "<td class='vtable' align='left'>\n";
+	echo $school_bell_selector->draw_min('school_bell_min', $school_bell_min);
+	echo "<br />\n";
+	echo $text['description-school_bell_min']."\n";
+	echo "\n";
+	echo "</td>\n";
+	echo "</tr>\n";
+
+	// Show Hour
+	echo "<tr>\n";
+	echo "<td class='vncell' valign='top' align='left' nowrap='nowrap'>\n";
+	echo "	".$text['label-school_bell_hour']."\n";
+	echo "</td>\n";
+	echo "<td class='vtable' align='left'>\n";
+	echo $school_bell_selector->draw_hou('school_bell_hour', $school_bell_hour);
+	echo "<br />\n";
+	echo $text['description-school_bell_hour']."\n";
+	echo "\n";
+	echo "</td>\n";
+	echo "</tr>\n";
+
+	// Show Day of the Month
+	echo "<tr>\n";
+	echo "<td class='vncell' valign='top' align='left' nowrap='nowrap'>\n";
+	echo "	".$text['label-school_bell_dom']."\n";
+	echo "</td>\n";
+	echo "<td class='vtable' align='left'>\n";
+	echo $school_bell_selector->draw_dom('school_bell_dom', $school_bell_dom);
+	echo "<br />\n";
+	echo $text['description-school_bell_dom']."\n";
+	echo "\n";
+	echo "</td>\n";
+	echo "</tr>\n";
+
+	// Show Month
+	echo "<tr>\n";
+	echo "<td class='vncell' valign='top' align='left' nowrap='nowrap'>\n";
+	echo "	".$text['label-school_bell_mon']."\n";
+	echo "</td>\n";
+	echo "<td class='vtable' align='left'>\n";
+	echo $school_bell_selector->draw_mon('school_bell_mon', $school_bell_mon);
+	echo "<br />\n";
+	echo $text['description-school_bell_mon']."\n";
+	echo "\n";
+	echo "</td>\n";
+	echo "</tr>\n";
+
+	// Show Day of the Week
+	echo "<tr>\n";
+	echo "<td class='vncell' valign='top' align='left' nowrap='nowrap'>\n";
+	echo "	".$text['label-school_bell_dow']."\n";
+	echo "</td>\n";
+	echo "<td class='vtable' align='left'>\n";
+	echo $school_bell_selector->draw_dow('school_bell_dow', $school_bell_dow);
+	echo "<br />\n";
+	echo $text['description-school_bell_dow']."\n";
+	echo "\n";
+	echo "</td>\n";
+	echo "</tr>\n";
+
+	// Show timezone
+	echo "<tr>\n";
+	echo "<td class='vncell' valign='top' align='left' nowrap='nowrap'>\n";
+	echo "	".$text['label-school_bell_timezone']."\n";
+	echo "</td>\n";
+	echo "<td class='vtable' align='left'>\n";
+	echo "	<select class='formfld' name='school_bell_timezone'>\n";
+	foreach ($timezone_identifiers_list as $timezone_identifier) {
+		echo "		<option value='$timezone_identifier' ".(($school_bell_timezone == $timezone_identifier) ? "selected" : null).">".escape($timezone_identifier)."</option>\n";
+	}
+	echo "	</select>\n";
+	echo "<br />\n";
+	echo $text['description-school_bell_timezone']."\n";
+	echo "\n";
+	echo "</td>\n";
+	echo "</tr>\n";
+
+	// Show divider
+	echo "<tr><td colspan='2'><br /></td></tr>\n";
+
+	// Show enabled
+	echo "<tr>\n";
+	echo "<td class='vncell' valign='top' align='left' nowrap='nowrap'>\n";
+	echo "	".$text['label-school_bell_enabled']."\n";
+	echo "</td>\n";
+	echo "<td class='vtable' align='left'>\n";
+	echo "	<select class='formfld' name='school_bell_enabled'>\n";
+	echo "		<option value='true' ".(($school_bell_enabled == "true") ? "selected" : null).">".$text['label-true']."</option>\n";
+	echo "		<option value='false' ".(($school_bell_enabled == "false") ? "selected" : null).">".$text['label-false']."</option>\n";
+	echo "	</select>\n";
+	echo "<br />\n";
+	echo $text['description-school_bell_enabled']."\n";
+	echo "\n";
+	echo "</td>\n";
+	echo "</tr>\n";
+
+	// Show description
+	echo "<tr>\n";
+	echo "<td class='vncellreq' valign='top' align='left' nowrap='nowrap'>\n";
+	echo "	".$text['label-school_bell_description']."\n";
+	echo "</td>\n";
+	echo "<td class='vtable' align='left'>\n";
+	echo "	<input class='formfld' type='text' name='school_bell_description' maxlength='255' value=\"".escape($school_bell_description)."\">\n";
+	echo "<br />\n";
+	echo $text['description-school_bell_description']."\n";
+	echo "</td>\n";
+	echo "</tr>\n";
+
+	echo "	<tr>\n";
+	echo "		<td colspan='2' align='right'>\n";
+	if ($action == "update") {
+		echo "		<input type='hidden' name='id' value='".escape($school_bell_uuid)."'>\n";
+	}
+	echo "			<br>";
+	echo "			<input type='submit' name='submit' class='btn' value='".$text['button-save']."'>\n";
+	echo "		</td>\n";
+	echo "	</tr>";
+	echo "</table>";
+	echo "<br><br>";
+	echo "</form>";
+
+	echo "<table>";
+	echo "<tr>";
+	echo "<td>";
+	echo $text['description-school_bells_schedule_templates'];
+	echo "</td>";
+	echo "</tr>";
+	echo "</table>";
+
+//include the footer
+	require_once "resources/footer.php";
+?>

+ 179 - 0
school_bells/school_bells.php

@@ -0,0 +1,179 @@
+<?php
+/*
+	FusionPBX
+	Version: MPL 1.1
+
+	The contents of this file are subject to the Mozilla Public License Version
+	1.1 (the "License"); you may not use this file except in compliance with
+	the License. You may obtain a copy of the License at
+	http://www.mozilla.org/MPL/
+
+	Software distributed under the License is distributed on an "AS IS" basis,
+	WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+	for the specific language governing rights and limitations under the
+	License.
+
+	The Original Code is FusionPBX
+
+	The Initial Developer of the Original Code is
+	Mark J Crane <[email protected]>
+	Portions created by the Initial Developer are Copyright (C) 2008-2016
+	the Initial Developer. All Rights Reserved.
+
+	Contributor(s):
+	Mark J Crane <[email protected]>
+	Igor Olhovskiy <[email protected]>
+*/
+require_once "root.php";
+require_once "resources/require.php";
+require_once "resources/check_auth.php";
+
+if (permission_exists('school_bell_view')) {
+	//access granted
+}
+else {
+	echo "access denied";
+	exit;
+}
+
+//add multi-lingual support
+	$language = new text;
+	$text = $language->get();
+
+require_once "resources/header.php";
+	$document['title'] = $text['title-school_bells'];
+
+require_once "resources/paging.php";
+
+//get variables used to control the order
+	$order_by = $_GET["order_by"];
+	$order = $_GET["order"];
+
+	//prepare to page the results
+	$sql = "SELECT count(school_bell_uuid) AS num_rows FROM v_school_bells";
+	$sql .= " WHERE domain_uuid = :domain_uuid";
+	$prep_statement = $db->prepare($sql);
+	$prep_statement->bindValue('domain_uuid', $domain_uuid);
+	if ($prep_statement) {
+		$prep_statement->execute();
+		$row = $prep_statement->fetch(PDO::FETCH_ASSOC);
+		$num_rows = ($row['num_rows'] > 0) ? $row['num_rows'] : '0';
+	}
+
+	//prepare to page the results
+	$rows_per_page = ($_SESSION['domain']['paging']['numeric'] != '') ? $_SESSION['domain']['paging']['numeric'] : 50;
+	$param = "";
+	$page = $_GET['page'];
+	if (strlen($page) == 0) { 
+		$page = 0; 
+		$_GET['page'] = 0; 
+	}
+	list($paging_controls, $rows_per_page, $var3) = paging($num_rows, $param, $rows_per_page);
+	$offset = $rows_per_page * $page;
+
+	//get the list
+	if ($num_rows > 0) {
+		$sql = "SELECT * FROM v_school_bells";
+		$sql .= " WHERE domain_uuid = :domain_uuid";
+		if (strlen($order_by)> 0) { 
+			$sql .= " ORDER BY $order_by $order"; 
+		}
+		$sql .= " LIMIT $rows_per_page OFFSET $offset";
+
+		$prep_statement = $db->prepare(check_sql($sql));
+		$prep_statement->bindValue('domain_uuid', $domain_uuid);
+
+		$prep_statement->execute();
+		$result = $prep_statement->fetchAll();
+		$result_count = count($result);
+		unset ($prep_statement, $sql);
+	}
+
+	//show the content
+	echo "<table width='100%' cellpadding='0' cellspacing='0 border='0'>\n";
+	echo "	<tr>\n";
+	echo "		<td width='50%' align='left' nowrap='nowrap'><b>".$text['header-school_bells']." (".$num_rows.")</b></td>\n";
+	echo "		<td width='50%' align='right'>&nbsp;</td>\n";
+	echo "	</tr>\n";
+	echo "	<tr>\n";
+	echo "		<td align='left' colspan='2'>\n";
+	echo "			".$text['description-school_bells']."<br /><br />\n";
+	echo "		</td>\n";
+	echo "	</tr>\n";
+	echo "</table>\n";
+
+	$c = 0;
+	$row_style["0"] = "row_style0";
+	$row_style["1"] = "row_style1";
+
+	echo "<table class='tr_hover' width='100%' border='0' cellpadding='0' cellspacing='0'>\n";
+	echo "<tr>\n";
+	echo th_order_by('school_bell_name', $text['label-school_bell_name'], $order_by, $order);
+	echo th_order_by('school_bell_leg_a_data', $text['label-school_bell_leg_a_data'], $order_by, $order);
+	echo th_order_by('school_bell_leg_b_data', $text['label-school_bell_leg_b_data'], $order_by, $order);
+	echo "<th>".$text['label-school_bell_schedule_time']."</th>\n";
+	echo th_order_by('school_bell_enabled', $text['label-school_bell_enabled'], $order_by, $order);
+	echo th_order_by('school_bell_description', $text['label-school_bell_description'], $order_by, $order);
+	echo "<td class='list_control_icons'>";
+	if (permission_exists('school_bell_add')) {
+		echo "<a href='school_bell_edit.php' alt='".$text['button-add']."'>$v_link_label_add</a>";
+	}
+	echo "</td>\n";
+	echo "</tr>\n";
+
+	if ($result_count > 0) {
+		foreach($result as $row) {
+			$row = array_map('escape', $row);
+
+			$tr_link = (permission_exists('school_bell_edit')) ? "href='school_bell_edit.php?id=".$row['school_bell_uuid']."'" : null;
+			echo "<tr ".$tr_link.">\n";
+			echo "	<td valign='top' class='".$row_style[$c]."'>".$row['school_bell_name']."&nbsp;</td>\n";
+			echo "	<td valign='top' class='".$row_style[$c]."'>".$row['school_bell_leg_a_data']."&nbsp;</td>\n";
+			echo "	<td valign='top' class='".$row_style[$c]."'>".$row['school_bell_leg_b_data']."&nbsp;</td>\n";
+
+			$school_bell_schedule_time = ($row['school_bell_min'] == -1) ? '* ': $row['school_bell_min'] . " ";
+			$school_bell_schedule_time .= ($row['school_bell_hour'] == -1) ? '* ': $row['school_bell_hour'] . " ";
+			$school_bell_schedule_time .= ($row['school_bell_dom'] == -1) ? '* ': $row['school_bell_dom'] . " ";
+			$school_bell_schedule_time .= ($row['school_bell_mon'] == -1) ? '* ': $row['school_bell_mon'] . " ";
+			$school_bell_schedule_time .= ($row['school_bell_dow'] == -1) ? '* ': $row['school_bell_dow'] . " ";
+			echo "	<td valign='top' class='".$row_style[$c]."'>".$school_bell_schedule_time."&nbsp;</td>\n";
+
+			echo "	<td valign='top' class='".$row_style[$c]."'>".$row['school_bell_enabled']."&nbsp;</td>\n";
+			echo "	<td valign='top' class='".$row_style[$c]."'>".$row['school_bell_description']."&nbsp;</td>\n";
+
+			echo "	<td class='list_control_icons'>";
+			if (permission_exists('school_bell_edit')) {
+				echo "<a href='school_bell_edit.php?id=".$row['school_bell_uuid']."' alt='".$text['button-edit']."'>$v_link_label_edit</a>";
+			}
+			if (permission_exists('school_bell_delete')) {
+				echo "<a href='school_bell_delete.php?id=".$row['school_bell_uuid']."' alt='".$text['button-delete']."' onclick=\"return confirm('".$text['confirm-delete']."')\">$v_link_label_delete</a>";
+			}
+			echo "	</td>\n";
+			echo "</tr>\n";
+			$c = 1 - $c; // Switch 1/0/1/0...
+		} //end foreach
+		unset($sql, $result, $row_count);
+	} //end if results
+
+	echo "<tr>\n";
+	echo "<td colspan='10' align='left'>\n";
+	echo "	<table width='100%' cellpadding='0' cellspacing='0'>\n";
+	echo "	<tr>\n";
+	echo "		<td width='33.3%' nowrap>&nbsp;</td>\n";
+	echo "		<td width='33.3%' align='center' nowrap>$paging_controls</td>\n";
+	echo "		<td class='list_control_icons'>";
+	if (permission_exists('school_bell_add')) {
+		echo 		"<a href='school_bell_edit.php' alt='".$text['button-add']."'>$v_link_label_add</a>";
+	}
+	echo "		</td>\n";
+	echo "	</tr>\n";
+ 	echo "	</table>\n";
+	echo "</td>\n";
+	echo "</tr>\n";
+
+	echo "</table>";
+	echo "<br /><br />";
+
+//include the footer
+	require_once "resources/footer.php";
+?>

+ 123 - 0
school_bells/school_bells_cron.php

@@ -0,0 +1,123 @@
+<?php 
+
+//restrict to command line only
+	if(defined('STDIN')) {
+		$document_root = str_replace("\\", "/", $_SERVER["PHP_SELF"]);
+		preg_match("/^(.*)\/app\/.*$/", $document_root, $matches);
+		$document_root = $matches[1];
+		set_include_path($document_root);
+		include "root.php";
+		require_once "resources/require.php";
+		require_once "resources/classes/text.php";
+		$_SERVER["DOCUMENT_ROOT"] = $document_root;
+		$format = 'text'; //html, text
+	
+		//add multi-lingual support
+		$language = new text;
+		$text = $language->get();
+	}
+	else {
+		die('access denied');
+	}
+
+	set_time_limit(55); // Cannot run more than 55 seconds
+
+	$current_timestamp = time();
+
+	$current_minute = (int)date('i', $current_timestamp);
+
+	$sql = "SELECT v_domains.domain_name AS context,";
+	$sql .= " domain_uuid AS domain_uuid,";
+	$sql .= " school_bell_leg_a_data AS extension,";
+	$sql .= " school_bell_leg_b_type AS full_path,";
+	$sql .= " school_bell_ring_timeout AS ring_timeout,";
+	$sql .= " school_bell_min as min,";
+	$sql .= " school_bell_hour as hour,";
+	$sql .= " school_bell_dom as dom,";
+	$sql .= " school_bell_mon as mon,";
+	$sql .= " school_bell_dow as dow,";
+	$sql .= " school_bell_timezone as timezone ";
+	$sql .= "FROM v_school_bells ";
+	$sql .= "JOIN v_domains ON v_domains.domain_uuid = v_school_bells.domain_uuid ";
+	$sql .= " WHERE school_bell_min = :current_minute";
+	$sql .= " OR school_bell_min = -1";
+	
+	$prep_statement = $db->prepare(check_sql($sql));
+	if (!$prep_statement) {
+		die('SQL forming error');
+	}
+	$prep_statement->bindValue('current_minute', $current_minute);
+	
+	if (!$prep_statement->execute()) {
+		die('SQL execute error');
+	}
+
+	$school_bells = $prep_statement->fetchAll(PDO::FETCH_NAMED);
+
+	if (count($school_bells) == 0) {
+		return;
+	}
+
+	$freeswitch_event_socket = event_socket_create($_SESSION['event_socket_ip_address'], $_SESSION['event_socket_port'], $_SESSION['event_socket_password']);
+	if (!$freeswitch_event_socket) {
+		die("Cannot connect to Event socket");
+	}
+
+	//$switch_result = event_socket_request($fp, 'api sofia status');
+	//print($switch_result);
+
+	foreach ($school_bells as $school_bell) {
+
+		$school_bell_timezone = $school_bell['timezone'];
+		date_default_timezone_set($school_bell_timezone);
+
+		$school_bell_hour = (int)$school_bell['hour'];
+		$current_hour = (int)date('G', $current_timestamp);
+
+		if ($school_bell_hour != -1 || $current_hour != $school_bell_hour) { // Hour is not matched
+			continue;
+		}
+
+		$school_bell_dom = (int)$school_bell['dom'];
+		$current_dom = (int)date('j', $current_timestamp);
+
+		if ($school_bell_dom != -1 || $current_dom != $school_bell_dom) { // Day of the month is not matched
+			continue;
+		}
+
+		$school_bell_mon = (int)$school_bell['mon'];
+		$current_mon = (int)date('n', $current_timestamp);
+
+		if ($school_bell_mon != -1 || $current_mon != $school_bell_mon) { // Month is not matched
+			continue;
+		}
+
+		$school_bell_dow = (int)$school_bell['dow'];
+		$current_dow = (int)date('w', $current_timestamp);
+
+		if ($school_bell_dow != -1 || $current_dow != $school_bell_dow) { // Day of the week is not matched
+			continue;
+		}
+
+		// We got our signal!
+		$school_bell_ring_timeout = (int)$school_bell['ring_timeout'];
+		if ($school_bell_ring_timeout > 60) {
+			$school_bell_ring_timeout = ($school_bell['min'] == "-1") ? 55: $school_bell_ring_timeout;
+		}
+
+		$school_bell_ring_timeout = ($school_bell_ring_timeout == 0) ? 5 : $school_bell_ring_timeout;
+
+		$switch_cmd = "bgapi ";
+		$switch_cmd .= "originate {ignore_early_media=true,";
+		$switch_cmd .= "hangup_after_bridge=true,";
+		$switch_cmd .= "domain_name=".$school_bell['context'].",";
+		$switch_cmd .= "domain_uuid=".$school_bell['domain_uuid'].",";
+		$switch_cmd .= "call_timeout=".$school_bell_ring_timeout."}";
+		$switch_cmd .= "loopback/".$school_bell['extension']."/".$school_bell['context'];
+		$switch_cmd .= " &playback(".$school_bell['full_path'].")";
+		
+		event_socket_request($freeswitch_event_socket, $switch_cmd);
+
+	}
+
+?>