source: trunk/jpdd/class.jpdd.organization.php @ 1386

Last change on this file since 1386 was 1386, checked in by Daniel Kahn Gillmor, 5 years ago

display number of attendees in liaison view for january conferences

File size: 17.8 KB
Line 
1<?php  /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 2; -*-
2
3       */
4
5require_once('class.dkg.person.php');
6require_once('class.jpdd.category.php');
7
8if (!class_exists('JPDD_Organization')) {
9
10  class JPDD_Organization extends DKG_Row {
11    function JPDD_Organization($args = array()) {
12      $this->DKG_Row($args);
13    }
14   
15    function getCreatePrivilege() {
16          return array('Edit Organizations');
17        }
18        function getEditPrivilege() {
19          return array('Edit Organizations');
20        }
21
22    function countAttendeesSQL($eventid) {
23      return 'SELECT \'attendees\' AS title, COUNT(*) AS count FROM attendance JOIN workshop ON (workshop_id = workshop.id) JOIN affiliation USING (person_id) WHERE event_id = '.(int)$eventid.' AND organization_id = '.$this->getID();
24    }
25    function countApplicationsSQL($eventid) {
26      return 'SELECT \'applications\' AS title, COUNT(*) AS count FROM application JOIN affiliation USING (person_id) WHERE event_id = '.(int)$eventid.' AND organization_id = '.$this->getID();
27    }
28    function countRolesSQL($eventid) {
29      return 'SELECT \'role\' AS title, COUNT(*) AS count FROM person_role WHERE event_id = '.(int)$eventid.' AND organization_id = '.$this->getID();
30    }
31
32    function isParticipatingInEvent($eventid) {
33      global $jpdd;
34      $x = (int)($jpdd->getValueFromSQL('SELECT SUM(count) AS count FROM ('.$this->countAttendeesSQL($eventid).
35                                        ' UNION '.$this->countApplicationsSQL($eventid).
36                                        ' UNION '.$this->countRolesSQL($eventid).') AS foo', 'count'));
37      return ($x > 0);
38    }
39
40    function showInList() {
41      global $jpdd;
42     
43      // people who can edit organizations should be able to see them all.
44      if ($jpdd->isAuthenticated() && $jpdd->_authenticated_user->HasAnyOfThesePrivileges('Edit Organizations'))
45        return true;
46
47      // otherwise, we should only list organizations who have active
48      // applications, liaisons, or attendance in the current event:
49      return $this->isParticipatingInEvent($jpdd->getActiveEventID());
50    }
51
52    // try to add a richtext editor for this form, since it has a description:
53    function getFormInnards() {
54      global $jpdd;
55      $websiteerr = is_null($this->_website) ? NULL : $jpdd->isValid('URL', $this->_website);
56      $jpdd->addTinyMCE();
57      return '<div>
58<label>Name:<br/><input type="text" name="title" value="'.$this->getTitle(true).'"/></label><br/>
59<label>Description<br/><textarea name="description" rows="20" cols="70">'.$this->getDescription(true).'</textarea></label><br/>
60<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>
61</div>';
62    }
63
64    function applyPostForm($prefix = '') {
65      global $jpdd;
66      $this->_title = $jpdd->nonEmptyString($_POST[$prefix.'title']);
67      $this->_description = $jpdd->nonEmptyString($_POST[$prefix.'description']);
68      $this->_website = $jpdd->nonEmptyString($_POST[$prefix.'website']);
69    }
70
71    function getWebsite() {
72      global $jpdd;
73      if (! is_null($this->_website) && (is_null($jpdd->isValid('URL', $this->_website))))
74        return $this->_website;
75      return NULL;
76    }
77
78    function handleCreation($prefix = '') {
79      global $jpdd;
80      $this->applyPostForm($prefix);
81      $res = $jpdd->executeSQL('INSERT INTO '.$this->getSingletonTable().' (title, description, website) VALUES ('.
82                                                           $jpdd->stringOrDefault($this->_title).', '.
83                                                           $jpdd->stringOrDefault($this->_description).', '.
84                                                           $jpdd->stringOrDefault($this->_website).
85                               ')', false);
86          if (false === $res) {
87        $logid = $jpdd->log('creating organization db insert failed with pg error: '.pg_last_error($jpdd->_db));
88                return 'database insertion of organization failed for some reason (error: '.(int)$logid.').';
89          } else {
90                $this->JPDD_Organization(array('data' => $jpdd->getSingletonFromSQL('SELECT * from '.$this->getSingletonTable().' WHERE id = currval(\''.$this->getSingletonTable().'_id_seq\')')));
91                return NULL;
92          }
93    }
94
95    function handleEdit() {
96      global $jpdd;
97      $this->applyPostForm();
98      $ret = $jpdd->executeSQL('UPDATE '.$this->getSingletonTable().' SET '.
99                               'title = '.$jpdd->stringOrDefault($this->getTitle()).', '.
100                               'description = '.$jpdd->stringOrDefault($this->getDescription()).', '.
101                               'website = '.$jpdd->stringOrDefault($this->_website).' '.
102                               'WHERE id = '.$this->getID());
103          if (false === $res) {
104        $logid = $jpdd->log('database update of organization '.$this->getID().' insert failed with pg error: '.pg_last_error($jpdd->_db));
105                return 'update of organization failed for some reason (error: '.(int)$logid.').';
106          } else {
107                $this->JPDD_Organization(array('id' => $this->getID()));
108                return NULL;
109          }
110    }
111
112    function getPDFLinks() {
113      global $jpdd;
114      if ($jpdd->isAuthenticated()) {
115        if ($jpdd->_authenticated_user->hasAllOfThesePrivileges('Edit Organizations')) {
116          $pdfs = array('Attendance List' => 'attendance');
117          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";
118        }
119      } else {
120        return '';
121      }
122    }
123
124
125        function getLinkedTitle($classnames = NULL) {
126      global $jpdd;
127      if ($jpdd->isAuthenticated() && $jpdd->_authenticated_user->canEdit($this)) {
128        return parent::getLinkedTitle($classnames);
129      } else {
130        if (!is_null($this->_description)) {
131          // if there's a description, treat as normal.
132          return parent::getLinkedTitle($classnames);
133        } elseif (!is_null($this->getWebsite())) {
134          // instead, if there is a website, link to that.
135          return '<a '.(is_null($classnames) ? '' : 'class="'.$classnames.'" ').'href="'.$this->getWebsite().'">'.$this->getTitle().'</a>';
136        } else {
137          // otherwise, there's not much here, so don't bother linking:
138          return $this->getTitle();
139        }
140      }
141        }
142
143    function getPDF($pdfname) {
144      require_once('class.jpdd.pdf.php');
145      $ret = new JPDD_PDF();
146      if ($pdfname == 'attendance.pdf') {
147        $ret->addAttendanceLocationsPage($this);
148      } else {
149        return NULL;
150      }
151      return $ret;
152    }
153   
154    function getDetailTopInnards() {
155      return $this->getPDFLinks();
156    }
157
158    function getApplyingPeople() {
159      global $jpdd;
160
161      $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().' AND organization_id = '.$this->getID().' ORDER BY category_id, first_name, middle_name, last_name';
162
163      return $jpdd->getMultiSeriesFromSQLByValue($sql, 'category_id', 'JPDD_Person');
164    }
165
166    function getAffiliatedPersonIDs() {
167      global $jpdd;
168      return array_map('intval', $jpdd->getValuesFromSQL('SELECT person_id FROM affiliation WHERE organization_id = '.$this->getID(), 'person_id'));
169    }
170
171    function getLiaisonForm() {
172      global $jpdd;
173
174      $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'); 
175     
176      if (count($requirements) == 0) {
177        return '<h3>'.(int)($this->countAttendeesSQL($eventid)).' people signed up</h3>'.$this->getListOfPeopleForEvent($jpdd->getActiveEventID());
178      }
179     
180      // this is gonna require the interface js libraries:
181
182      $jpdd->addSourcedScript('scripts/jquery.js');
183      $jpdd->addSourcedScript('scripts/interface/interface.js');
184      $jpdd->addSourcedScript('scripts/jpdd.base.js');
185      $jpdd->addSourcedScript('scripts/jpdd.liaison.js');
186      $jpdd->addStyleSheet('styles/liaison.css');
187      $script = '';
188
189      // get the list of attendees for this event related to this
190      // organization:
191      $applied = $this->getApplyingPeople();
192
193      $listed_ids = array();
194
195      // get the remaining attendees affiliated with this
196      // organization 
197      // FIXME: this contains too many people at the moment, because it includes existing attendees.
198      $otheraffiliates = $this->getM2MPeers('person', 'affiliation');
199
200      // get the per-category requirements for this event:
201      $jpdd->prepClass('category');
202
203      $ret = '<div class="instructions">Please sign up teachers from your school by clicking and dragging their names to the appropriate subject areas on the left.<br/>'.
204        'New teachers can be added in the box below.<br/>'.
205        '<strong>Remember to click <input type="submit" value="Save Changes"/> before exiting!</strong></div>';
206      $script .= '$("li.affiliated_person").Draggable( {revert: true, ghosting: true} );
207$("li.affiliated_person a.deaffiliate").bind("click", JPDD.Liaison.clickdelete);
208$("fieldset.category").each( JPDD.Liaison.testapply );';
209
210      $ret .= '<table class="liaisonui"><tbody><tr><td>';
211
212      // hide the dropdown initially.  It will be showed if the liaison clicks the "attending this workshop" checkbox.
213      $dropdown = '<div id="newassign" style="display: none; padding-left: 1em;"><select name="newassign">'."\n<option>choose a workshop subject</option>\n";
214      reset($requirements);
215      while(list(,$req) = each($requirements)) {
216        $ret .= '<fieldset id="category_'.$req->getID().'" catval="'.(int)$req->getID().'" class="category discipline" min="'.(int)$req->_minimum.'" max="'.(int)$req->_maximum.'"><legend>'.$req->getTitle().'</legend><div class="notes"></div>
217<ul>
218';
219       
220        $dropdown .= '<option value="'.$req->getID().'">'.$req->getTitle().'</option>'."\n";
221        if (array_key_exists($req->getID(), $applied)) {
222          $ret .= join("\n", array_map(create_function('$x', 'return $x->getListItem("affiliated_person", '.$req->getID().', \'<a href="#" class="deaffiliate">[delete]</a>\');'), $applied[$req->getID()]));
223          $ids = array_map(create_function('$x', 'return $x->getID();'), $applied[$req->getID()]);
224          $listed_ids = array_merge($listed_ids, $ids);
225        }
226         
227        /*
228        $item = 0;
229        while ($item < $req->_minimum) {
230          $x = 'application_'.$req->getID().'_'.$item;
231          $ret .= '<input type="hidden" name="application_'.$req->getID().'" value="" id="'.$x.'" />';
232          $item++;
233        }
234        while ($item < $req->_maximum) {
235
236          $item++;
237        }
238        */
239        $ret .= '</ul></fieldset>';
240      }
241     
242      $dropdown .= '</select></div>';
243     
244      $ret .= '</td><td>';
245
246      // show all the affiliates in their own list:
247      $ret .= '<fieldset class="category" catval=""><legend>Available teachers</legend><div class="notes"></div><ul>'.
248        join("\n", array_map(create_function('$x', 'return $x->getListItem("affiliated_person", "", \'<a href="#" class="deaffiliate">[delete]</a>\');'), array_filter($otheraffiliates, create_function('$x', '$y = array('.join(',', $listed_ids).'); return !in_array($x->getID(), $y);')))).'
249</ul>
250</fieldset>
251';
252
253      $ret .= '</tr><tr><td><input type="submit" value="Save Changes"></td><td>';
254
255      // allow liaisons to create new people:
256      $ret .= '<fieldset><legend>Add a new teacher</legend>
257<label>First name:<br/><input type="text" name="first_name" value=""/></label><br/>
258<label>Last name:<br/><input type="text" name="last_name" value=""/></label><br/>
259<label>E-mail Address:<br/><input type="text" name="email" value=""/></label><br/>
260'.JPDD_Category::getInterestDropdown('primaryinterest', "Primary Focus?").'<br/>
261<label>Attending this workshop?<input type="checkbox" name="isattending" onchange="if (this.checked) { $(\'#newassign\').show() } else {$(\'#newassign\').hide();};" value="yes" /></label><br/>
262'.$dropdown.'<br/>
263</fieldset>';
264
265      $ret .= '</tr></tbody></table>';
266      $jpdd->addScriptChunk('$(document).ready(function() {'.$script.'});');
267      return '<form action="'.$jpdd->Path('liaison/organization/'.$this->getID()).'" method="post">'.
268        $ret.
269        $jpdd->getFormTokenHiddenInput().
270        '</form>';
271    }
272   
273    function handleLiaisonForm() {
274      global $jpdd;
275      // walk through the people supplied: if they're affiliated with
276      // the org in question, check their invitation status for the
277      // current session, and make sure it matches the input.
278
279      $affiliatedids = $this->getAffiliatedPersonIDs();
280      $acceptedcategories = array_map('intval', $jpdd->getValuesFromSQL('SELECT category_id FROM attendance_requirements WHERE event_id = '.$jpdd->getActiveEventID(), 'category_id'));
281
282      // we'll just ignore unaffiliated people:
283      $people = array_intersect_key($jpdd->getPostedIDtoIDMap('person'), array_flip($affiliatedids));
284
285      // and get the list of people who've been "de-affiliated":
286      $deaffiliateds = $jpdd->getPostedIDs('deaffiliate');
287
288      $unapplied = array();
289      reset($people);
290      while(list($person_id, $category) = each($people)) {
291        if (is_null($category) || !in_array($category, $acceptedcategories))
292          $unapplied[] = $person_id;
293        else {
294          $jpdd->executeSQL('DELETE FROM application WHERE event_id = '.$jpdd->getActiveEventID().' AND person_id = '.$person_id);
295          $jpdd->executeSQL('INSERT INTO application (event_id, person_id, category_id) VALUES ('.(int)$jpdd->getActiveEventID().', '.
296                            (int)$person_id.', '.$category.')');
297        }
298      }
299
300      reset($deaffiliateds);
301      while (list(,$pid) = each($deaffiliateds)) {
302        $jpdd->executeSQL('DELETE FROM affiliation WHERE person_id = '.$pid.' AND organization_id = '.$this->getID());
303      }
304     
305      if (count($unapplied))
306        $jpdd->executeSQL('DELETE FROM application WHERE event_id = '.$jpdd->getActiveEventID().' AND person_id IN ('.join(',', $unapplied).')');
307
308      if ($jpdd->arrayKeyIsNotEmpty('first_name', $_POST) || 
309          $jpdd->arrayKeyIsNotEmpty('last_name', $_POST) || 
310          $jpdd->arrayKeyIsNotEmpty('email', $_POST)) {
311
312        $acceptableinterests = JPDD_Category::getInterestIDs();
313
314        // FIXME: if the person fields are present, check if person
315        // already exists, as affiliated with the school.
316
317
318        // if not, create the person,
319        $newp = new JPDD_Person(array('data' => array('first_name' => $_POST['first_name'],
320                                                      'last_name' => $_POST['last_name'],
321                                                      'email' => $_POST['email'])));
322        $res = $newp->storeNewInDatabase();
323        if (false !== $res) {
324          // affiliate the person with the org:
325          $newp->addM2MPeers('organization', 'affiliation', array($this->getID()));
326       
327          if ($jpdd->arrayKeyIsNotEmpty('isattending', $_POST) && ($_POST['newassign'] == 'yes') &&
328              $jpdd->arrayKeyIsNotEmpty('newassign', $_POST) && in_array((int)$_POST['newassign'], $acceptedcategories)) {
329            // FIXME: if the org already has enough for this category, put this user into "alternate"?
330            $jpdd->executeSQL('INSERT INTO application (event_id, person_id, category_id) VALUES ('.(int)$jpdd->getActiveEventID().', '.
331                              $newp->getID().', '.(int)$_POST['newassign'].')');
332          }
333          if ($jpdd->arrayKeyIsNotEmpty('primaryinterest', $_POST) && in_array((int)$_POST['primaryinterest'], $acceptableinterests)) {
334            $sql = 'INSERT INTO person_interest (person_id, category_id) VALUES ('.
335              $newp->getID().', '.(int)$_POST['primaryinterest'].')';
336            $jpdd->executeSQL($sql);
337          }
338        }
339      }
340    }
341
342        function getDetailInnards() {
343      global $jpdd;
344      $ret = '';
345     
346      if (!is_null($this->getWebsite())) 
347        $ret .= '<a class="outlink" href="'.$this->getWebsite().'">Find out more about '.$this->getTitle().'</a>';
348
349      if ($jpdd->isAuthenticated() && $jpdd->_authenticated_user->hasAllOfThesePrivileges('Manage Signups')) 
350        $ret .= '<div><a href="'.$jpdd->Path('liaison', 'organization', $this->getID()).'">See the liaison view for '.htmlentities($this->getTitle()).'</a></div>';
351
352      // FIXME: maybe show all affiliated people?
353      if ($jpdd->isAuthenticated() && $jpdd->_authenticated_user->hasAllOfThesePrivileges('List People')) {
354        $ret .= $this->getListOfPeopleForEvent($jpdd->getActiveEventID());
355      }
356      return $ret;
357    }
358
359    function getListOfPeopleForEvent($event) {
360      global $jpdd;
361      $ret = '';
362      $event = (int)$event;
363
364      $peops = $this->getM2MPeers('person', 'affiliation');
365
366      // show people with specific roles for this conference:
367      $roles = $jpdd->getKeyValuePairsFromSQL('SELECT person_id, role.title AS title FROM person_role JOIN role ON (role_id = role.id)
368WHERE event_id = '.$event.' AND organization_id = '.$this->getID(), 'person_id', 'title');
369      $applications = $jpdd->getKeyValuePairsFromSQL('SELECT person_id, category.title AS title FROM application JOIN
370category ON (category_id = category.id) JOIN affiliation USING (person_id) WHERE event_id = '.$event.' AND organization_id = '.$this->getID(), 'person_id', 'title');
371
372      $ret .= '<h3>'.count($peops).(count($peops) == 1 ? ' Affiliated Person' : ' Affiliated People').'</h3><ul>'."\n";
373      reset($peops);
374      while(list(,$x) = each($peops))
375        $ret .= "<li>".$x->getLinkedTitle()." ".$x->getWorkshopText(false, $event).
376          (array_key_exists($x->getID(), $roles) ? ' <span class="roletag">'.$roles[$x->getID()].'</span>' : '').
377          (array_key_exists($x->getID(), $applications) ? ' <span class="applicationtag">'.$applications[$x->getID()].'</span>' : '')."</li>\n";
378      $ret .= "</ul>\n";
379          return $ret;
380        }
381  }
382
383}
Note: See TracBrowser for help on using the repository browser.