| 1 | <?php /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 2; -*- |
|---|
| 2 | |
|---|
| 3 | */ |
|---|
| 4 | |
|---|
| 5 | require_once('class.dkg.person.php'); |
|---|
| 6 | |
|---|
| 7 | if (!class_exists('JPDD_Organization')) { |
|---|
| 8 | |
|---|
| 9 | class JPDD_Organization extends DKG_Row { |
|---|
| 10 | |
|---|
| 11 | function getCreatePrivilege() { |
|---|
| 12 | return array('Edit Organizations'); |
|---|
| 13 | } |
|---|
| 14 | function getEditPrivilege() { |
|---|
| 15 | return array('Edit Organizations'); |
|---|
| 16 | } |
|---|
| 17 | |
|---|
| 18 | # try to add a richtext editor for this form, since it has a description: |
|---|
| 19 | function getFormInnards() { |
|---|
| 20 | global $jpdd; |
|---|
| 21 | $websiteerr = is_null($this->_website) ? NULL : $jpdd->isValid('URL', $this->_website); |
|---|
| 22 | $jpdd->addTinyMCE(); |
|---|
| 23 | return '<div> |
|---|
| 24 | <label>Name:<br/><input type="text" name="title" value="'.$this->getTitle(true).'"/></label><br/> |
|---|
| 25 | <label>Description<br/><textarea name="description" rows="20" cols="70">'.$this->getDescription(true).'</textarea></label><br/> |
|---|
| 26 | <label>Web Site:<br/>'.(is_null($websiteerr)?'':'<span class="error">'.$websiteerr.'</span><br/>').'<input type="text" size="50" '.(is_null($websiteerr)?'':'class="error" ').'name="website" value="'.htmlentities($this->_website).'"/></label> |
|---|
| 27 | </div>'; |
|---|
| 28 | } |
|---|
| 29 | |
|---|
| 30 | function applyPostForm($prefix = '') { |
|---|
| 31 | global $jpdd; |
|---|
| 32 | $this->_title = $jpdd->nonEmptyString($_POST[$prefix.'title']); |
|---|
| 33 | $this->_description = $jpdd->nonEmptyString($_POST[$prefix.'description']); |
|---|
| 34 | $this->_website = $jpdd->nonEmptyString($_POST[$prefix.'website']); |
|---|
| 35 | } |
|---|
| 36 | |
|---|
| 37 | function getWebsite() { |
|---|
| 38 | global $jpdd; |
|---|
| 39 | if (! is_null($this->_website) && (is_null($jpdd->isValid('URL', $this->_website)))) |
|---|
| 40 | return $this->_website; |
|---|
| 41 | return NULL; |
|---|
| 42 | } |
|---|
| 43 | |
|---|
| 44 | function handleCreation($prefix = '') { |
|---|
| 45 | global $jpdd; |
|---|
| 46 | $this->applyPostForm($prefix); |
|---|
| 47 | $res = $jpdd->executeSQL('INSERT INTO '.$this->getSingletonTable().' (title, description, website) VALUES ('. |
|---|
| 48 | $jpdd->stringOrDefault($this->_title).', '. |
|---|
| 49 | $jpdd->stringOrDefault($this->_description).', '. |
|---|
| 50 | $jpdd->stringOrDefault($this->_website). |
|---|
| 51 | ')', false); |
|---|
| 52 | if (false === $res) { |
|---|
| 53 | $logid = $jpdd->log('creating organization db insert failed with pg error: '.pg_last_error($jpdd->_db)); |
|---|
| 54 | return 'database insertion of organization failed for some reason (error: '.(int)$logid.').'; |
|---|
| 55 | } else { |
|---|
| 56 | $this->JPDD_Organization(array('data' => $jpdd->getSingletonFromSQL('SELECT * from '.$this->getSingletonTable().' WHERE id = currval(\''.$this->getSingletonTable().'_id_seq\')'))); |
|---|
| 57 | return NULL; |
|---|
| 58 | } |
|---|
| 59 | } |
|---|
| 60 | |
|---|
| 61 | function handleEdit() { |
|---|
| 62 | global $jpdd; |
|---|
| 63 | $this->applyPostForm(); |
|---|
| 64 | $ret = $jpdd->executeSQL('UPDATE '.$this->getSingletonTable().' SET '. |
|---|
| 65 | 'title = '.$jpdd->stringOrDefault($this->getTitle()).', '. |
|---|
| 66 | 'description = '.$jpdd->stringOrDefault($this->getDescription()).', '. |
|---|
| 67 | 'website = '.$jpdd->stringOrDefault($this->_website).' '. |
|---|
| 68 | 'WHERE id = '.$this->getID()); |
|---|
| 69 | if (false === $res) { |
|---|
| 70 | $logid = $jpdd->log('database update of organization '.$this->getID().' insert failed with pg error: '.pg_last_error($jpdd->_db)); |
|---|
| 71 | return 'update of organization failed for some reason (error: '.(int)$logid.').'; |
|---|
| 72 | } else { |
|---|
| 73 | $this->JPDD_Organization(array('id' => $this->getID())); |
|---|
| 74 | return NULL; |
|---|
| 75 | } |
|---|
| 76 | } |
|---|
| 77 | |
|---|
| 78 | function getPDFLinks() { |
|---|
| 79 | global $jpdd; |
|---|
| 80 | if ($jpdd->isAuthenticated()) { |
|---|
| 81 | if ($jpdd->_authenticated_user->hasAllOfThesePrivileges('Edit Organizations')) { |
|---|
| 82 | $pdfs = array('Attendance List' => 'attendance'); |
|---|
| 83 | return '<div class="pdf-links">'."\n".join('', array_map(create_function('$t, $v', 'global $jpdd; return "<a href=\"".$jpdd->Path("printout", "organization", '.$this->getID().', $v.".pdf")."\">".$t."</a>\n";'), array_keys($pdfs), $pdfs))."</div>\n"; |
|---|
| 84 | } |
|---|
| 85 | } else { |
|---|
| 86 | return ''; |
|---|
| 87 | } |
|---|
| 88 | } |
|---|
| 89 | |
|---|
| 90 | |
|---|
| 91 | function getLinkedTitle($classnames = NULL) { |
|---|
| 92 | global $jpdd; |
|---|
| 93 | if ($jpdd->isAuthenticated() && $jpdd->_authenticated_user->canEdit($this)) { |
|---|
| 94 | return parent::getLinkedTitle($classnames); |
|---|
| 95 | } else { |
|---|
| 96 | if (!is_null($this->_description)) { |
|---|
| 97 | // if there's a description, treat as normal. |
|---|
| 98 | return parent::getLinkedTitle($classnames); |
|---|
| 99 | } elseif (!is_null($this->getWebsite())) { |
|---|
| 100 | // instead, if there is a website, link to that. |
|---|
| 101 | return '<a '.(is_null($classnames) ? '' : 'class="'.$classnames.'" ').'href="'.$this->getWebsite().'">'.$this->getTitle().'</a>'; |
|---|
| 102 | } else { |
|---|
| 103 | // otherwise, there's not much here, so don't bother linking: |
|---|
| 104 | return $this->getTitle(); |
|---|
| 105 | } |
|---|
| 106 | } |
|---|
| 107 | } |
|---|
| 108 | |
|---|
| 109 | function getPDF($pdfname) { |
|---|
| 110 | require_once('class.jpdd.pdf.php'); |
|---|
| 111 | $ret = new JPDD_PDF(); |
|---|
| 112 | if ($pdfname == 'attendance.pdf') { |
|---|
| 113 | $ret->addAttendanceLocationsPage($this); |
|---|
| 114 | } else { |
|---|
| 115 | return NULL; |
|---|
| 116 | } |
|---|
| 117 | return $ret; |
|---|
| 118 | } |
|---|
| 119 | |
|---|
| 120 | function getDetailTopInnards() { |
|---|
| 121 | return $this->getPDFLinks(); |
|---|
| 122 | } |
|---|
| 123 | |
|---|
| 124 | function getApplyingPeople() { |
|---|
| 125 | global $jpdd; |
|---|
| 126 | |
|---|
| 127 | $sql = 'SELECT person.*, category_id FROM person JOIN affiliation ON (person_id = person.id) JOIN application ON (person.id = application.person_id) WHERE event_id = '.$jpdd->getActiveEventID().' ORDER BY category_id, first_name, middle_name, last_name'; |
|---|
| 128 | |
|---|
| 129 | return $jpdd->getMultiSeriesFromSQLByValue($sql, 'category_id', 'JPDD_Person'); |
|---|
| 130 | } |
|---|
| 131 | |
|---|
| 132 | function getAffiliatedPersonIDs() { |
|---|
| 133 | global $jpdd; |
|---|
| 134 | return array_map('intval', $jpdd->getValuesFromSQL('SELECT person_id FROM affiliation WHERE organization_id = '.$this->getID(), 'person_id')); |
|---|
| 135 | } |
|---|
| 136 | |
|---|
| 137 | function getLiaisonForm() { |
|---|
| 138 | global $jpdd; |
|---|
| 139 | |
|---|
| 140 | // this is gonna require the interface js libraries: |
|---|
| 141 | |
|---|
| 142 | $jpdd->addSourcedScript('scripts/jquery.js'); |
|---|
| 143 | $jpdd->addSourcedScript('scripts/interface/interface.js'); |
|---|
| 144 | $jpdd->addSourcedScript('scripts/jpdd.liaison.js'); |
|---|
| 145 | $jpdd->addStyleSheet('styles/liaison.css'); |
|---|
| 146 | $script = ''; |
|---|
| 147 | |
|---|
| 148 | // get the list of attendees for this event related to this |
|---|
| 149 | // organization: |
|---|
| 150 | $applied = $this->getApplyingPeople(); |
|---|
| 151 | |
|---|
| 152 | $listed_ids = array(); |
|---|
| 153 | |
|---|
| 154 | // get the remaining attendees affiliated with this |
|---|
| 155 | // organization |
|---|
| 156 | // FIXME: this contains too many people at the moment, because it includes existing attendees. |
|---|
| 157 | $otheraffiliates = $this->getM2MPeers('person', 'affiliation'); |
|---|
| 158 | |
|---|
| 159 | // get the per-category requirements for this event: |
|---|
| 160 | $jpdd->prepClass('category'); |
|---|
| 161 | $requirements = $jpdd->getSeriesFromSQL('SELECT category.*, minimum, maximum FROM attendance_requirements JOIN category ON (category.id = category_id) WHERE event_id = '.$jpdd->getActiveEventID().' ORDER BY minimum DESC', 'JPDD_Category'); |
|---|
| 162 | |
|---|
| 163 | $ret = '<div class="instructions">Please sign up teachers from your school by dragging them to the appropriate subject area on the left.</div>'; |
|---|
| 164 | $script .= '$("li.affiliated_person").Draggable( {revert: true, ghosting: true} ); |
|---|
| 165 | $("fieldset.category").each( JPDD.Liaison.testapply );'; |
|---|
| 166 | |
|---|
| 167 | $ret .= '<table class="liaisonui"><tbody><tr><td>'; |
|---|
| 168 | |
|---|
| 169 | $dropdown = '<select name="newassign">'."\n<option>choose a subject</option>\n"; |
|---|
| 170 | reset($requirements); |
|---|
| 171 | while(list(,$req) = each($requirements)) { |
|---|
| 172 | $ret .= '<fieldset id="category_'.$req->getID().'" catval="'.(int)$req->getID().'" class="category" min="'.(int)$req->_minimum.'" max="'.(int)$req->_maximum.'"><legend>'.$req->getTitle().'</legend><div class="notes"></div> |
|---|
| 173 | <ul> |
|---|
| 174 | '; |
|---|
| 175 | |
|---|
| 176 | $dropdown .= '<option value="'.$req->getID().'">'.$req->getTitle().'</option>'."\n"; |
|---|
| 177 | if (array_key_exists($req->getID(), $applied)) { |
|---|
| 178 | $ret .= join("\n", array_map(create_function('$x', 'return $x->getListItem("affiliated_person", '.$req->getID().');'), $applied[$req->getID()])); |
|---|
| 179 | $ids = array_map(create_function('$x', 'return $x->getID();'), $applied[$req->getID()]); |
|---|
| 180 | $listed_ids = array_merge($listed_ids, $ids); |
|---|
| 181 | } |
|---|
| 182 | |
|---|
| 183 | /* |
|---|
| 184 | $item = 0; |
|---|
| 185 | while ($item < $req->_minimum) { |
|---|
| 186 | $x = 'application_'.$req->getID().'_'.$item; |
|---|
| 187 | $ret .= '<input type="hidden" name="application_'.$req->getID().'" value="" id="'.$x.'" />'; |
|---|
| 188 | $item++; |
|---|
| 189 | } |
|---|
| 190 | while ($item < $req->_maximum) { |
|---|
| 191 | |
|---|
| 192 | $item++; |
|---|
| 193 | } |
|---|
| 194 | */ |
|---|
| 195 | $ret .= '</ul></fieldset>'; |
|---|
| 196 | } |
|---|
| 197 | |
|---|
| 198 | $dropdown .= '</select>'; |
|---|
| 199 | |
|---|
| 200 | $ret .= '</td><td>'; |
|---|
| 201 | |
|---|
| 202 | // show all the affiliates in their own list: |
|---|
| 203 | $ret .= '<fieldset class="category" catval=""><legend>Available teachers</legend><div class="notes"></div><ul>'. |
|---|
| 204 | join("\n", array_map(create_function('$x', 'return $x->getListItem("affiliated_person", "");'), array_filter($otheraffiliates, create_function('$x', '$y = array('.join(',', $listed_ids).'); return !in_array($x->getID(), $y);')))).' |
|---|
| 205 | </ul> |
|---|
| 206 | </fieldset> |
|---|
| 207 | '; |
|---|
| 208 | |
|---|
| 209 | // allow liaisons to create new people: |
|---|
| 210 | $ret .= '<fieldset><legend>Add a new teacher</legend> |
|---|
| 211 | '.$dropdown.'<br/> |
|---|
| 212 | <label>First name:<br/><input type="text" name="first_name" value=""/></label><br/> |
|---|
| 213 | <label>Last name:<br/><input type="text" name="last_name" value=""/></label><br/> |
|---|
| 214 | <label>E-mail Address:<br/><input type="text" name="email" value=""/></label><br/> |
|---|
| 215 | </fieldset>'; |
|---|
| 216 | |
|---|
| 217 | $ret .= '</tr></tbody></table>'; |
|---|
| 218 | $jpdd->addScriptChunk('$(document).ready(function() {'.$script.'});'); |
|---|
| 219 | return '<form action="'.$jpdd->Path('liaison/organization/'.$this->getID()).'" method="post">'. |
|---|
| 220 | $ret. |
|---|
| 221 | $jpdd->getFormTokenHiddenInput(). |
|---|
| 222 | '<input type="submit" value="Save Changes">'. |
|---|
| 223 | '</form>'; |
|---|
| 224 | } |
|---|
| 225 | |
|---|
| 226 | function handleLiaisonForm() { |
|---|
| 227 | global $jpdd; |
|---|
| 228 | // walk through the people supplied: if they're affiliated with |
|---|
| 229 | // the org in question, check their invitation status for the |
|---|
| 230 | // current session, and make sure it matches the input. |
|---|
| 231 | |
|---|
| 232 | $affiliatedids = $this->getAffiliatedPersonIDs(); |
|---|
| 233 | $acceptedcategories = array_map('intval', $jpdd->getValuesFromSQL('SELECT category_id FROM attendance_requirements WHERE event_id = '.$jpdd->getActiveEventID(), 'category_id')); |
|---|
| 234 | |
|---|
| 235 | // we'll just ignore unaffiliated people: |
|---|
| 236 | $people = array_intersect_key($jpdd->getPostedIDtoIDMap('person'), array_flip($affiliatedids)); |
|---|
| 237 | |
|---|
| 238 | $unapplied = array(); |
|---|
| 239 | reset($people); |
|---|
| 240 | while(list($person_id, $category) = each($people)) { |
|---|
| 241 | if (is_null($category) || !in_array($category, $acceptedcategories)) |
|---|
| 242 | $unapplied[] = $person_id; |
|---|
| 243 | else { |
|---|
| 244 | $jpdd->executeSQL('DELETE FROM application WHERE event_id = '.$jpdd->getActiveEventID().' AND person_id = '.$person_id); |
|---|
| 245 | $jpdd->executeSQL('INSERT INTO application (event_id, person_id, category_id) VALUES ('.(int)$jpdd->getActiveEventID().', '. |
|---|
| 246 | (int)$person_id.', '.$category.')'); |
|---|
| 247 | } |
|---|
| 248 | } |
|---|
| 249 | |
|---|
| 250 | if (count($unapplied)) |
|---|
| 251 | $jpdd->executeSQL('DELETE FROM application WHERE event_id = '.$jpdd->getActiveEventID().' AND person_id IN ('.join(',', $unapplied).')'); |
|---|
| 252 | |
|---|
| 253 | if ($jpdd->arrayKeyIsNotEmpty('first_name', $_POST) || |
|---|
| 254 | $jpdd->arrayKeyIsNotEmpty('last_name', $_POST) || |
|---|
| 255 | $jpdd->arrayKeyIsNotEmpty('email', $_POST)) { |
|---|
| 256 | // FIXME: if the person fields are present, check if person |
|---|
| 257 | // already exists, as affiliated with the school. |
|---|
| 258 | |
|---|
| 259 | |
|---|
| 260 | // if not, create the person, |
|---|
| 261 | $newp = new JPDD_Person(array('data' => array('first_name' => $_POST['first_name'], |
|---|
| 262 | 'last_name' => $_POST['last_name'], |
|---|
| 263 | 'email' => $_POST['email']))); |
|---|
| 264 | $res = $newp->storeNewInDatabase(); |
|---|
| 265 | if (false !== $res) { |
|---|
| 266 | // affiliate the person with the org: |
|---|
| 267 | $newp->addM2MPeers('organization', 'affiliation', array($this->getID())); |
|---|
| 268 | |
|---|
| 269 | if ($jpdd->arrayKeyIsNotEmpty('newassign', $_POST) && in_array((int)$_POST['newassign'], $acceptedcategories)) { |
|---|
| 270 | // FIXME: if the org already has enough for this category, put this user into "alternate"? |
|---|
| 271 | $jpdd->executeSQL('INSERT INTO application (event_id, person_id, category_id) VALUES ('.(int)$jpdd->getActiveEventID().', '. |
|---|
| 272 | $newp->getID().', '.(int)$_POST['newassign'].')'); |
|---|
| 273 | } |
|---|
| 274 | } |
|---|
| 275 | } |
|---|
| 276 | } |
|---|
| 277 | |
|---|
| 278 | function getDetailInnards() { |
|---|
| 279 | global $jpdd; |
|---|
| 280 | $ret = ''; |
|---|
| 281 | |
|---|
| 282 | if (!is_null($this->getWebsite())) |
|---|
| 283 | $ret .= '<a class="outlink" href="'.$this->getWebsite().'">Find out more about '.$this->getTitle().'</a>'; |
|---|
| 284 | |
|---|
| 285 | // FIXME: maybe show all affiliated people? |
|---|
| 286 | if ($jpdd->isAuthenticated() && $jpdd->_authenticated_user->hasAllOfThesePrivileges('List People')) { |
|---|
| 287 | $peops = $this->getM2MPeers('person', 'affiliation'); |
|---|
| 288 | |
|---|
| 289 | $ret .= '<h3>'.count($peops).(count($peops) == 1 ? ' Person' : ' People').'</h3><ul>'."\n". |
|---|
| 290 | join('', array_map(create_function('$x', 'return "<li>".$x->getLinkedTitle()." ".$x->getWorkshopText(false)."\n";'), $peops)). |
|---|
| 291 | "</ul>\n"; |
|---|
| 292 | } |
|---|
| 293 | |
|---|
| 294 | return $ret; |
|---|
| 295 | } |
|---|
| 296 | } |
|---|
| 297 | |
|---|
| 298 | } |
|---|