You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vcl.apache.org by jf...@apache.org on 2014/09/11 18:01:49 UTC
svn commit: r1624325 [7/13] - in /vcl/trunk/web: ./ .ht-inc/
.ht-inc/authmethods/ css/ js/ js/resources/
Added: vcl/trunk/web/.ht-inc/resource.php
URL: http://svn.apache.org/viewvc/vcl/trunk/web/.ht-inc/resource.php?rev=1624325&view=auto
==============================================================================
--- vcl/trunk/web/.ht-inc/resource.php (added)
+++ vcl/trunk/web/.ht-inc/resource.php Thu Sep 11 16:01:48 2014
@@ -0,0 +1,1640 @@
+<?php
+/*
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn resource($type)
+///
+/// \param $type - type of resource
+///
+/// \brief wrapper to create appropriate object and call selectionText for that
+/// object
+///
+////////////////////////////////////////////////////////////////////////////////
+function resource($type) {
+ switch($type) {
+ case 'config':
+ $obj = new Config();
+ break;
+ case 'image':
+ $obj = new Image();
+ break;
+ case 'computer':
+ $obj = new Computer();
+ break;
+ case 'managementnode':
+ $obj = new ManagementNode();
+ break;
+ case 'schedule':
+ $obj = new Schedule();
+ break;
+ }
+
+ $html = $obj->selectionText();
+ print $html;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \class Resource
+///
+/// \brief base class for all resources; provides functionality useful to all
+/// types of resources
+///
+////////////////////////////////////////////////////////////////////////////////
+class Resource {
+ var $restype;
+ var $restypename;
+ var $hasmapping;
+ var $maptype;
+ var $maptypename;
+ var $basecdata;
+ var $defaultGetDataArgs;
+ var $deletable;
+ var $deletetoggled;
+ var $errmsg;
+ var $namefield;
+ var $noadd;
+ var $jsondata;
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn __construct()
+ ///
+ /// \brief class construstor
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function __construct() {
+ # defines if resource type is mapped to another type
+ $this->hasmapping = 0;
+ # type of resource this resource maps to
+ $this->maptype = '';
+ # display name for $this->maptype
+ $this->maptypename = '';
+ # can this resource type be deleted
+ $this->deletable = 1;
+ # can this resource type be flagged as deleted
+ $this->deletetoggled = 1;
+ # array of arguments and default values that should be passed to getData function
+ $this->defaultGetDataArgs = array();
+ # base data for continuations
+ $this->basecdata = array('obj' => $this);
+ # field in database table used for the name of this resource type
+ $this->namefield = 'name';
+ # can this resource have new resources directly added
+ $this->addable = 1;
+ # base data for sending JSON response to AJAX call; this allows an
+ # inheriting function to set some additional data before calling base
+ # function
+ $this->jsondata = array();
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn getData($args)
+ ///
+ /// \param $args - array of arguments that determine what data gets returned
+ ///
+ /// \return empty array
+ ///
+ /// \brief stub function; each inheriting class should implement this
+ /// function
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function getData($args) {
+ return array();
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn selectionText()
+ ///
+ /// \brief generates HTML to select what management function to perform
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function selectionText() {
+ global $user;
+ # get a count of resources user can administer
+ $tmp = getUserResources(array("{$this->restype}Admin"), array("administer"));
+ $resAdminCnt = count($tmp[$this->restype]);
+
+ # get a count of resources user has access to
+ $tmp = getUserResources(array("{$this->restype}Admin"), array("available"));
+ $resCnt = count($tmp[$this->restype]);
+
+ # get a count of resource groups user can manage
+ $tmp = getUserResources(array("{$this->restype}Admin"), array("manageGroup"), 1);
+ $resGroupCnt = count($tmp[$this->restype]);
+
+ if($this->hasmapping) {
+ # get a count of $restype groups and $maptype groups user can map
+ $tmp = getUserResources(array("{$this->restype}Admin"), array("manageMapping"), 1);
+ $resMapCnt = count($tmp[$this->restype]);
+ $tmp = getUserResources(array("{$this->maptype}Admin"), array("manageMapping"), 1);
+ $maptypeMapCnt = count($tmp[$this->maptype]);
+ }
+ else {
+ $resMapCnt = 0;
+ $maptypeMapCnt = 0;
+ }
+
+ $h = '';
+
+ $h .= "<H2>Manage {$this->restypename}s</H2>\n";
+ $h .= "<FORM action=\"" . BASEURL . SCRIPT . "\" method=post>\n";
+ $showsubmit = 0;
+ if(in_array("{$this->restype}Admin", $user["privileges"]) &&
+ ($this->addable == 1 || $resAdminCnt)) {
+ $cont = addContinuationsEntry("viewResources", $this->basecdata);
+ $h .= "<INPUT type=radio name=continuation value=\"$cont\" checked ";
+ $h .= "id=\"{$this->restype}edit\"><label for=\"{$this->restype}edit\">Edit ";
+ $h .= "{$this->restypename} Profiles</label><br>\n";
+ $showsubmit = 1;
+ }
+
+ if(($resAdminCnt && $resGroupCnt) || ($resMapCnt && $maptypeMapCnt)) {
+ if($this->hasmapping)
+ $label = "Edit Grouping & Mapping";
+ else
+ $label = "Edit Grouping";
+ $cont = addContinuationsEntry("groupMapHTML", $this->basecdata);
+ $h .= "<INPUT type=radio name=continuation value=\"$cont\" id=\"";
+ $h .= "resgroupmap\"><label for=\"resgroupmap\">$label</label><br>\n";
+ $showsubmit = 1;
+ }
+
+ if($resAdminCnt)
+ $h .= $this->extraSelectAdminOptions();
+
+ if($showsubmit)
+ $h .= "<br><INPUT type=submit value=Submit>\n";
+ else
+ $h .= "You don't have access to manage any {$this->restype}s.<br>\n";
+ $h .= "</FORM>\n";
+
+ return $h;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn viewResources()
+ ///
+ /// \brief prints a page to view resource information
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function viewResources() {
+ global $user, $mode;
+ $h = '';
+ $h .= "<h2>{$this->restypename} Profiles</h2>\n";
+
+ $resdata = $this->getData($this->defaultGetDataArgs);
+ if(! empty($resdata)) {
+ $tmp = array_keys($resdata);
+ $testid = $tmp[0];
+ $fields = array_keys($resdata[$testid]);
+ }
+
+ # hidden elements
+ $cdata = $this->basecdata;
+ $cdata['add'] = 1;
+ $cont = addContinuationsEntry('AJsaveResource', $cdata);
+ $h .= "<input type=\"hidden\" id=\"addresourcecont\" value=\"$cont\">\n";
+ if(! empty($resdata)) {
+ $h .= "<input type=\"hidden\" id=\"saveresourcecont\">\n";
+ $cont = addContinuationsEntry('AJeditResource', $this->basecdata);
+ $h .= "<input type=\"hidden\" id=\"editresourcecont\" value=\"$cont\">\n";
+ if($this->deletable) {
+ $cont = addContinuationsEntry('AJpromptToggleDeleteResource', $this->basecdata);
+ $h .= "<input type=\"hidden\" id=\"deleteresourcecont\" value=\"$cont\">\n";
+ }
+ $cont = addContinuationsEntry('jsonResourceStore', $this->basecdata);
+ $h .= "<div dojoType=\"dojo.data.ItemFileWriteStore\" url=\"" . BASEURL;
+ $h .= SCRIPT . "?continuation=$cont\" jsid=\"resourcestore\" ";
+ $h .= "comparatorMap=\"\{\}\"></div>\n";
+ /*$h .= "<div dojoType=\"dojo.data.ItemFileWriteStore\"\n";
+ $h .= "data=\"{'identifier':'id', 'label':'name', 'items':[]}\" \n";
+ $h .= "jsid=\"affiliationstore\"></div>\n";
+ $h .= "<div dojoType=\"dojo.data.ItemFileWriteStore\"\n";
+ $h .= "data=\"{'identifier':'id', 'label':'name', 'items':[]}\" \n";
+ $h .= "jsid=\"ownerstore\"></div>\n";
+ $h .= "<div dojoType=\"dojo.data.ItemFileWriteStore\"\n";
+ $h .= "data=\"{'identifier':'id', 'label':'name', 'items':[]}\" \n";
+ $h .= "jsid=\"editgroupstore\"></div>\n";*/
+ }
+
+ if($this->addable)
+ $h .= dijitButton('', "Add New {$this->restypename}", "addNewResource('Add {$this->restypename}');");
+
+ if(empty($resdata)) {
+ $h .= "<br><br>(No {$this->restypename}s found to which you have access.)\n";
+ $cont = addContinuationsEntry("viewResources", $this->basecdata);
+ $url = BASEURL . SCRIPT . "?continuation=$cont";
+ $h .= "<input type=\"hidden\" id=\"reloadpageurl\" value=\"$url\">\n";
+ }
+
+ $h .= $this->addEditDialogHTML(0);
+
+ if(empty($resdata)) {
+ print $h;
+ return;
+ }
+
+ # filters
+ $h .= "<div dojoType=\"dijit.TitlePane\" title=\"Filters (click to expand)\" ";
+ $h .= "open=\"false\">\n";
+ $h .= "<span id=\"namefilter\">\n";
+ $h .= "<strong>Name</strong>:\n";
+ $h .= "<div dojoType=\"dijit.form.TextBox\" id=\"namefilter\" length=\"80\">";
+ $h .= " <script type=\"dojo/connect\" event=\"onKeyUp\" args=\"event\">\n";
+ $h .= " if(event.keyCode == 13) resource.GridFilter();\n";
+ $h .= " </script>\n";
+ $h .= "</div>\n";
+
+ $h .= dijitButton('', "Apply Name Filter", "resource.GridFilter();");
+ $h .= "<br>\n";
+
+ $h .= "</span>\n"; # namefilter
+ $h .= "<strong>Displayed Fields</strong>:<br>\n";
+ $h .= $this->addDisplayCheckboxes($fields, $resdata[$testid]);
+ if($this->deletetoggled) {
+ $h .= "<label for=\"showdeleted\"><strong>Include Deleted ";
+ $h .= "{$this->restypename}s:</strong>:</label>\n";
+ $h .= "<input type=\"checkbox\" dojoType=\"dijit.form.CheckBox\" ";
+ $h .= "id=\"showdeleted\" onChange=\"resource.GridFilter();\">\n";
+ }
+ $h .= "</div>\n";
+
+ $h .= $this->extraResourceFilters();
+
+ $h .= "<div id=\"gridcontainer\">\n";
+ $h .= "<table dojoType=\"dojox.grid.DataGrid\" jsId=\"resourcegrid\" ";
+ $h .= "sortInfo=3 store=\"resourcestore\" autoWidth=\"true\" style=\"";
+ #$h .= "height: 580px;\" query=\"{type: new RegExp('normal|federated|courseroll')}\">\n";
+ if($this->deletetoggled)
+ $h .= "height: 580px;\" query=\"{deleted: '0'}\">\n";
+ else
+ $h .= "height: 580px;\">\n";
+ $h .= "<thead>\n";
+ $h .= "<tr>\n";
+ if(preg_match('/MSIE/i', $_SERVER['HTTP_USER_AGENT']))
+ $w = array('64px', '38px', '200px', '142px', '65px', '142px', '59px', '58px', '63px', '73px');
+ else
+ $w = array('5em', '3em', '17em', '12em', '5em', '12em', '5em', '5em', '5.6em', '6.3em');
+ $h .= "<th field=\"id\" id=\"delcolth\" width=\"{$w[0]}\" formatter=\"resource.DeleteBtn\" styles=\"text-align: center;\"> </th>\n";
+ $h .= "<th field=\"id\" width=\"{$w[1]}\" formatter=\"resource.EditBtn\" styles=\"text-align: center;\"> </th>\n";
+ $h .= "<th field=\"name\" width=\"{$w[2]}\">Name</th>\n";
+ $h .= "<th field=\"owner\" width=\"{$w[3]}\">Owner</th>\n";
+ foreach($fields as $field) {
+ if($field == $this->namefield ||
+ $field == 'name' ||
+ $field == 'owner' ||
+ is_array($resdata[$testid][$field]) ||
+ preg_match('/id$/', $field))
+ continue;
+ $h .= "<th field=\"$field\" hidden=\"true\" formatter=\"resource.colformatter\">";
+ $h .= $this->fieldDisplayName($field);
+ $h .= "</th>\n";
+ }
+ $h .= "</tr>\n";
+ $h .= "</thead>\n";
+ $h .= "</table>\n";
+ $h .= "</div>\n";
+
+ if($this->deletable) {
+ # toggle delete dialog
+ $h .= "<div id=\"toggleDeleteDialog\" dojoType=\"dijit.Dialog\">\n";
+ $h .= "<h2 id=\"toggleDeleteHeading\"></h2>\n";
+ $h .= "<span id=\"toggleDeleteQuestion\"></span><br>\n";
+ $h .= "<div id=\"confdelrescontent\"></div>\n";
+ $h .= dijitButton('toggleDeleteBtn', "Delete {$this->restypename}", "submitToggleDeleteResource();");
+ $h .= dijitButton('', "Cancel", "clearHideConfirmDelete();");
+ $h .= "<input type=hidden id=\"submitdeletecont\">\n";
+ $h .= "</div>\n";
+ }
+
+ print $h;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn addDisplayCheckboxes($allfields, $sample)
+ ///
+ /// \param $allfields - array of fields for which to generate checkboxes
+ /// \param $sample - sample data item that is used to determine what fields
+ /// to use for generating checkboxes
+ ///
+ /// \return html
+ ///
+ /// \brief generates checkboxes to be used as filters on the viewResources
+ /// page
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function addDisplayCheckboxes($allfields, $sample) {
+ $fields = array('owner');
+ foreach($allfields as $field) {
+ if($field == $this->namefield ||
+ $field == 'name' ||
+ $field == 'owner' ||
+ is_array($sample[$field]) ||
+ preg_match('/id$/', $field))
+ continue;
+ $fields[] = $field;
+ }
+ $h = '';
+ $fieldcnt = count($fields);
+ $cols = $fieldcnt / 4;
+ if($cols > 4)
+ $cols = 4;
+ if($fieldcnt < 6) {
+ foreach($fields as $field) {
+ if($field == 'name' || $field == 'owner')
+ $h .= "<input type=checkbox id=chk$field checked onClick=\"resource.toggleResFieldDisplay(this, '$field')\">";
+ else
+ $h .= "<input type=checkbox id=chk$field onClick=\"resource.toggleResFieldDisplay(this, '$field')\">";
+ $h .= "<label for=chk$field>";
+ $h .= $this->fieldDisplayName($field);
+ $h .= "</label><br>\n";
+ }
+ }
+ else {
+ $h .= "<table>\n";
+ $cnt = 0;
+ foreach($fields as $field) {
+ $mod = $cols;
+ if($cnt % $mod == 0)
+ $h .= "<tr>\n";
+ if($field == 'name' || $field == 'owner')
+ $h .= " <td><input type=checkbox id=chk$field checked onClick=\"resource.toggleResFieldDisplay(this, '$field')\">";
+ else
+ $h .= " <td><input type=checkbox id=chk$field onClick=\"resource.toggleResFieldDisplay(this, '$field')\">";
+ $h .= "<label for=chk$field>";
+ $h .= $this->fieldDisplayName($field);
+ $h .= "</label><br>\n";
+ $cnt++;
+ if($cnt % $mod == 0)
+ $h .= "</tr>\n";
+ }
+ if($cnt % $mod != 0)
+ $h .= "</tr>\n";
+ $h .= "</table>\n";
+ }
+ return $h;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn fieldDisplayName($field)
+ ///
+ /// \param $field - name of a resource field
+ ///
+ /// \return display value for $field
+ ///
+ /// \brief generates the display value for $field; this base function just
+ /// uppercases the first letter; each inheriting class should create its own
+ /// function
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function fieldDisplayName($field) {
+ return ucfirst($field);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn extraResourceFilters()
+ ///
+ /// \return empty string
+ ///
+ /// \brief base function; allows inheriting classes to generate additional
+ /// filters to be displayed on the viewResources page
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function extraResourceFilters() {
+ return '';
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn jsonResourceStore()
+ ///
+ /// \brief generates and sends a JSON formatted store of resource data
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function jsonResourceStore() {
+ global $user;
+ $args = $this->defaultGetDataArgs;
+ $args['includedeleted'] = 1;
+ $resdata = $this->getData($args);
+ $resources = getUserResources(array($this->restype . "Admin"), array("administer"), 0, 1);
+ foreach($resources as $type => $tmp) {
+ if($type != $this->restype)
+ unset($resources[$type]);
+ }
+
+
+ // this method may include fields for some records but not others
+ /*$items = array();
+ foreach($resdata as $id => $res) {
+ if(! array_key_exists($id, $resources[$this->restype]))
+ continue;
+ $g = array('id' => $id);
+ $g['name'] = $res[$this->namefield];
+ $g['owner'] = $res['owner'];
+ foreach($res as $key => $val) {
+ if($key == 'name' ||
+ $key == 'owner' ||
+ $key == $this->namefield ||
+ is_array($val) ||
+ preg_match('/id$/', $key))
+ continue;
+ $g[$key] = $val;
+ }
+ $items[] = $g;
+ }
+ return $items;*/
+
+
+
+ // this method only includes keys that exist in the first element
+ reset($resdata);
+ $id = key($resdata);
+ $fields = array_keys($resdata[$id]);
+ $items = array();
+ foreach($resdata as $id => $res) {
+ if(! array_key_exists($id, $resources[$this->restype]))
+ continue;
+ $item = array('id' => $id);
+ $item['name'] = $res[$this->namefield];
+ $item['owner'] = $res['owner'];
+ foreach($fields as $field) {
+ if($field == 'name' ||
+ $field == 'owner' ||
+ $field == $this->namefield ||
+ ! array_key_exists($field, $res) ||
+ is_array($res[$field]) ||
+ preg_match('/id$/', $field))
+ continue;
+ $item[$field] = $res[$field];
+ }
+ $items[] = $item;
+ unset($resdata[$id]);
+ }
+ sendJSON($items, 'id');
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn toggleDeleteResource($rscid)
+ ///
+ /// \param $rscid - id of a resource (from table specific to that resource,
+ /// not from the resource table)
+ ///
+ /// \return 1 on success, 0 on failure
+ ///
+ /// \brief if resource type allows resources to be flagged as deleted;
+ /// toggles the deleted flag; otherwise deletes the entry from that resources
+ /// table and the general resource table
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function toggleDeleteResource($rscid) {
+ if($this->deletetoggled) {
+ $query = "SELECT deleted "
+ . "FROM `{$this->restype}` "
+ . "WHERE id = $rscid";
+ $qh = doQuery($query);
+ if($row = mysql_fetch_assoc($qh)) {
+ $newval = (int)(! (int)$row['deleted']);
+ $query = "UPDATE {$this->restype} "
+ . "SET deleted = $newval "
+ . "WHERE id = $rscid";
+ doQuery($query);
+ $this->submitToggleDeleteResourceExtra($rscid, $row['deleted']);
+ }
+ else
+ return 0;
+ }
+ else {
+ $query = "DELETE r "
+ . "FROM resource r, "
+ . "resourcetype rt "
+ . "WHERE r.resourcetypeid = rt.id AND "
+ . "rt.name = '{$this->restype}' AND "
+ . "r.subid = $rscid";
+ doQuery($query);
+ $query = "DELETE FROM `{$this->restype}` "
+ . "WHERE id = $rscid";
+ doQuery($query);
+
+ $this->submitToggleDeleteResourceExtra($rscid);
+ }
+
+ # clear user resource cache for this type
+ $key = getKey(array(array($this->restype . "Admin"), array("administer"), 0, 1, 0));
+ unset($_SESSION['userresources'][$key]);
+ $key = getKey(array(array($this->restype . "Admin"), array("administer"), 0, 0, 0));
+ unset($_SESSION['userresources'][$key]);
+
+ return 1;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn AJpromptToggleDeleteResource()
+ ///
+ /// \brief generates and sends content prompting user to confirm deletion of
+ /// resource
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function AJpromptToggleDeleteResource() {
+ $rscid = processInputVar('rscid', ARG_NUMERIC);
+ # check access to $rscid
+ $resources = getUserResources(array("{$this->restype}Admin"), array("administer"), 0, 1);
+ if(! array_key_exists($rscid, $resources[$this->restype])) {
+ $type = strtolower($this->restypename);
+ $rt = array('status' => 'noaccess',
+ 'msg' => "You do not have access to delete the selected $type.",
+ 'rscid' => $rscid);
+ sendJSON($rt);
+ return;
+ }
+ $rt = array('html' => '',
+ 'title' => "Confirm Delete {$this->restypename}",
+ 'question' => "Delete the following {$this->restype}?",
+ 'btntxt' => "Delete {$this->restypename}",
+ 'status' => 'success');
+ $args = $this->defaultGetDataArgs;
+ if($this->deletetoggled)
+ $args['includedeleted'] = 1;
+ $args['rscid'] = $rscid;
+ $resdata = $this->getData($args);
+ if($this->deletetoggled && $resdata[$rscid]['deleted']) {
+ $rt['title'] = "Confirm Undelete {$this->restypename}";
+ $rt['question'] = "Undelete the following {$this->restype}?";
+ $rt['btntxt'] = "Undelete {$this->restypename}";
+ }
+ $fields = array_keys($resdata[$rscid]);
+ $rt['html'] .= "<table>";
+ $rt['html'] .= "<tr><th>Name:</th><td>{$resdata[$rscid][$this->namefield]}</td></tr>";
+ $rt['html'] .= "<tr><th>Owner:</th><td>{$resdata[$rscid]['owner']}</td></tr>";
+ foreach($fields as $field) {
+ if($field == $this->namefield ||
+ $field == 'name' ||
+ $field == 'owner' ||
+ is_array($resdata[$rscid][$field]) ||
+ preg_match('/id$/', $field))
+ continue;
+ $rt['html'] .= "<tr><th>";
+ $rt['html'] .= ucfirst($field);
+ $rt['html'] .= ":</th><td>{$resdata[$rscid][$field]}</td></tr>";
+ }
+ $rt['html'] .= "</table>";
+ $rt['html'] .= $this->toggleDeleteResourceExtra();
+
+ $cdata = getContinuationVar();
+ $cdata['rscid'] = $rscid;
+ $cont = addContinuationsEntry('AJsubmitToggleDeleteResource', $cdata);
+ $rt['cont'] = $cont;
+ sendJSON($rt);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn toggleDeleteResourceExtra()
+ ///
+ /// \return empty string
+ ///
+ /// \brief allows inheriting class to generate additional information to be
+ /// included on the confirm toggle delete resource page
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function toggleDeleteResourceExtra() {
+ return '';
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn AJsubmitToggleDeleteResource()
+ ///
+ /// \brief AJAX callable wrapper for toggleDeleteResource
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function AJsubmitToggleDeleteResource() {
+ $rscid = getContinuationVar('rscid');
+ if($this->toggleDeleteResource($rscid))
+ $rt = array('status' => 'success', 'rscid' => $rscid);
+ else
+ $rt = array('status' => 'failed', 'rscid' => $rscid);
+ sendJSON($rt);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn submitToggleDeleteResourceExtra($rscid, $deleted)
+ ///
+ /// \param $rscid - id of a resource (from table specific to that resource,
+ /// not from the resource table)
+ /// \param $deleted - (optional, default=0) 1 if resource was previously
+ /// deleted; 0 if not
+ ///
+ /// \brief function to do any extra stuff specific to a resource type when
+ /// toggling delete for a resource; to be implemented by inheriting class if
+ /// needed
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function submitToggleDeleteResourceExtra($rscid, $deleted=0) {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn groupMapHTML()
+ ///
+ /// \brief prints HTML for groupping and mapping page
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function groupMapHTML() {
+ $h = '';
+ $h .= "<div dojoType=\"dojo.data.ItemFileWriteStore\" jsId=\"resourcetogroupsstore\" ";
+ $h .= "data=\"resourcetogroupsdata\"></div>\n";
+ $h .= "<div dojoType=\"dojo.data.ItemFileWriteStore\" jsId=\"grouptoresourcesstore\" ";
+ $h .= "data=\"grouptoresourcesdata\"></div>\n";
+ $h .= "<div dojoType=\"dojo.data.ItemFileWriteStore\" jsId=\"mapbyresgroupstore\" ";
+ $h .= "data=\"mapbyresgroupdata\"></div>\n";
+ $h .= "<div dojoType=\"dojo.data.ItemFileWriteStore\" jsId=\"mapbymaptogroupstore\" ";
+ $h .= "data=\"mapbymaptogroupdata\"></div>\n";
+ $h .= "<div id=\"mainTabContainer\" dojoType=\"dijit.layout.TabContainer\"\n";
+ $h .= " style=\"width:600px;height:600px\">\n";
+ $h .= $this->groupByResourceHTML();
+ $h .= $this->groupByGroupHTML();
+ if($this->hasmapping) {
+ $h .= "<input type=\"hidden\" id=\"domapping\" value=\"1\">\n";
+ $h .= $this->mapByResGroupHTML();
+ $h .= $this->mapByMapToGroupHTML();
+ }
+ else
+ $h .= "<input type=\"hidden\" id=\"domapping\" value=\"0\">\n";
+ $h .= "</div>\n";
+ print $h;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn groupByResourceHTML()
+ ///
+ /// \return html
+ ///
+ /// \brief generates HTML for resource grouping by selecting a resource
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function groupByResourceHTML() {
+ # build list of resources
+ $tmp = getUserResources(array($this->restype . "Admin"), array('manageGroup'));
+ if(empty($tmp[$this->restype]))
+ return '';
+ $resources = $tmp[$this->restype];
+ uasort($resources, 'sortKeepIndex');
+ $h = '';
+ $h .= "<div id=\"groupbyresourcediv\" dojoType=\"dijit.layout.ContentPane\" title=\"Group By {$this->restypename}\">\n";
+ $h .= "<div id=\"groupbyresourcedesc\">\n";
+ $h .= "Select an item from the drop-down box and click \"Get Groups\" ";
+ $h .= "to see<br>all of the groups it is in. Then, select a group it ";
+ $h .= "is in and click the Remove<br>button to remove it from that group, ";
+ $h .= "or select a group it is not in and click<br>the Add button to ";
+ $h .= "add it to that group.<br><br>\n";
+ $h .= "</div>\n"; # groupbyresourcedesc
+ $h .= "<div id=\"groupbyresourcesel\">\n";
+ $h .= "{$this->restypename}:<select id=\"resources\">\n";
+ foreach($resources as $id => $res)
+ $h .= "<option value=$id>$res</option>\n";
+ $h .= "</select>\n";
+ $h .= dijitButton('fetchGrpsButton', "Get Groups",
+ "populateLists('resources', 'ingroups', 'inresourcename', 'outresourcename', 'resgroupinggroupscont');");
+ $h .= "</div>\n"; # groupbyresourcesel
+ $h .= "<table><tbody><tr>\n";
+ # select for groups resource is in
+ $h .= "<td valign=top>\n";
+ $h .= "Groups <span style=\"font-weight: bold;\" id=\"inresourcename\"></span> is in:<br>\n";
+ $h .= "<table dojoType=\"dojox.grid.DataGrid\" jsId=\"ingroups\" ";
+ $h .= "store=\"resourcetogroupsstore\" style=\"width: 240px; height: 250px;\" query=\"{inout: 1}\" ";
+ $h .= "selectionMode=\"extended\">\n";
+ $h .= "<thead>\n";
+ $h .= "<tr>\n";
+ $h .= "<th field=\"name\" width=\"160px\"></th>\n";
+ $h .= "</tr>\n";
+ $h .= "</thead>\n";
+ $h .= "</table>\n";
+ $h .= "</td>\n";
+ # transfer buttons
+ $h .= "<td style=\"vertical-align: middle;\">\n";
+ $h .= dijitButton('', "<div style=\"width: 50px;\"><-Add</div>", "resource.addRemItem('addgrpcont', 'resources', 'outgroups');");
+ $cdata = $this->basecdata;
+ $cdata['mode'] = 'add';
+ $cont = addContinuationsEntry('AJaddRemGroupResource', $cdata);
+ $h .= "<input type=\"hidden\" id=\"addgrpcont\" value=\"$cont\">\n";
+ $h .= "<br><br><br>\n";
+ $h .= dijitButton('', "<div style=\"width: 50px;\">Remove-></div>", "resource.addRemItem('remgrpcont', 'resources', 'ingroups');");
+ $cdata['mode'] = 'remove';
+ $cont = addContinuationsEntry('AJaddRemGroupResource', $cdata);
+ $h .= "<input type=\"hidden\" id=\"remgrpcont\" value=\"$cont\">\n";
+ $h .= "</td>\n";
+ # select for groups resource is not in
+ $h .= "<td valign=top>\n";
+ $h .= "Groups <span style=\"font-weight: bold;\" id=\"outresourcename\"></span> is not in:<br>\n";
+ $h .= "<table dojoType=\"dojox.grid.DataGrid\" jsId=\"outgroups\" ";
+ $h .= "store=\"resourcetogroupsstore\" style=\"width: 240px; height: 250px;\" query=\"{inout: 1}\" ";
+ $h .= "selectionMode=\"extended\">\n";
+ $h .= "<thead>\n";
+ $h .= "<tr>\n";
+ $h .= "<th field=\"name\" width=\"160px\"></th>\n";
+ $h .= "</tr>\n";
+ $h .= "</thead>\n";
+ $h .= "</table>\n";
+ $h .= "</td>\n";
+ $h .= "</tr></tbody></table>\n";
+ $cdata = $this->basecdata;
+ $cdata['store'] = 'resourcetogroupsstore';
+ $cdata['intitle'] = 'ingroups';
+ $cdata['outtitle'] = 'outgroups';
+ $cont = addContinuationsEntry('jsonResourceGroupingGroups', $cdata);
+ $h .= "<input type=hidden id=\"resgroupinggroupscont\" value=\"$cont\">\n";
+ $h .= "</div>\n";
+ return $h;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn jsonResourceGroupingGroups()
+ ///
+ /// \brief sends JSON of resource groups for resource grouping by selecting a
+ /// resource page
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function jsonResourceGroupingGroups() {
+ $resid = processInputVar('id', ARG_NUMERIC);
+ $resources = getUserResources(array($this->restype . "Admin"), array("manageGroup"));
+ if(! array_key_exists($resid, $resources[$this->restype])) {
+ sendJSON(array('status' => 'noaccess'));
+ return;
+ }
+ $groups = getUserResources(array($this->restype . 'Admin'), array('manageGroup'), 1);
+ $memberships = getResourceGroupMemberships($this->restype);
+ $all = array();
+ foreach($groups[$this->restype] as $id => $group) {
+ if(array_key_exists($resid, $memberships[$this->restype]) &&
+ in_array($id, $memberships[$this->restype][$resid]))
+ $all[] = array('id' => $id, 'name' => $group, 'inout' => 1);
+ else
+ $all[] = array('id' => $id, 'name' => $group, 'inout' => 0);
+ }
+ $arr = array('items' => $all,
+ 'intitle' => getContinuationVar('intitle'),
+ 'outtitle' => getContinuationVar('outtitle'));
+ sendJSON($arr);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn AJaddRemGroupResource()
+ ///
+ /// \brief adds or removes groups for a resource and sends JSON response
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function AJaddRemGroupResource() {
+ $rscid = processInputVar('id', ARG_NUMERIC);
+ $resources = getUserResources(array($this->restype . "Admin"), array("manageGroup"));
+ if(! array_key_exists($rscid, $resources[$this->restype])) {
+ $arr = array('status' => 'noaccess');
+ sendJSON($arr);
+ return;
+ }
+
+ $groups = getUserResources(array($this->restype . "Admin"), array("manageGroup"), 1);
+ $tmp = processInputVar('listids', ARG_STRING);
+ $tmp = explode(',', $tmp);
+ $groupids = array();
+ foreach($tmp as $id) {
+ if(! is_numeric($id))
+ continue;
+ if(! array_key_exists($id, $groups[$this->restype])) {
+ $arr = array('status' => 'noaccess');
+ sendJSON($arr);
+ return;
+ }
+ $groupids[] = $id;
+ }
+
+ $mode = getContinuationVar('mode');
+
+ $args = $this->defaultGetDataArgs;
+ $args['rscid'] = $rscid;
+ $resdata = $this->getData($args);
+
+ if($mode == 'add') {
+ $adds = array();
+ foreach($groupids as $id)
+ $adds[] = "({$resdata[$rscid]['resourceid']}, $id)";
+ $query = "INSERT IGNORE INTO resourcegroupmembers "
+ . "(resourceid, resourcegroupid) VALUES ";
+ $query .= implode(',', $adds);
+ doQuery($query);
+ }
+ else {
+ $rems = implode(',', $groupids);
+ $query = "DELETE FROM resourcegroupmembers "
+ . "WHERE resourceid = {$resdata[$rscid]['resourceid']} AND "
+ . "resourcegroupid IN ($rems)";
+ doQuery($query);
+ }
+
+ $_SESSION['userresources'] = array();
+ $regids = "^" . implode('$|^', $groupids) . "$";
+ $arr = array('status' => 'success',
+ 'regids' => $regids,
+ 'inselobj' => 'ingroups',
+ 'outselobj' => 'outgroups');
+ sendJSON($arr);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn groupByGroupHTML()
+ ///
+ /// \return html
+ ///
+ /// \brief generates HTML for resource grouping by selecting a resource group
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function groupByGroupHTML() {
+ $resources = getUserResources(array($this->restype . 'Admin'), array('manageGroup'));
+ if(empty($resources[$this->restype]))
+ return '';
+ $h = '';
+ $h .= "<div id=\"groupbygroupdiv\" dojoType=\"dijit.layout.ContentPane\" title=\"Group By Group\">\n";
+ $h .= "Select a group from the drop-down box and click \"Get {$this->restypename}s\"<br>";
+ $h .= "to see all of the resources in it. Then, select a resource in it and click the<br>";
+ $h .= "Remove button to remove it from that group, or select a resource that is not ";
+ $h .= "<br>in it and click the Add button to add it to that group.<br><br>\n";
+ $h .= "Group:<select id=\"resgroups\">\n";
+ # build list of groups
+ $tmp = getUserResources(array($this->restype . "Admin"), array('manageGroup'), 1);
+ $groups = $tmp[$this->restype];
+ uasort($groups, 'sortKeepIndex');
+ foreach($groups as $id => $group)
+ $h .= "<option value=$id>$group</option>\n";
+ $h .= "</select>\n";
+ $h .= dijitButton('fetchResourcesButton', "Get {$this->restypename}s",
+ "populateLists('resgroups', 'inresources', 'ingroupname', 'outgroupname', 'resgroupingresourcescont');");
+ $h .= "<table><tbody><tr>\n";
+ # select for resources in group
+ $h .= "<td valign=top>\n";
+ $h .= "{$this->restypename}s in <span style=\"font-weight: bold;\" id=\"ingroupname\"></span>:<br>\n";
+ $h .= "<table dojoType=\"dojox.grid.DataGrid\" jsId=\"inresources\" ";
+ $h .= "store=\"grouptoresourcesstore\" style=\"width: 240px; height: 250px;\" query=\"{inout: 1}\" ";
+ $h .= "selectionMode=\"extended\" sortInfo=\"1\">\n";
+ $h .= "<thead>\n";
+ $h .= "<tr>\n";
+ $h .= "<th field=\"name\" width=\"160px\"></th>\n";
+ $h .= "</tr>\n";
+ $h .= "</thead>\n";
+ $h .= "</table>\n";
+ $h .= "</td>\n";
+ # transfer buttons
+ $h .= "<td style=\"vertical-align: middle;\">\n";
+ $h .= dijitButton('', "<div style=\"width: 50px;\"><-Add</div>", "resource.addRemItem('additemcont', 'resgroups', 'outresources');");
+ $cdata = $this->basecdata;
+ $cdata['mode'] = 'add';
+ $cont = addContinuationsEntry('AJaddRemResourceGroup', $cdata);
+ $h .= "<input type=\"hidden\" id=\"additemcont\" value=\"$cont\">\n";
+ $h .= "<br><br><br>\n";
+ $h .= dijitButton('', "<div style=\"width: 50px;\">Remove-></div>", "resource.addRemItem('remitemcont', 'resgroups', 'inresources');");
+ $cdata['mode'] = 'remove';
+ $cont = addContinuationsEntry('AJaddRemResourceGroup', $cdata);
+ $h .= "<input type=\"hidden\" id=\"remitemcont\" value=\"$cont\">\n";
+ $h .= "</td>\n";
+ # select for groups resource is not in
+ $h .= "<td valign=top>\n";
+ $h .= "{$this->restypename}s not in <span style=\"font-weight: bold;\" id=\"outgroupname\"></span>:<br>\n";
+ $h .= "<table dojoType=\"dojox.grid.DataGrid\" jsId=\"outresources\" ";
+ $h .= "store=\"grouptoresourcesstore\" style=\"width: 240px; height: 250px;\" query=\"{inout: 1}\" ";
+ $h .= "selectionMode=\"extended\" sortInfo=\"1\">\n";
+ $h .= "<thead>\n";
+ $h .= "<tr>\n";
+ $h .= "<th field=\"name\" width=\"160px\"></th>\n";
+ $h .= "</tr>\n";
+ $h .= "</thead>\n";
+ $h .= "</table>\n";
+ $h .= "</td>\n";
+ $h .= "</tr></tbody></table>\n";
+ $cdata = $this->basecdata;
+ $cdata['store'] = 'grouptoresourcesstore';
+ $cdata['intitle'] = 'inresources';
+ $cdata['outtitle'] = 'outresources';
+ $cont = addContinuationsEntry('jsonResourceGroupingResources', $cdata);
+ $h .= "<input type=hidden id=\"resgroupingresourcescont\" value=\"$cont\">\n";
+ $h .= "</div>\n";
+ return $h;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn jsonResourceGroupingResources()
+ ///
+ /// \brief sends JSON of resources for resource grouping by selecting a
+ /// resource group
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function jsonResourceGroupingResources() {
+ $groupid = processInputVar('id', ARG_NUMERIC);
+ $groups = getUserResources(array($this->restype . "Admin"), array("manageGroup"), 1);
+ if(! array_key_exists($groupid, $groups[$this->restype])) {
+ sendJSON(array('status' => 'noaccess'));
+ return;
+ }
+ $resources = getUserResources(array($this->restype . 'Admin'), array('manageGroup'));
+ #uasort($resources[$this->restype], 'sortKeepIndex');
+ $memberships = getResourceGroupMemberships($this->restype);
+ $all = array();
+ foreach($resources[$this->restype] as $id => $res) {
+ if(array_key_exists($id, $memberships[$this->restype]) &&
+ in_array($groupid, $memberships[$this->restype][$id]))
+ $all[] = array('id' => $id, 'name' => $res, 'inout' => 1);
+ else
+ $all[] = array('id' => $id, 'name' => $res, 'inout' => 0);
+ }
+ $arr = array('items' => $all,
+ 'intitle' => getContinuationVar('intitle'),
+ 'outtitle' => getContinuationVar('outtitle'));
+ sendJSON($arr);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn AJaddRemResourceGroup()
+ ///
+ /// \brief adds or removes resources for a resource group and sends JSON
+ /// response
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function AJaddRemResourceGroup() {
+ $groupid = processInputVar('id', ARG_NUMERIC);
+ $groups = getUserResources(array($this->restype . "Admin"), array("manageGroup"), 1);
+ if(! array_key_exists($groupid, $groups[$this->restype])) {
+ $arr = array('status' => 'noaccess');
+ sendJSON($arr);
+ return;
+ }
+
+ $resources = getUserResources(array($this->restype . "Admin"), array("manageGroup"));
+ $tmp = processInputVar('listids', ARG_STRING);
+ $tmp = explode(',', $tmp);
+ $rscids = array();
+ foreach($tmp as $id) {
+ if(! is_numeric($id))
+ continue;
+ if(! array_key_exists($id, $resources[$this->restype])) {
+ $arr = array('status' => 'noaccess');
+ sendJSON($arr);
+ return;
+ }
+ $rscids[] = $id;
+ }
+
+ $mode = getContinuationVar('mode');
+
+ $resdata = $this->getData($this->defaultGetDataArgs);
+
+ if($mode == 'add') {
+ $adds = array();
+ foreach($rscids as $id)
+ $adds[] = "({$resdata[$id]['resourceid']}, $groupid)";
+ $query = "INSERT IGNORE INTO resourcegroupmembers "
+ . "(resourceid, resourcegroupid) VALUES ";
+ $query .= implode(',', $adds);
+ }
+ else {
+ $delids = array();
+ foreach($rscids as $id)
+ $delids[] = $resdata[$id]['resourceid'];
+ $inlist = implode(',', $delids);
+ $query = "DELETE FROM resourcegroupmembers "
+ . "WHERE resourcegroupid = $groupid AND "
+ . "resourceid IN ($inlist)";
+ doQuery($query);
+ }
+
+ doQuery($query);
+ $_SESSION['userresources'] = array();
+ $regids = "^" . implode('$|^', $rscids) . "$";
+ $arr = array('status' => 'success',
+ 'regids' => $regids,
+ 'inselobj' => 'inresources',
+ 'outselobj' => 'outresources');
+ sendJSON($arr);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn
+ ///
+ /// \brief Resource
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function groupByGridHTML() {
+ # TODO
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn mapByResGroupHTML()
+ ///
+ /// \return html
+ ///
+ /// \brief generates HTML for resource mapping by selecting a resource group
+ /// of this type of resource
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function mapByResGroupHTML() {
+ $tmp = getUserResources(array($this->restype . "Admin"),
+ array("manageMapping"), 1);
+ $groups = $tmp[$this->restype];
+ uasort($groups, "sortKeepIndex");
+ $tmp = getUserResources(array($this->maptype . "Admin"),
+ array("manageMapping"), 1);
+ $mapgroups = $tmp[$this->maptype];
+ uasort($mapgroups, "sortKeepIndex");
+ $h = '';
+
+ if(! count($groups) || ! count($mapgroups)) {
+ $h .= "You don't have access to manage any mappings for this resource ";
+ $h .= "type.<br>\n";
+ return $h;
+ }
+
+ $h .= "<div id=\"mapbyresgroupdiv\" dojoType=\"dijit.layout.ContentPane\" title=\"Map By {$this->restypename} Group\">\n";
+ $h .= "Select an item from the drop-down box and click \"Get {$this->maptypename} Groups\"<br>";
+ $h .= "to see all of the groups it maps to. Then, select a group ";
+ $h .= "it does not map<br>to and click the Add button to map it to that group, ";
+ $h .= "or select a group it<br>maps to and click the Remove ";
+ $h .= "button to unmap it from that group.<br><br>\n";
+ $h .= "{$this->restypename} Group:<select id=\"groups\">\n";
+ foreach($groups as $id => $group)
+ $h .= "<option value=$id>$group</option>\n";
+ $h .= "</select>\n";
+ $h .= dijitButton('', "Get {$this->maptypename} Groups",
+ "populateLists('groups', 'inmapgroups', 'inmapgroupname', 'outmapgroupname', 'mapbyresgroupcont');");
+ $h .= "<table><tbody><tr>\n";
+ # select for groups mapped to
+ $h .= "<td valign=top>\n";
+ $h .= "{$this->maptypename} Groups <span style=\"font-weight: bold;\" id=\"inmapgroupname\"></span> maps to:<br>\n";
+ $h .= "<table dojoType=\"dojox.grid.DataGrid\" jsId=\"inmapgroups\" ";
+ $h .= "store=\"mapbyresgroupstore\" style=\"width: 240px; height: 250px;\" query=\"{inout: 1}\" ";
+ $h .= "selectionMode=\"extended\">\n";
+ $h .= "<thead>\n";
+ $h .= "<tr>\n";
+ $h .= "<th field=\"name\" width=\"160px\"></th>\n";
+ $h .= "</tr>\n";
+ $h .= "</thead>\n";
+ $h .= "</table>\n";
+ $h .= "</td>\n";
+ # transfer buttons
+ $h .= "<td style=\"vertical-align: middle;\">\n";
+ $h .= dijitButton('', "<div style=\"width: 50px;\"><-Add</div>", "resource.addRemItem('addmapgrpcont', 'groups', 'outmapgroups');");
+ $cdata = $this->basecdata;
+ $cdata['mode'] = 'add';
+ $cont = addContinuationsEntry('AJaddRemMapToGroup', $cdata);
+ $h .= "<input type=\"hidden\" id=\"addmapgrpcont\" value=\"$cont\">\n";
+ $h .= "<br>\n";
+ $h .= "<br>\n";
+ $h .= "<br>\n";
+ $h .= dijitButton('', "<div style=\"width: 50px;\">Remove-></div>", "resource.addRemItem('remmapgrpcont', 'groups', 'inmapgroups');");
+ $cdata['mode'] = 'remove';
+ $cont = addContinuationsEntry('AJaddRemMapToGroup', $cdata);
+ $h .= "<input type=\"hidden\" id=\"remmapgrpcont\" value=\"$cont\">\n";
+ $h .= "</td>\n";
+ # select for groups resource is not in
+ $h .= "<td valign=top>\n";
+ $h .= "{$this->maptypename} Groups <span style=\"font-weight: bold;\" id=\"outmapgroupname\"></span> does not map to:<br>\n";
+ $h .= "<table dojoType=\"dojox.grid.DataGrid\" jsId=\"outmapgroups\" ";
+ $h .= "store=\"mapbyresgroupstore\" style=\"width: 240px; height: 250px;\" query=\"{inout: 1}\" ";
+ $h .= "selectionMode=\"extended\">\n";
+ $h .= "<thead>\n";
+ $h .= "<tr>\n";
+ $h .= "<th field=\"name\" width=\"160px\"></th>\n";
+ $h .= "</tr>\n";
+ $h .= "</thead>\n";
+ $h .= "</table>\n";
+ $h .= "</td>\n";
+ $h .= "</tr></tbody></table>\n";
+ $cdata = $this->basecdata;
+ $cdata['store'] = 'mapbyresgroupstore';
+ $cdata['intitle'] = 'inmapgroups';
+ $cdata['outtitle'] = 'outmapgroups';
+ $cont = addContinuationsEntry('jsonResourceMappingMapToGroups', $cdata);
+ $h .= "<input type=hidden id=\"mapbyresgroupcont\" value=\"$cont\">\n";
+ $h .= "</div>\n";
+ return $h;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn jsonResourceMappingMapToGroups()
+ ///
+ /// \brief sends JSON of resource groups for resource mapping by selecting a
+ /// resource group of this resource type
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function jsonResourceMappingMapToGroups() {
+ $resgrpid = processInputVar('id', ARG_NUMERIC);
+ $resources = getUserResources(array($this->restype . "Admin"), array("manageMapping"), 1);
+ if(! array_key_exists($resgrpid, $resources[$this->restype])) {
+ sendJSON(array('status' => 'noaccess'));
+ return;
+ }
+ $mapgroups = getUserResources(array($this->maptype . 'Admin'), array('manageMapping'), 1);
+ $mapping = getResourceMapping($this->restype, $this->maptype);
+ $all = array();
+
+ foreach($mapgroups[$this->maptype] as $id => $group) {
+ if(array_key_exists($resgrpid, $mapping) &&
+ in_array($id, $mapping[$resgrpid]))
+ $all[] = array('id' => $id, 'name' => $group, 'inout' => 1);
+ else
+ $all[] = array('id' => $id, 'name' => $group, 'inout' => 0);
+ }
+ $arr = array('items' => $all,
+ 'intitle' => getContinuationVar('intitle'),
+ 'outtitle' => getContinuationVar('outtitle'));
+ sendJSON($arr);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn AJaddRemMapToGroup()
+ ///
+ /// \brief adds or removes groups that map to a group of this resource type
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function AJaddRemMapToGroup() {
+ $groupid = processInputVar('id', ARG_NUMERIC);
+ $groups = getUserResources(array($this->restype . "Admin"),
+ array("manageMapping"), 1);
+ if(! array_key_exists($groupid, $groups[$this->restype])) {
+ $arr = array('status' => 'noaccess');
+ sendJSON($arr);
+ return;
+ }
+
+ $mapgroups = getUserResources(array($this->maptype . "Admin"),
+ array("manageMapping"), 1);
+ $tmp = processInputVar('listids', ARG_STRING);
+ $tmp = explode(',', $tmp);
+ $mapids = array();
+ foreach($tmp as $id) {
+ if(! is_numeric($id))
+ continue;
+ if(! array_key_exists($id, $mapgroups[$this->maptype])) {
+ $arr = array('status' => 'noaccess');
+ sendJSON($arr);
+ return;
+ }
+ $mapids[] = $id;
+ }
+
+ $mytypeid = getResourceTypeID($this->restype);
+ $maptypeid = getResourceTypeID($this->maptype);
+
+ $mode = getContinuationVar('mode');
+
+ if($mode == 'add') {
+ $adds = array();
+ foreach($mapids as $id)
+ $adds[] = "($groupid, $mytypeid, $id, $maptypeid)";
+ $query = "INSERT IGNORE INTO resourcemap "
+ . "(resourcegroupid1, resourcetypeid1, "
+ . "resourcegroupid2, resourcetypeid2) "
+ . "VALUES ";
+ $query .= implode(',', $adds);
+ doQuery($query);
+ }
+ else {
+ foreach($mapids as $id) {
+ $query = "DELETE FROM resourcemap "
+ . "WHERE resourcegroupid1 = $groupid AND "
+ . "resourcetypeid1 = $mytypeid AND "
+ . "resourcegroupid2 = $id AND "
+ . "resourcetypeid2 = $maptypeid";
+ doQuery($query);
+ }
+ }
+ $regids = "^" . implode('$|^', $mapids) . "$";
+ $arr = array('status' => 'success',
+ 'regids' => $regids,
+ 'inselobj' => 'inmapgroups',
+ 'outselobj' => 'outmapgroups');
+ sendJSON($arr);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn mapByMapToGroupHTML()
+ ///
+ /// \return html
+ ///
+ /// \brief generates HTML for resource mapping by selecting a resource group
+ /// of the type that this type maps to
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function mapByMapToGroupHTML() {
+ $tmp = getUserResources(array($this->maptype . "Admin"),
+ array("manageMapping"), 1);
+ $mapgroups = $tmp[$this->maptype];
+ uasort($mapgroups, "sortKeepIndex");
+ $tmp = getUserResources(array($this->restype . "Admin"),
+ array("manageMapping"), 1);
+ $groups = $tmp[$this->restype];
+ uasort($groups, "sortKeepIndex");
+ $h = '';
+
+ if(! count($mapgroups) || ! count($groups)) {
+ $h .= "You don't have access to manage any mappings for this resource ";
+ $h .= "type.<br>\n";
+ return $h;
+ }
+
+ $h .= "<div id=\"mapbymaptogroupdiv\" dojoType=\"dijit.layout.ContentPane\" title=\"Map By {$this->maptypename} Group\">\n";
+ $h .= "Select an item from the drop-down box and click \"Get {$this->restypename} Groups\"<br>";
+ $h .= "to see all of the groups it maps to. Then, select a group ";
+ $h .= "it does not map<br>to and click the Add button to map it to that group, ";
+ $h .= "or select a group it<br>maps to and click the Remove ";
+ $h .= "button to unmap it from that group.<br><br>\n";
+ $h .= "{$this->maptypename} Group:<select id=\"maptogroups\">\n";
+ foreach($mapgroups as $id => $group)
+ $h .= "<option value=$id>$group</option>\n";
+ $h .= "</select>\n";
+ $h .= dijitButton('', "Get {$this->restypename} Groups",
+ "populateLists('maptogroups', 'inmaptogroups', 'inmaptogroupname', 'outmaptogroupname', 'mapbymaptogroupcont');");
+ $h .= "<table><tbody><tr>\n";
+ # select for groups mapped to
+ $h .= "<td valign=top>\n";
+ $h .= "{$this->restypename} Groups <span style=\"font-weight: bold;\" id=\"inmaptogroupname\"></span> maps to:<br>\n";
+ $h .= "<table dojoType=\"dojox.grid.DataGrid\" jsId=\"inmaptogroups\" ";
+ $h .= "store=\"mapbymaptogroupstore\" style=\"width: 240px; height: 250px;\" query=\"{inout: 1}\" ";
+ $h .= "selectionMode=\"extended\">\n";
+ $h .= "<thead>\n";
+ $h .= "<tr>\n";
+ $h .= "<th field=\"name\" width=\"160px\"></th>\n";
+ $h .= "</tr>\n";
+ $h .= "</thead>\n";
+ $h .= "</table>\n";
+ $h .= "</td>\n";
+ # transfer buttons
+ $h .= "<td style=\"vertical-align: middle;\">\n";
+ $h .= dijitButton('', "<div style=\"width: 50px;\"><-Add</div>",
+ "resource.addRemItem('addmaptogrpcont', 'maptogroups', 'outmaptogroups');");
+ $cdata = $this->basecdata;
+ $cdata['mode'] = 'add';
+ $cont = addContinuationsEntry('AJaddRemGroupMapTo', $cdata);
+ $h .= "<input type=\"hidden\" id=\"addmaptogrpcont\" value=\"$cont\">\n";
+ $h .= "<br><br><br>\n";
+ $h .= dijitButton('', "<div style=\"width: 50px;\">Remove-></div>",
+ "resource.addRemItem('remmaptogrpcont', 'maptogroups', 'inmaptogroups');");
+ $cdata['mode'] = 'remove';
+ $cont = addContinuationsEntry('AJaddRemGroupMapTo', $cdata);
+ $h .= "<input type=\"hidden\" id=\"remmaptogrpcont\" value=\"$cont\">\n";
+ $h .= "</td>\n";
+ # select for groups resource is not in
+ $h .= "<td valign=top>\n";
+ $h .= "{$this->restypename} Groups <span style=\"font-weight: bold;\" id=\"outmaptogroupname\"></span> does not map to:<br>\n";
+ $h .= "<table dojoType=\"dojox.grid.DataGrid\" jsId=\"outmaptogroups\" ";
+ $h .= "store=\"mapbymaptogroupstore\" style=\"width: 240px; height: 250px;\" query=\"{inout: 1}\" ";
+ $h .= "selectionMode=\"extended\">\n";
+ $h .= "<thead>\n";
+ $h .= "<tr>\n";
+ $h .= "<th field=\"name\" width=\"160px\"></th>\n";
+ $h .= "</tr>\n";
+ $h .= "</thead>\n";
+ $h .= "</table>\n";
+ $h .= "</td>\n";
+ $h .= "</tr></tbody></table>\n";
+ $cdata = $this->basecdata;
+ $cdata['store'] = 'mapbymaptogroupstore';
+ $cdata['intitle'] = 'inmaptogroups';
+ $cdata['outtitle'] = 'outmaptogroups';
+ $cont = addContinuationsEntry('jsonResourceMappingGroups', $cdata);
+ $h .= "<input type=hidden id=\"mapbymaptogroupcont\" value=\"$cont\">\n";
+ $h .= "</div>\n";
+ return $h;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn jsonResourceMappingGroups()
+ ///
+ /// \brief sends JSON of resource groups for resource mapping by selecting a
+ /// resource group of the type this type maps to
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function jsonResourceMappingGroups() {
+ $resmaptogrpid = processInputVar('id', ARG_NUMERIC);
+ $resources = getUserResources(array($this->maptype . "Admin"), array("manageMapping"), 1);
+ if(! array_key_exists($resmaptogrpid, $resources[$this->maptype])) {
+ sendJSON(array('status' => 'noaccess'));
+ return;
+ }
+ $groups = getUserResources(array($this->restype . 'Admin'), array('manageMapping'), 1);
+ $mapping = getResourceMapping($this->maptype, $this->restype);
+ $all = array();
+
+ foreach($groups[$this->restype] as $id => $group) {
+ if(array_key_exists($resmaptogrpid, $mapping) &&
+ in_array($id, $mapping[$resmaptogrpid]))
+ $all[] = array('id' => $id, 'name' => $group, 'inout' => 1);
+ else
+ $all[] = array('id' => $id, 'name' => $group, 'inout' => 0);
+ }
+ $arr = array('items' => $all,
+ 'intitle' => getContinuationVar('intitle'),
+ 'outtitle' => getContinuationVar('outtitle'));
+ sendJSON($arr);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn AJaddRemGroupMapTo()
+ ///
+ /// \brief adds or removes groups that map to a group of the type this
+ /// resource maps to
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function AJaddRemGroupMapTo() {
+ $mapgroupid = processInputVar('id', ARG_NUMERIC);
+ $mapgroups = getUserResources(array($this->maptype . "Admin"),
+ array("manageMapping"), 1);
+ if(! array_key_exists($mapgroupid, $mapgroups[$this->maptype])) {
+ $arr = array('status' => 'noaccess');
+ sendJSON($arr);
+ return;
+ }
+
+ $groups = getUserResources(array($this->restype . "Admin"),
+ array("manageMapping"), 1);
+ $tmp = processInputVar('listids', ARG_STRING);
+ $tmp = explode(',', $tmp);
+ $groupids = array();
+ foreach($tmp as $id) {
+ if(! is_numeric($id))
+ continue;
+ if(! array_key_exists($id, $groups[$this->restype])) {
+ $arr = array('status' => 'noaccess');
+ sendJSON($arr);
+ return;
+ }
+ $groupids[] = $id;
+ }
+
+ $mytypeid = getResourceTypeID($this->restype);
+ $maptypeid = getResourceTypeID($this->maptype);
+
+ $mode = getContinuationVar('mode');
+
+ if($mode == 'add') {
+ $adds = array();
+ foreach($groupids as $id)
+ $adds[] = "($id, $mytypeid, $mapgroupid, $maptypeid)";
+ $query = "INSERT IGNORE INTO resourcemap "
+ . "(resourcegroupid1, resourcetypeid1, "
+ . "resourcegroupid2, resourcetypeid2) "
+ . "VALUES ";
+ $query .= implode(',', $adds);
+ doQuery($query);
+ }
+ else {
+ foreach($groupids as $id) {
+ $query = "DELETE FROM resourcemap "
+ . "WHERE resourcegroupid1 = $id AND "
+ . "resourcetypeid1 = $mytypeid AND "
+ . "resourcegroupid2 = $mapgroupid AND "
+ . "resourcetypeid2 = $maptypeid";
+ doQuery($query);
+ }
+ }
+ $regids = "^" . implode('$|^', $groupids) . "$";
+ $arr = array('status' => 'success',
+ 'regids' => $regids,
+ 'inselobj' => 'inmaptogroups',
+ 'outselobj' => 'outmaptogroups');
+ sendJSON($arr);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn mapByGridHTML()
+ ///
+ /// \brief
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function mapByGridHTML() {
+ # TODO
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn AJsaveResource()
+ ///
+ /// \brief saves changes to a resource; must be implemented by inheriting
+ /// class
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function AJsaveResource() {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn AJeditResource()
+ ///
+ /// \brief sends data for editing a resource
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function AJeditResource() {
+ $rscid = processInputVar('rscid', ARG_NUMERIC);
+ $resources = getUserResources(array($this->restype . 'Admin'), array('administer'), 0, 1);
+ if(! array_key_exists($rscid, $resources[$this->restype])) {
+ $ret = array('status' => 'noaccess');
+ sendJSON($ret);
+ return;
+ }
+ $args = $this->defaultGetDataArgs;
+ $args['rscid'] = $rscid;
+ $tmp = $this->getData($args);
+ $data = $tmp[$rscid];
+ $cdata = $this->basecdata;
+ $cdata['rscid'] = $rscid;
+ $cdata['olddata'] = $data;
+
+ # save continuation
+ $cont = addContinuationsEntry('AJsaveResource', $cdata);
+
+ $ret = $this->jsondata;
+ $ret['title'] = "Edit {$this->restypename}";
+ $ret['cont'] = $cont;
+ $ret['resid'] = $rscid;
+ $ret['data'] = $data;
+ $ret['status'] = 'success';
+ sendJSON($ret);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn addResource($data)
+ ///
+ /// \param $data - array of needed data for adding a new resource
+ ///
+ /// \return id of new resource
+ ///
+ /// \brief handles all parts of adding a new resource to the database; should
+ /// be implemented by inheriting class, but not required since it is only
+ /// called by functions in the inheriting class (nothing in this base class
+ /// calls it directly)
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function addResource($data) {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn addEditDialogHTML($add)
+ ///
+ /// \param $add (optional, defaul=0) - 0 for edit, 1 for add
+ ///
+ /// \brief handles generating HTML for dialog used to edit resource; must be
+ /// implemented by inheriting class
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function addEditDialogHTML($add) {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn extraSelectAdminOptions()
+ ///
+ /// \return html
+ ///
+ /// \brief generates any HTML for additional options that should be shown on
+ /// selectionText page
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function extraSelectAdminOptions() {
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn AJstartImage()
+///
+/// \brief starts the imaging process for a reservation
+///
+////////////////////////////////////////////////////////////////////////////////
+function AJstartImage() {
+ global $user;
+ $requestid = getContinuationVar("requestid");
+ $checkpoint = getContinuationVar("checkpoint", 0);
+
+ $data = getRequestInfo($requestid);
+ $disableUpdate = 1;
+ $imageid = '';
+ if(count($data['reservations']) == 1) {
+ $imageid = $data['reservations'][0]['imageid'];
+ $revid = $data['reservations'][0]['imagerevisionid'];
+ }
+ else {
+ foreach($data["reservations"] as $res) {
+ if($res["forcheckout"]) {
+ $imageid = $res["imageid"];
+ $revid = $res['imagerevisionid'];
+ break;
+ }
+ }
+ }
+ if(! empty($imageid)) {
+ $imageData = getImages(0, $imageid);
+ if($imageData[$imageid]['ownerid'] == $user['id'])
+ $disableUpdate = 0;
+ if($imageData[$imageid]['installtype'] == 'none' ||
+ $imageData[$imageid]['installtype'] == 'kickstart')
+ $disableUpdate = 1;
+ }
+ else {
+ $data['status'] = 'error';
+ $data['errmsg'] = _("There was an error in starting the imaging process. Please contact a system administrator.");
+ sendJSON($data);
+ return;
+ }
+ $obj = new Image();
+ $cdata = array('obj' => $obj,
+ 'requestid' => $requestid,
+ 'imageid' => $imageid,
+ 'baserevisionid' => $data['reservations'][0]['imagerevisionid'],
+ 'checkpoint' => $checkpoint,
+ 'add' => 1);
+ $cont = addContinuationsEntry('AJsaveResource', $cdata, SECINDAY, 0);
+ $arr = array('newcont' => $cont,
+ 'enableupdate' => 0,
+ 'connectmethods' => $imageData[$imageid]['connectmethods'],
+ 'owner' => "{$user['unityid']}@{$user['affiliation']}",
+ 'checkpoint' => $checkpoint);
+
+ $cdata = array('obj' => $obj,
+ 'imageid' => $imageid,
+ 'newimage' => 1,
+ 'curmethods' => $imageData[$imageid]['connectmethods']);
+ $cont = addContinuationsEntry('connectmethodDialogContent', $cdata);
+ $arr['connectmethodurl'] = BASEURL . SCRIPT . "?continuation=$cont";
+
+ if(! $disableUpdate) {
+ $revisions = getImageRevisions($imageid);
+ if(array_key_exists($revid, $revisions))
+ $comments = $revisions[$revid]['comments'];
+ else {
+ $keys = array_keys($revisions);
+ if(count($keys)) {
+ $key = array_pop($keys);
+ $comments = $revisions[$key]['comments'];
+ }
+ else
+ $comments = '';
+ }
+ if(preg_match('/\w/', $comments)) {
+ $cmt = "These are the comments from the previous revision ";
+ $cmt .= "({$revisions[$revid]['revision']}):<br>";
+ $cmt .= "{$revisions[$revid]['comments']}<br><br>";
+ }
+ else
+ $cmt = "The previous revision did not have any comments.<br><br>";
+ $arr['comments'] = $cmt;
+ $cdata = array('obj' => $obj,
+ 'requestid' => $requestid,
+ 'imageid' => $imageid,
+ 'checkpoint' => $checkpoint,
+ 'revisionid' => $revid);
+ $cont = addContinuationsEntry('AJupdateImage', $cdata, SECINDAY, 0);
+ $arr['updatecont'] = $cont;
+ $arr['enableupdate'] = 1;
+ }
+ $arr['status'] = 'success';
+ sendJSON($arr);
+}
+
+?>
Added: vcl/trunk/web/.ht-inc/schedule.php
URL: http://svn.apache.org/viewvc/vcl/trunk/web/.ht-inc/schedule.php?rev=1624325&view=auto
==============================================================================
--- vcl/trunk/web/.ht-inc/schedule.php (added)
+++ vcl/trunk/web/.ht-inc/schedule.php Thu Sep 11 16:01:48 2014
@@ -0,0 +1,464 @@
+<?php
+/*
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \class Schedule
+///
+/// \brief extends Resource class to add things specific to resources of the
+/// schedule type
+///
+////////////////////////////////////////////////////////////////////////////////
+class Schedule extends Resource {
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn __construct()
+ ///
+ /// \brief calls parent constructor; initializes things for Schedule class
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function __construct() {
+ parent::__construct();
+ $this->restype = 'schedule';
+ $this->restypename = 'Schedule';
+ $this->namefield = 'name';
+ $this->basecdata['obj'] = $this;
+ $this->deletable = 1;
+ $this->deletetoggled = 0;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn getData($args)
+ ///
+ /// \param $args - unused in this class
+ ///
+ /// \return array of data as returned from getSchedules
+ ///
+ /// \brief wrapper for calling getSchedules
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function getData($args) {
+ return getSchedules();
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn addEditDialogHTML()
+ ///
+ /// \param $add - unused for this class
+ ///
+ /// \brief generates HTML for dialog used to edit resource
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function addEditDialogHTML($add=0) {
+ global $user, $days;
+ # dialog for on page editing
+ $h = '';
+ $h .= "<div dojoType=dijit.Dialog\n";
+ $h .= " id=\"addeditdlg\"\n";
+ $h .= " title=\"Edit {$this->restypename}\"\n";
+ $h .= " duration=250\n";
+ $h .= " style=\"width: 70%;\"\n";
+ $h .= " draggable=true>\n";
+ $h .= "<div id=\"addeditdlgcontent\">\n";
+ # id
+ $h .= "<input type=\"hidden\" id=\"editresid\">\n";
+
+ $h .= "<div style=\"text-align: center;\">\n";
+ # name
+ $errmsg = "Name cannot contain single (') or double (") quotes, "
+ . "less than (<), or greater than (>) and can be from 2 to 30 "
+ . "characters long";
+ $h .= labeledFormItem('name', 'Name', 'text', '^([A-Za-z0-9-!@#$%^&\*\(\)_=\+\[\]{}\\\|:;,\./\?~` ]){2,30}$',
+ 1, '', $errmsg, '', '', '200px');
+ # owner
+ $extra = array('onKeyPress' => 'setOwnerChecking');
+ $h .= labeledFormItem('owner', 'Owner', 'text', '', 1,
+ "{$user['unityid']}@{$user['affiliation']}", 'Unknown user',
+ 'checkOwner', $extra, '200px');
+ #$h .= labeledFormItem('owner', 'Owner', 'text', '{$user['unityid']}@{$user['affiliation']}',
+ # 1, '', 'Unknown user', 'checkOwner', 'onKeyPress', 'setOwnerChecking');
+ $cont = addContinuationsEntry('AJvalidateUserid');
+ $h .= "<input type=\"hidden\" id=\"valuseridcont\" value=\"$cont\">\n";
+
+ # table of times
+ $h .= "<br>";
+ $h .= "<span style=\"text-align: center;\"><h3>Schedule Times</h3></span>\n";
+ $h .= "The start and end day/times are based on a week's time period with ";
+ $h .= "the start/end point being 'Sunday 12:00 am'. i.e. The earliest ";
+ $h .= "start day/time is 'Sunday 12:00 am' and the latest end day/";
+ $h .= "time is 'Sunday 12:00 am'<br><br>\n";
+ $h .= "Start:";
+ $h .= selectInputAutoDijitHTML('startday', $days, 'startday');
+ $h .= "<input type=\"text\" id=\"starttime\" dojoType=\"dijit.form.TimeTextBox\" ";
+ $h .= "required=\"true\" value=\"T00:00:00\"/>\n";
+ $h .= "End:";
+ $h .= selectInputAutoDijitHTML('endday', $days, 'endday');
+ $h .= "<input type=\"text\" id=\"endtime\" dojoType=\"dijit.form.TimeTextBox\" ";
+ $h .= "required=\"true\" value=\"T00:00:00\" />\n";
+ $h .= dijitButton('addTimeBtn', "Add", "addTime();");
+ $h .= "</div>\n"; # text-align: center
+ $h .= "<div dojoType=\"dojo.data.ItemFileWriteStore\" jsId=\"scheduleStore\" ";
+ $h .= "data=\"scheduleTimeData\"></div>\n";
+ $h .= "<table dojoType=\"dojox.grid.DataGrid\" jsId=\"scheduleGrid\" sortInfo=1 ";
+ $h .= "store=\"scheduleStore\" style=\"width: 520px; height: 165px;\">\n";
+ $h .= "<thead>\n";
+ $h .= "<tr>\n";
+ $h .= "<th field=\"startday\" width=\"94px\" formatter=\"formatDay\">Start Day</th>\n";
+ $h .= "<th field=\"startday\" width=\"94px\" formatter=\"formatTime\">Start Time</th>\n";
+ $h .= "<th field=\"endday\" width=\"94px\" formatter=\"formatDay\">End Day</th>\n";
+ $h .= "<th field=\"endday\" width=\"94px\" formatter=\"formatTime\">End Time</th>\n";
+ $h .= "<th field=\"remove\" width=\"80px\">Remove</th>\n";
+ $h .= "</tr>\n";
+ $h .= "</thead>\n";
+ $h .= "</table>\n";
+ $h .= "</div>\n"; # addeditdlgcontent
+
+ $h .= "<div id=\"addeditdlgerrmsg\" class=\"nperrormsg\"></div>\n";
+ $h .= "<div id=\"editdlgbtns\" align=\"center\">\n";
+ $h .= dijitButton('addeditbtn', "Confirm", "saveResource();");
+ $h .= dijitButton('', "Cancel", "addEditDlgHide();");
+ $h .= "</div>\n"; # editdlgbtns
+ $h .= "</div>\n"; # addeditdlg
+
+ $h .= "<div dojoType=dijit.Dialog\n";
+ $h .= " id=\"groupingnote\"\n";
+ $h .= " title=\"Schedule Grouping\"\n";
+ $h .= " duration=250\n";
+ $h .= " draggable=true>\n";
+ $h .= "Each schedule should be a member of a schedule<br>resource group. The following dialog will allow you<br>to add the new schedule to a group.<br><br>\n";
+ $h .= "<div align=\"center\">\n";
+ $h .= dijitButton('', "Close", "dijit.byId('groupingnote').hide();");
+ $h .= "</div>\n"; # btn div
+ $h .= "</div>\n"; # groupingnote
+
+ $h .= "<div dojoType=dijit.Dialog\n";
+ $h .= " id=\"groupdlg\"\n";
+ $h .= " title=\"Schedule Grouping\"\n";
+ $h .= " duration=250\n";
+ $h .= " draggable=true>\n";
+ $h .= "<div id=\"groupdlgcontent\"></div>\n";
+ $h .= "<div align=\"center\">\n";
+ $script = " dijit.byId('groupdlg').hide();\n";
+ $script .= " checkFirstAdd();\n";
+ $h .= dijitButton('', "Close", $script);
+ $h .= "</div>\n"; # btn div
+ $h .= "</div>\n"; # groupdlg
+
+ return $h;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn AJsaveResource()
+ ///
+ /// \brief saves changes to resource
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function AJsaveResource() {
+ $add = getContinuationVar('add', 0);
+ $data = $this->validateResourceData();
+ if($data['error']) {
+ $ret = array('status' => 'error', 'msg' => $data['errormsg']);
+ sendJSON($ret);
+ return;
+ }
+
+ if($add) {
+ if(! $data['rscid'] = $this->addResource($data)) {
+ sendJSON(array('status' => 'adderror',
+ 'errormsg' => 'Error encountered while trying to create new schedule.<br>Please contact an admin for assistance.'));
+ return;
+ }
+ }
+ else {
+ $ownerid = getUserlistID($data['owner']);
+ $query = "UPDATE schedule "
+ . "SET name = '{$data['name']}', "
+ . "ownerid = $ownerid "
+ . "WHERE id = {$data['rscid']}";
+ doQuery($query);
+ }
+
+ if(! $add) {
+ $query = "DELETE FROM scheduletimes WHERE scheduleid = {$data['rscid']}";
+ doQuery($query, 101);
+ }
+ $qvals = array();
+ foreach($data['times'] as $time)
+ $qvals[] = "({$data['rscid']}, {$time['start']}, {$time['end']})";
+ $allvals = implode(',', $qvals);
+ $query = "INSERT INTO scheduletimes "
+ . "(scheduleid, start, end) "
+ . "VALUES $allvals";
+ doQuery($query, 101);
+
+ # clear user resource cache for this type
+ $key = getKey(array(array($this->restype . "Admin"), array("administer"), 0, 1, 0));
+ unset($_SESSION['userresources'][$key]);
+ $key = getKey(array(array($this->restype . "Admin"), array("administer"), 0, 0, 0));
+ unset($_SESSION['userresources'][$key]);
+ $key = getKey(array(array($this->restype . "Admin"), array("manageGroup"), 0, 1, 0));
+ unset($_SESSION['userresources'][$key]);
+ $key = getKey(array(array($this->restype . "Admin"), array("manageGroup"), 0, 0, 0));
+ unset($_SESSION['userresources'][$key]);
+
+ $tmp = $this->getData(array('includedeleted' => 0, 'rscid' => $data['rscid']));
+ $data = $tmp[$data['rscid']];
+ $arr = array('status' => 'success');
+ if($add) {
+ $arr['action'] = 'add';
+ $arr['nogroups'] = 0;
+ $groups = getUserResources(array($this->restype . 'Admin'), array('manageGroup'), 1);
+ if(count($groups[$this->restype]))
+ $arr['groupingHTML'] = $this->groupByResourceHTML();
+ else
+ $arr['nogroups'] = 1;
+ }
+ else
+ $arr['action'] = 'edit';
+ $arr['data'] = $data;
+ sendJSON($arr);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn addResource($data)
+ ///
+ /// \param $data - array of needed data for adding a new resource
+ ///
+ /// \return id of new resource
+ ///
+ /// \brief handles adding a new schedule and other associated data to the
+ /// database
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function addResource($data) {
+ global $user;
+
+ $ownerid = getUserlistID($data['owner']);
+ $query = "INSERT INTO schedule "
+ . "(name, "
+ . "ownerid) "
+ . "VALUES ('{$data['name']}', "
+ . "$ownerid)";
+ doQuery($query);
+
+ $rscid = dbLastInsertID();
+ if($rscid == 0) {
+ return 0;
+ }
+
+ $query = "INSERT INTO resource "
+ . "(resourcetypeid, "
+ . "subid) "
+ . "VALUES (15, "
+ . "$rscid)";
+ doQuery($query, 223);
+
+ return $rscid;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn validateResourceData()
+ ///
+ /// \return array with these fields:\n
+ /// \b rscid - id of resource (from schedule table)\n
+ /// \b name\n
+ /// \b owner\n
+ /// \b times - array of arrays, each having 2 keys: start and end, each in
+ /// unix timestamp format\n
+ /// \b error - 0 if submitted data validates; 1 if anything is invalid\n
+ /// \b errormsg - if error = 1; string of error messages separated by html
+ /// break tags
+ ///
+ /// \brief validates form input from editing or adding a schedule
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function validateResourceData() {
+ global $user;
+
+ $return = array('error' => 0);
+ $errormsg = array();
+
+ $return['rscid'] = getContinuationVar('rscid', 0);
+ $return["name"] = processInputVar("name", ARG_STRING);
+ $return["owner"] = processInputVar("owner", ARG_STRING, "{$user["unityid"]}@{$user['affiliation']}");
+ $times = processInputVar('times', ARG_STRING);
+
+ if(! preg_match("/^([A-Za-z0-9-!@#$%^&\*\(\)_=\+\[\]{}\\\|:;,\.\/\?~` ]){2,30}$/", $return['name'])) {
+ $return['error'] = 1;
+ $errormsg[] = "Name cannot contain single (') or double (") quotes, "
+ . "less than (<), or greater than (>) and can be from 2 to 30 "
+ . "characters long";
+ }
+ elseif($this->checkForScheduleName($return['name'], $return['rscid'])) {
+ $return['error'] = 1;
+ $errormsg[] = "A schedule already exists with this name.";
+ }
+ if(! validateUserid($return['owner'])) {
+ $return['error'] = 1;
+ $errormsg[] = "Submitted owner is not valid";
+ }
+ if(! preg_match('/^([0-9]+:[0-9]+,)*([0-9]+:[0-9]+){1}$/', $times)) {
+ $return['error'] = 1;
+ $errormsg[] = "Invalid time data submitted";
+ }
+
+ if(! $return['error']) {
+ $times = explode(',', $times);
+ $return['times'] = array();
+ foreach($times as $pair) {
+ list($start, $end) = explode(':', $pair);
+ foreach($return['times'] as $check) {
+ if($start < $check['end'] && $end > $check['start']) {
+ $return['error'] = 1;
+ $errormsg[] = "Two sets of times are overlapping - please correct and save again";
+ break(2);
+ }
+ }
+ $return['times'][] = array('start' => $start, 'end' => $end);
+ }
+ }
+
+ if($return['error'])
+ $return['errormsg'] = implode('<br>', $errormsg);
+
+ return $return;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn toggleDeleteResourceExtra()
+ ///
+ /// \return html
+ ///
+ /// \brief generates additional HTML to be included at the end of the confirm
+ /// toggle delete resource page
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function toggleDeleteResourceExtra() {
+ $rscid = processInputVar('rscid', ARG_NUMERIC);
+ $data = $this->getData('');
+ $h = '';
+ if(count($data[$rscid]["times"])) {
+ $h .= "<br><TABLE>\n";
+ $h .= " <TR>\n";
+ $h .= " <TH>Start</TH>\n";
+ $h .= " <TD> </TD>\n";
+ $h .= " <TH>End</TH>\n";
+ $h .= " <TR>\n";
+ foreach($data[$rscid]["times"] as $time) {
+ $h .= " <TR>\n";
+ $h .= " <TD>" . $this->minToDaytime($time["start"]) . "</TD>\n";
+ $h .= " <TD> </TD>\n";
+ $h .= " <TD>" . $this->minToDaytime($time["end"]) . "</TD>\n";
+ $h .= " </TR>\n";
+ }
+ $h .= "</TABLE><br>\n";
+ }
+ return $h;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn submitToggleDeleteResourceExtra($rscid, $deleted)
+ ///
+ /// \param $rscid - id of a resource (from schedule table)
+ /// \param $deleted - (optional, default=0) 1 if resource was previously
+ /// deleted; 0 if not
+ ///
+ /// \brief handles deleting associated entries from scheduletimes table
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function submitToggleDeleteResourceExtra($rscid, $deleted=0) {
+ $query = "DELETE FROM scheduletimes "
+ . "WHERE scheduleid = $rscid";
+ doQuery($query);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn checkForScheduleName($name, $id)
+ ///
+ /// \param $name - the name of a schedule
+ /// \param $id - id of a schedule to ignore
+ ///
+ /// \return 1 if $name is already in the schedule table, 0 if not
+ ///
+ /// \brief checks for $name being in the schedule table except for $id
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function checkForScheduleName($name, $id) {
+ $query = "SELECT id FROM schedule "
+ . "WHERE name = '$name'";
+
+ if(! empty($id))
+ $query .= " AND id != $id";
+ $qh = doQuery($query, 101);
+ if(mysql_num_rows($qh))
+ return 1;
+ return 0;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn minToDaytime($min)
+ ///
+ /// \param $min - minute of the week
+ ///
+ /// \return day of week and time of day
+ ///
+ /// \brief calculates day of week and time of day from $min and returns a
+ /// nicely formatted string of "Weekday HH:MM am/pm"
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function minToDaytime($min) {
+ $days = array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+ "Friday", "Saturday");
+ $time = minuteToTime($min % 1440);
+ if((int)($min / 1440) == 0) {
+ $day = 0;
+ }
+ elseif((int)($min / 1440) == 1) {
+ $day = 1;
+ }
+ elseif((int)($min / 1440) == 2) {
+ $day = 2;
+ }
+ elseif((int)($min / 1440) == 3) {
+ $day = 3;
+ }
+ elseif((int)($min / 1440) == 4) {
+ $day = 4;
+ }
+ elseif((int)($min / 1440) == 5) {
+ $day = 5;
+ }
+ elseif((int)($min / 1440) == 6) {
+ $day = 6;
+ }
+ elseif((int)($min / 1440) > 6) {
+ $day = 0;
+ }
+ return $days[$day] . " $time";
+ }
+}
+?>