91 |
101 |
189 |
--------------------------------------------------------------------------------
/site/sugarRestClient.php:
--------------------------------------------------------------------------------
1 | $value) {
13 | $return[] = array('name' => $key, 'value' => $value);
14 | }
15 |
16 | return $return;
17 | }
18 |
19 | /**
20 | * Converts a SugarCRM-REST compatible name_value_list to an Array
21 | *
22 | * @param array $data
23 | * @return array
24 | */
25 | function convertNVLToArray($data)
26 | {
27 | $return = array();
28 | foreach ($data as $row) {
29 | $return[$row['name']] = $row['value'];
30 | }
31 |
32 | return $return;
33 | }
34 |
35 | class sugarRestClient
36 | {
37 |
38 | /**
39 | * SugarCRM Session ID
40 | *
41 | * @var string
42 | */
43 | protected $sid;
44 | /**
45 | * Rest object
46 | *
47 | * @var string
48 | */
49 | private $rest_url;
50 | /**
51 | * SugarCRM User
52 | *
53 | * @var string
54 | */
55 | private $rest_user;
56 | /**
57 | * SugarCRM Pass
58 | *
59 | * @var string
60 | */
61 | private $rest_pass;
62 |
63 | public function __construct()
64 | {
65 | include_once 'components/com_advancedopenportal/models/advancedopenportal.php';
66 | $settings = AdvancedOpenPortalModelAdvancedOpenPortal::getSettings();
67 | $this->rest_url = $settings->sugar_url . "/service/v4_1/rest.php";
68 | $this->base_url = $settings->sugar_url;
69 | $this->rest_user = $settings->sugar_user;
70 | $this->rest_pass = $settings->sugar_pass;
71 | }
72 |
73 | /**
74 | * Login with user credentials
75 | *
76 | * @return boolean
77 | */
78 | public function login()
79 | {
80 | $login_params = array(
81 | 'user_name' => $this->rest_user,
82 | 'password' => $this->rest_pass,
83 | );
84 |
85 | $result = $this->rest_request('login', array(
86 | 'user_auth' => $login_params,
87 | "application_name" => "",
88 | 'name_value_list' => array(array('name' => 'notifyonsave', 'value' => 'true'))
89 | ));
90 |
91 | if (isset($result['id'])) {
92 | $this->sid = $result['id'];
93 |
94 | return $result['id'];
95 | }
96 |
97 | if (isset($result['name'])) {
98 | return false;
99 | }
100 |
101 | return false;
102 | }
103 |
104 | /**
105 | * convert to rest request and return decoded array
106 | *
107 | * @param $call_name
108 | * @param $call_arguments
109 | * @return array
110 | */
111 | private function rest_request($call_name, $call_arguments)
112 | {
113 |
114 | ob_start();
115 | $ch = curl_init();
116 |
117 | $post_data = array(
118 | 'method' => $call_name,
119 | 'input_type' => 'JSON',
120 | 'response_type' => 'JSON',
121 | 'rest_data' => json_encode($call_arguments)
122 | );
123 |
124 | curl_setopt($ch, CURLOPT_URL, $this->rest_url);
125 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
126 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
127 | curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
128 | curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
129 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
130 | $output = curl_exec($ch);
131 |
132 | $response_data = json_decode($output, true);
133 |
134 | curl_close($ch);
135 | ob_end_flush();
136 |
137 | return $response_data;
138 | }
139 |
140 | /**
141 | * Logout
142 | */
143 | public function logout()
144 | {
145 | $this->rest_request('logout', array(
146 | 'session' => $this->sid,
147 | ));
148 |
149 | $this->sid = null;
150 | }
151 |
152 | /**
153 | * Retrieves a list of entries
154 | *
155 | * @param string $module
156 | * @param string $query
157 | * @param string $order_by
158 | * @param integer $offset
159 | * @param array $select_fields
160 | * @param array $related_fields
161 | * @param string $max_results
162 | * @param boolean $deleted
163 | * @return bool|array
164 | */
165 | public function getEntryList(
166 | $module,
167 | $query = '',
168 | $order_by = '',
169 | $offset = 0,
170 | $select_fields = array(),
171 | $related_fields = array(),
172 | $max_results = '0',
173 | $deleted = false
174 | ) {
175 | if (!$this->sid) {
176 | return false;
177 | }
178 |
179 | $result = $this->rest_request('get_entry_list', array(
180 | 'session' => $this->sid,
181 | 'module_name' => $module,
182 | 'query' => $query,
183 | 'order_by' => $order_by,
184 | 'offset' => $offset,
185 | 'select_fields' => $select_fields,
186 | 'link_name_to_fields_array' => $related_fields,
187 | 'max_results' => $max_results,
188 | 'deleted' => $deleted,
189 | ));
190 |
191 | if ($result['result_count'] > 0) {
192 | return $result;
193 | }
194 |
195 | return false;
196 | }
197 |
198 | /**
199 | * @param $module
200 | * @param $id
201 | * @param array $select_fields
202 | * @param array $related_fields
203 | * @return array|bool
204 | */
205 | public function getEntry($module, $id, $select_fields = array(), $related_fields = array())
206 | {
207 | if (!$this->sid) {
208 | return false;
209 | }
210 |
211 | $result = $this->rest_request('get_entry', array(
212 | 'session' => $this->sid,
213 | 'module_name' => $module,
214 | 'id' => $id,
215 | 'select_fields' => $select_fields,
216 | 'link_name_to_fields_array' => $related_fields,
217 | ));
218 |
219 | if (!isset($result['result_count']) || $result['result_count'] > 0) {
220 | return $result;
221 | }
222 |
223 | return false;
224 | }
225 |
226 | /**
227 | * Adds or changes an entry
228 | *
229 | * @param string $module
230 | * @param array $data
231 | * @return bool|array
232 | */
233 | public function setEntry($module, $data)
234 | {
235 | if (!$this->sid) {
236 | return false;
237 | }
238 |
239 | return $this->rest_request('set_entry', array(
240 | 'session' => $this->sid,
241 | 'module_name' => $module,
242 | 'name_value_list' => convertArrayToNVL(str_replace("&", "%26", $data)),
243 | ));
244 | }
245 |
246 | /**
247 | * Creates a new relationship-entry
248 | *
249 | * @param string $module1
250 | * @param string $module1_id
251 | * @param string $module2
252 | * @param string $module2_id
253 | * @return bool|array
254 | */
255 | public function setRelationship($module1, $module1_id, $module2, $module2_id)
256 | {
257 | if (!$this->sid) {
258 | return false;
259 | }
260 |
261 | $data = array(
262 | 'session' => $this->sid,
263 | 'module_name' => $module1,
264 | 'module_id' => $module1_id,
265 | 'link_field_name' => $module2,
266 | '$related_ids' => array($module2_id),
267 | );
268 |
269 | return $this->rest_request('set_relationship', $data);
270 | }
271 |
272 | /**
273 | * Retrieves relationship data
274 | *
275 | * @param string $module_name
276 | * @param string $module_id
277 | * @param string $related_module
278 | * @param string $related_module_query
279 | * @param array $related_fields
280 | * @param array $related_module_link_name_to_fields_array
281 | * @param bool $deleted
282 | * @param string $order_by
283 | * @param int $offset
284 | * @param bool $limit
285 | * @return bool|array
286 | */
287 | public function getRelationships(
288 | $module_name,
289 | $module_id,
290 | $related_module,
291 | $related_module_query = '',
292 | $related_fields = array(),
293 | $related_module_link_name_to_fields_array = array(),
294 | $deleted = false,
295 | $order_by = '',
296 | $offset = 0,
297 | $limit = false
298 | ) {
299 | $result = $this->rest_request('get_relationships', array(
300 | 'session' => $this->sid,
301 | 'module_name' => $module_name,
302 | 'module_id' => $module_id,
303 | 'link_field_name' => $related_module,
304 | 'related_module_query' => $related_module_query,
305 | 'related_fields' => $related_fields,
306 | 'related_module_link_name_to_fields_array' => $related_module_link_name_to_fields_array,
307 | 'deleted' => $deleted,
308 | 'order_by' => $order_by,
309 | 'offset' => $offset,
310 | 'limit' => $limit,
311 | ));
312 |
313 | if (!isset($result['error']['number']) || $result['error']['number'] == 0) {
314 | return $result;
315 | }
316 |
317 | return false;
318 | }
319 |
320 | /**
321 | * Retrieves a module field
322 | *
323 | * @param string $module
324 | * @param string $field
325 | * @return bool|array
326 | */
327 | public function getModuleFields($module, $field)
328 | {
329 | if (!$this->sid) {
330 | return false;
331 | }
332 |
333 | $result = $this->rest_request('get_module_fields', array(
334 | 'session' => $this->sid,
335 | 'module_name' => $module,
336 | ));
337 |
338 | if ($result > 0) {
339 | return $result['module_fields'][$field];
340 | }
341 |
342 | return false;
343 | }
344 |
345 | /**
346 | * @param $module
347 | * @return bool|array
348 | */
349 | public function getAllModuleFields($module)
350 | {
351 | if (!$this->sid) {
352 | return false;
353 | }
354 |
355 | $result = $this->rest_request('get_module_fields', array(
356 | 'session' => $this->sid,
357 | 'module_name' => $module,
358 | ));
359 |
360 | if ($result > 0) {
361 | return $result['module_fields'];
362 | }
363 |
364 | return false;
365 | }
366 |
367 | /**
368 | * @param $note_id
369 | * @return array|bool
370 | */
371 | public function get_note_attachment($note_id)
372 | {
373 | if (!$this->sid) {
374 | return false;
375 | }
376 |
377 | $call_arguments = array(
378 | 'session' => $this->sid,
379 | 'id' => $note_id
380 | );
381 |
382 | return $this->rest_request('get_note_attachment',
383 | $call_arguments
384 | );
385 | }
386 |
387 | /**
388 | * @param $note_id
389 | * @param $file_name
390 | * @param $file_location
391 | * @return array|bool
392 | */
393 | public function set_note_attachment($note_id, $file_name, $file_location)
394 | {
395 | if (!$this->sid) {
396 | return false;
397 | }
398 |
399 | return $this->rest_request('set_note_attachment', array(
400 | 'session' => $this->sid,
401 | 'note' => array(
402 | 'id' => $note_id,
403 | 'filename' => $file_name,
404 | 'file' => base64_encode(file_get_contents($file_location)),
405 | ),
406 | ));
407 | }
408 |
409 | /**
410 | * @param $id
411 | * @return array|bool
412 | */
413 | public function get_document_revision($id)
414 | {
415 | if (!$this->sid) {
416 | return false;
417 | }
418 |
419 | return $this->rest_request('get_document_revision', array(
420 | 'session' => $this->sid,
421 | 'id' => $id,
422 | ));
423 | }
424 |
425 | /**
426 | * @param $document_id
427 | * @param $file_name
428 | * @param $file_location
429 | * @param int $revision_number
430 | * @return array|bool
431 | */
432 | public function set_document_revision($document_id, $file_name, $file_location, $revision_number = 1)
433 | {
434 | if (!$this->sid) {
435 | return false;
436 | }
437 |
438 | return $this->rest_request('set_document_revision', array(
439 | 'session' => $this->sid,
440 | 'document_revision' => array(
441 | 'id' => $document_id,
442 | 'revision' => $revision_number,
443 | 'filename' => $file_name,
444 | 'file' => base64_encode(file_get_contents($file_location)),
445 | ),
446 | ));
447 |
448 |
449 | }
450 | }
451 |
--------------------------------------------------------------------------------
/site/controller.php:
--------------------------------------------------------------------------------
1 | id){
24 | $msg = JText::_('COM_ADVANCEDOPENPORTAL_LOGIN_REQUIRED');
25 | }elseif(SugarCasesConnection::isUserBlocked($user)){
26 | $msg = JText::_('COM_ADVANCEDOPENPORTAL_PORTAL_USER_BLOCKED');
27 | }else{
28 | $msg = JText::_('COM_ADVANCEDOPENPORTAL_NO_PORTAL_ACCOUNT');
29 | }
30 | if($view != 'listcases'){
31 | JFactory::getApplication()->redirect(JURI::base(), $msg, 'error');
32 | }else{
33 | JFactory::getApplication()->enqueueMessage($msg, 'error');
34 | parent::display($cachable,$url_params);
35 | }
36 | }
37 | }
38 |
39 | private function getToggletatus($status){
40 | if(strpos($status, 'Closed') === 0){
41 | return "Open_New";
42 | }elseif(strpos($status, 'Open') === 0){
43 | return "Closed_Closed";
44 | }
45 | return null;
46 | }
47 |
48 | public function toggleCaseStatus(){
49 | $con = SugarCasesConnection::getInstance();
50 | require_once 'components/com_advancedopenportal/models/advancedopenportal.php';
51 | $settings = AdvancedOpenPortalModelAdvancedOpenPortal::getSettings();
52 | $settings->allow_case_reopen;
53 | $settings->allow_case_closing;
54 |
55 | $newStatus = $this->getToggletatus($_REQUEST['case_status']);
56 | if(($newStatus == 'Open_New' && !$settings->allow_case_reopen) || $newStatus == 'Closed_Closed' && !$settings->allow_case_closing){
57 | JFactory::getApplication()->redirect(JURI::base()."?option=com_advancedopenportal&view=showcase&id=".$_REQUEST['case_id']);
58 | return;
59 | }
60 | $user =& JFactory::getUser();
61 | $case = $con->getCase($_REQUEST['case_id'],$user->getParam("sugarid"));
62 | if(!$case){
63 | JFactory::getApplication()->redirect(JURI::base()."?option=com_advancedopenportal");
64 | return;
65 | }
66 |
67 | $con->setCaseStatus($_REQUEST['case_id'],$newStatus);
68 | JFactory::getApplication()->redirect(JURI::base()."?option=com_advancedopenportal&view=showcase&id=".$_REQUEST['case_id']);
69 | }
70 |
71 |
72 | function newcase(){
73 | $errors = array();
74 | $subject = JRequest::getVar("subject");
75 | $description = JRequest::getVar("description",null, 'default', 'html',4);
76 | $type = JRequest::getVar("type");
77 | $priority = JRequest::getVar("priority");
78 | $file_count = JRequest::getVar("file_count");
79 | $files = array();
80 | for($count = 1; $count <= $file_count; $count++){
81 | if(!array_key_exists("file".$count,$_FILES)){
82 | continue;
83 | }
84 | $fileError = $_FILES["file".$count]['error'];
85 | if ($fileError > 0){
86 | switch ($fileError){
87 | case 1:
88 | case 2:
89 | $errors["file".$count] = "File too large";
90 | break;
91 | case 3:
92 | $errors["file".$count] = "Partial upload";
93 | break;
94 | }
95 | continue;
96 | }
97 | $files[$_FILES["file".$count]['name']] = $_FILES["file".$count]['tmp_name'];
98 | }
99 | $user = JFactory::getUser();
100 | $contact_id = $user->getParam("sugarid");
101 | $casesConnection = SugarCasesConnection::getInstance();
102 | $new_case = $casesConnection->newCase($contact_id, $subject, $description, $type, $priority, $files);
103 | JFactory::getApplication()->redirect(JURI::base()."?option=com_advancedopenportal&view=showcase&id=".$new_case);
104 | }
105 |
106 | function addupdate(){
107 | $case_id = JRequest::getVar("case_id");
108 | $description = JRequest::getVar("update_text",null, 'default', 'html',4);
109 | if(!$case_id){
110 | echo json_encode(array('Case Id is required'));
111 | return;
112 | }
113 | if(!$description){
114 | echo json_encode(array('Update Text is required'));
115 | return;
116 | }
117 | $user = JFactory::getUser();
118 | $contact_id = $user->getParam("sugarid");
119 | $casesConnection = SugarCasesConnection::getInstance();
120 | $case_update = $casesConnection->postUpdate($case_id,$description,$contact_id);
121 | $file_count = JRequest::getVar("file_count");
122 |
123 | if($file_count){
124 | $case_update->notes = array();
125 | $files = array();
126 | for($count = 1; $count <= $file_count; $count++){
127 | if(!array_key_exists("file".$count,$_FILES)){
128 | continue;
129 | }
130 | $fileError = $_FILES["file".$count]['error'];
131 | if ($fileError > 0){
132 | switch ($fileError){
133 | case 1:
134 | case 2:
135 | $errors["file".$count] = "File too large";
136 | break;
137 | case 3:
138 | $errors["file".$count] = "Partial upload";
139 | break;
140 | }
141 | continue;
142 | }
143 | $files[$_FILES["file".$count]['name']] = $_FILES["file".$count]['tmp_name'];
144 | }
145 | $response = $casesConnection->addFiles($case_id, $case_update->id, $contact_id, $files);
146 | foreach($response as $res){
147 | $case_update->notes[] = $res;
148 | }
149 | }
150 |
151 |
152 | echo json_encode($case_update);
153 | }
154 |
155 | function create() {
156 | // Get the document object.
157 | $document =& JFactory::getDocument();
158 |
159 | // Set the MIME type for JSON output.
160 | $document->setMimeEncoding('application/json');
161 | //Connect to Sugar via Rest interface
162 | include_once 'components/com_advancedopenportal/sugarRestClient.php';
163 | $restClient = new sugarRestClient();
164 | $restClient->login();
165 |
166 | if(isset($_REQUEST['sug']) && $_REQUEST['sug'] != ''){
167 |
168 | $contacts = $restClient->getEntry('Contacts',$_REQUEST['sug'],array('name','email1'));
169 | if(!empty($contacts['entry_list'])){
170 |
171 | $contact = $contacts['entry_list'][0]['name_value_list'];
172 |
173 | $pass = JUserHelper::genRandomPassword();
174 | $pass_c = JUserHelper::getCryptedPassword($pass);
175 |
176 | $data = array();
177 | $data['fullname'] = $contact['name']['value'];
178 | $data['email'] = $contact['email1']['value'];
179 | $data['password'] = $pass_c;
180 | $data['username'] = $contact['email1']['value'];
181 |
182 | $user = JUser::getInstance();
183 |
184 | jimport('joomla.application.component.helper');
185 |
186 | $config = JFactory::getConfig();
187 | $params = JComponentHelper::getParams('com_users');
188 | // Default to Registered.
189 | $defaultUserGroup = $params->get('new_usertype', 2);
190 |
191 | $acl = JFactory::getACL();
192 |
193 | $user->set('id' , 0);
194 | $user->set('name' , $data['fullname']);
195 | $user->set('username' , $data['username']);
196 | $user->set('password' , $data['password']);
197 | $user->set('email' , $data['email']); // Result should contain an email (check)
198 | $user->set('usertype' , 'deprecated');
199 | $user->set('groups' , array($defaultUserGroup));
200 | $user->setParam('sugarid', $_REQUEST['sug']);
201 |
202 | //If autoregister is set let's register the user
203 | $autoregister = isset($options['autoregister']) ? $options['autoregister'] : $params->get('autoregister', 1);
204 |
205 | if ($autoregister) {
206 | if (!$user->save()) {
207 | echo json_encode(array("error"=>"Failed to save user ".implode(" ",$user->getErrors())));
208 | JFactory::getApplication()->close();
209 | return JError::raiseWarning('SOME_ERROR_CODE', $user->getError());
210 | }
211 | }
212 | else {
213 | // No existing user and autoregister off, this is a temporary user.
214 | $user->set('tmp_user', true);
215 | }
216 |
217 | $restClient->setEntry('Contacts',array('id'=>$_REQUEST['sug'], 'joomla_account_id' => $user->id,'joomla_account_access' => $pass, ));
218 | echo json_encode(array("success"=>true));
219 | }
220 | }else{
221 | echo json_encode(array("error"=>"ID Not specified"));
222 | }
223 | JFactory::getApplication()->close();
224 | }
225 |
226 | function update_e(){
227 | //Connect to Sugar via Rest interface
228 | include_once 'components/com_advancedopenportal/sugarRestClient.php';
229 | $restClient = new sugarRestClient();
230 | $restClient->login();
231 |
232 | if(isset($_REQUEST['sug']) && $_REQUEST['sug'] != ''){
233 |
234 | $contacts = $restClient->getEntry('Contacts',$_REQUEST['sug'],array('name','email1','joomla_account_id'));
235 |
236 | if(!empty($contacts['entry_list'])){
237 | $contact = $contacts['entry_list'][0]['name_value_list'];
238 |
239 | $userId = (int) $_REQUEST['uid'];
240 |
241 | // Check for a valid user id.
242 | if (!$userId) {
243 | $this->setError(JText::_('COM_USERS_ACTIVATION_TOKEN_NOT_FOUND'));
244 | return false;
245 | }
246 |
247 | // Load the users plugin group.
248 | JPluginHelper::importPlugin('user');
249 |
250 | // Activate the user.
251 | $user = JFactory::getUser($userId);
252 |
253 | $user->set('name', $contact['name']['value']);
254 | $user->set('email', $contact['email1']['value']);
255 | $user->set('username', $contact['email1']['value']);
256 |
257 | $user->save();
258 | }
259 | }
260 |
261 | }
262 |
263 | function disable_user(){
264 | $this->setUserDisabled(1);
265 | }
266 |
267 | function enable_user(){
268 | $this->setUserDisabled(0);
269 | }
270 |
271 | private function setUserDisabled($disable){
272 | if(isset($_REQUEST['sug']) && $_REQUEST['sug'] != ''){
273 | include_once 'components/com_advancedopenportal/sugarRestClient.php';
274 | $restClient = new sugarRestClient();
275 | $restClient->login();
276 | $contacts = $restClient->getEntry('Contacts',$_REQUEST['sug'],array('joomla_account_id'));
277 | if(!empty($contacts['entry_list'])){
278 | $contact = $contacts['entry_list'][0]['name_value_list'];
279 | $userId = (int) $_REQUEST['uid'];
280 | if (!$userId) {
281 | echo json_encode(array("error"=>JText::_('COM_USERS_ACTIVATION_TOKEN_NOT_FOUND')));
282 |
283 | }else{
284 | JPluginHelper::importPlugin('user');
285 | $user = JFactory::getUser($userId);
286 | $user->setParam('aop_block', $disable);
287 | $user->save();
288 | echo json_encode(array("success"=>true));
289 | }
290 | }
291 | }
292 | JFactory::getApplication()->close();
293 | }
294 |
295 |
296 | }
297 |
--------------------------------------------------------------------------------
/site/models/SugarCasesConnection.php:
--------------------------------------------------------------------------------
1 |
23 | */
24 | include_once 'components/com_advancedopenportal/sugarRestClient.php';
25 | include_once 'components/com_advancedopenportal/models/SugarCase.php';
26 | include_once 'components/com_advancedopenportal/models/SugarUpdate.php';
27 |
28 |
29 | class SugarCasesConnection {
30 |
31 | private $case_fields = array('id','name','date_entered','date_modified','description','case_number','type','status','state','priority','contact_created_by_id', 'contact_created_by_name');
32 | private $case_update_fields = array('id','name','date_entered','date_modified','description','contact','contact_id', 'internal', 'assigned_user_id');
33 | private $contact_fields = array('id','first_name','last_name','date_entered','date_modified','description','portal_user_type','account_id');
34 | private $user_fields = array('id','first_name', 'last_name', 'date_entered','date_modified','description');
35 | private $note_fields = array('id','name', 'date_entered','date_modified','description','filename','file_url');
36 |
37 | private static $singleton;
38 |
39 | public function __construct() {
40 |
41 | $this->restClient = new sugarRestClient();
42 | $this->cache = & JFactory::getCache();
43 | $this->cache->setCaching( 1 );
44 | if(!$this->restClient->login()){
45 | throw new Exception("Failed to connect to sugar. Please check your settings.");
46 | }
47 | }
48 |
49 | public static function getInstance(){
50 | if(!self::$singleton){
51 | self::$singleton = new SugarCasesConnection();
52 | }
53 | return self::$singleton;
54 | }
55 |
56 | private function getCaseFields(){
57 | return $this->cache->call(array($this->restClient,'getAllModuleFields'),'Cases');
58 | }
59 |
60 | public function getTypes(){
61 | $fields = $this->getCaseFields();
62 | return $fields['type'];
63 | }
64 |
65 | public function getPriorities(){
66 | $fields = $this->getCaseFields();
67 | return $fields['priority'];
68 | }
69 |
70 | public function getStatuses(){
71 | $fields = $this->getCaseFields();
72 | return $fields['status'];
73 | }
74 |
75 | public function getStates(){
76 | $fields = $this->getCaseFields();
77 | return $fields['state'];
78 | }
79 |
80 | public function getCaseStatusDisplay($status){
81 | $statuses = $this->getStatuses();
82 | foreach($statuses['options'] as $option){
83 | if($option['name'] == $status){
84 | return $option['value'];
85 | }
86 | }
87 | return $status;
88 | }
89 |
90 | public function addFiles($caseId, $caseUpdateId, $contactId, $files){
91 | $results = array();
92 | //For every file, create a new note. Add an attachment and link the note to the
93 | foreach($files as $file_name => $file_location){
94 | $note_data = array(
95 | 'name' => "Case Attachment: $file_name",
96 | 'parent_id' => $caseUpdateId,
97 | 'parent_type' => 'AOP_Case_Updates',
98 | );
99 | $new_note = $this->restClient->setEntry('Notes',$note_data);
100 | $note_id = $new_note['id'];
101 | $this->restClient->set_note_attachment($note_id, $file_name, $file_location);
102 | $this->restClient->setRelationship("Notes",$note_id,"contact",$contactId);
103 | $results[] = array('id'=>$note_id,'file_name'=>$file_name);
104 | }
105 | return $results;
106 | }
107 |
108 | public function newCase($contact_id,$subject, $description,$type,$priority,$files){
109 |
110 | $data = array("contact_id"=>$contact_id,
111 | "contact_created_by_id"=>$contact_id,
112 | "name" => $subject,
113 | "status" => 'New',
114 | "description" => $description,
115 | "type" => $type,
116 | "priority" => $priority,
117 | 'update_date_entered' => true,
118 | );
119 | //TODO: Check call results
120 | //Create the actual case.
121 | $response = $this->restClient->setEntry('Cases',$data);
122 | $this->restClient->setRelationship("Cases",$response['id'],"contacts",$contact_id);
123 | //For every file, create a new note. Add an attachment and link the note to the
124 | foreach($files as $file_name => $file_location){
125 | $note_data = array(
126 | 'name' => "Case Attachment: $file_name",
127 | );
128 | $new_note = $this->restClient->setEntry('Notes',$note_data);
129 | $note_id = $new_note['id'];
130 | $this->restClient->set_note_attachment($note_id, $file_name, $file_location);
131 | $this->restClient->setRelationship("Notes",$note_id,"cases",$response['id']);
132 | $this->restClient->setRelationship("Notes",$note_id,"contact",$contact_id);
133 | }
134 | return $response['id'];
135 | }
136 |
137 | public function postUpdate($case_id,$update_text, $contact_id){
138 | $data = array();
139 | //TODO: Add validation that this user can update this case.
140 | $data['name'] = $update_text;
141 | $data['description'] = nl2br($update_text);
142 | $data['description'] = str_replace("\n", "", $data['description']);
143 | $data['contact_id'] = $contact_id;
144 | $data['case_id'] = $case_id;
145 | $response = $this->restClient->setEntry('AOP_Case_Updates',$data);
146 | return $this->getUpdate($response['id']);
147 |
148 | }
149 |
150 | public function getUpdate($update_id){
151 | $sugarupdate = $this->restClient->getEntry("AOP_Case_Updates",$update_id,$this->case_update_fields,
152 | array(
153 | array('name'=>'contact',
154 | 'value' =>
155 | $this->contact_fields
156 | ),
157 | array('name'=>'assigned_user_link',
158 | 'value' =>
159 | $this->user_fields
160 | )));
161 | //TODO: Check exists
162 | $update = new SugarUpdate($sugarupdate['entry_list'][0],$sugarupdate['relationship_list'][0]);
163 | return $update;
164 | }
165 |
166 | public function getNoteAttachment($note_id){
167 | $attachment = $this->restClient->get_note_attachment($note_id);
168 | return $attachment['note_attachment'];
169 | }
170 |
171 | public function setCaseStatus($caseId,$newStatus){
172 | $state = explode('_',$newStatus,2);
173 | $state = array_shift($state);
174 | $caseData = array(
175 | 'id' => $caseId,
176 | 'status' => $newStatus,
177 | 'state' => $state,
178 | );
179 | return $this->restClient->setEntry('Cases',$caseData);
180 | }
181 |
182 | public function getCase($case_id, $contact_id)
183 | {
184 | $sugarcase = $this->restClient->getEntry("Cases", $case_id, $this->case_fields,
185 | array(
186 | array(
187 | 'name' => 'aop_case_updates',
188 | 'value' => $this->case_update_fields
189 | ),
190 | array(
191 | 'name' => 'notes',
192 | 'value' => $this->note_fields
193 | ),
194 | array(
195 | 'name' => 'accounts',
196 | 'value' => array('id')
197 | ),
198 | array(
199 | 'name' => 'contacts',
200 | 'value' => array('id')
201 | ),
202 | ));
203 |
204 | $case = new SugarCase($sugarcase['entry_list'][0], $sugarcase['relationship_list'][0]);
205 |
206 | $contact = $this->getContact($contact_id);
207 | $access = false;
208 |
209 | if ($contact->portal_user_type === 'Account' && !empty($contact->account_id)) {
210 | foreach ($case->accounts as $account) {
211 | if ($contact->account_id === $account->id) {
212 | $access = true;
213 | break;
214 | }
215 | }
216 | } else {
217 | foreach ($case->contacts as $caseContact) {
218 | if ($contact->id === $caseContact->id) {
219 | $access = true;
220 | break;
221 | }
222 | }
223 | }
224 |
225 | if (!$access) {
226 | return null;
227 | }
228 |
229 | //Grab all updates and related contacts in one go
230 | $sugarupdates = $this->restClient->getRelationships('Cases', $case_id, 'aop_case_updates', '',
231 | $this->case_update_fields,
232 | array(
233 | array(
234 | 'name' => 'contact',
235 | 'value' => $this->contact_fields
236 | ),
237 | array(
238 | 'name' => 'assigned_user_link',
239 | 'value' => $this->user_fields
240 | ),
241 | array(
242 | 'name' => 'notes',
243 | 'value' => $this->note_fields
244 | )
245 | )
246 | );
247 |
248 | $newupdates = array();
249 | foreach ($sugarupdates['entry_list'] as $index => $sugarupdate) {
250 | $update = new SugarUpdate($sugarupdate, $sugarupdates['relationship_list'][$index]);
251 | if ($update->internal) {
252 | continue;
253 | }
254 | $newupdates[] = $update;
255 | }
256 | usort($newupdates, function ($a, $b) {
257 | return strtotime($a->date_entered) - (strtotime($b->date_entered));
258 | });
259 |
260 | $case->aop_case_updates = $newupdates;
261 |
262 | return $case;
263 | }
264 |
265 | public function getContact($contactId){
266 | $sugarcontact = $this->restClient->getEntry("Contacts",$contactId,$this->contact_fields);
267 | $contact = new SugarUpdate($sugarcontact['entry_list'][0],$sugarcontact['relationship_list'][0]);
268 | return $contact;
269 | }
270 |
271 | public function getCases($contact_id)
272 | {
273 | $contact = $this->getContact($contact_id);
274 | if ($contact->portal_user_type === 'Account' && !empty($contact->account_id)) {
275 | $cases = $this->restClient->getRelationships('Accounts', $contact->account_id, 'cases', '', $this->case_fields);
276 | } else {
277 | $cases = $this->restClient->getRelationships('Contacts', $contact_id, 'cases', '', $this->case_fields);
278 | }
279 |
280 | return $this->fromSugarCases($cases);
281 | }
282 |
283 | private function fromSugarCases($sugarcases){
284 | $cases = array();
285 | foreach($sugarcases['entry_list'] as $sugarcase){
286 | $cases[] = new SugarCase($sugarcase, array());
287 | }
288 | return $cases;
289 | }
290 |
291 | public static function isValidPortalUser($user){
292 | return !empty($user->id) && $user->getParam("sugarid");
293 | }
294 |
295 | public static function isUserBlocked($user){
296 | return $user->getParam("aop_block");
297 | }
298 |
299 | private function getContactData($sugarId,$user){
300 | $data = array();
301 | if($sugarId){
302 | $data['id'] = $sugarId;
303 | }
304 | $name = explode(' ',$user['name'],2);
305 |
306 | $data['first_name'] = empty($name[0]) ? '' : $name[0];
307 | $data['last_name'] = empty($name[1]) ? '' : $name[1];
308 | $data['email'] = $user['email'];
309 | $data['email1'] = $user['email'];
310 | $data['joomla_account_id'] = $user['id'];
311 | return $data;
312 | }
313 |
314 | public function updateOrCreateContact($sugarId,$user){
315 | $contactData = $this->getContactData($sugarId, $user);
316 | $res = $this->restClient->setEntry('Contacts',$contactData);
317 | return $res;
318 | }
319 |
320 | }
321 |
--------------------------------------------------------------------------------
/site/js/jquery.form.min.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery Form Plugin; v20130616
3 | * http://jquery.malsup.com/form/
4 | * Copyright (c) 2013 M. Alsup; Dual licensed: MIT/GPL
5 | * https://github.com/malsup/form#copyright-and-license
6 | */
7 | ;(function(e){"use strict";function t(t){var r=t.data;t.isDefaultPrevented()||(t.preventDefault(),e(this).ajaxSubmit(r))}function r(t){var r=t.target,a=e(r);if(!a.is("[type=submit],[type=image]")){var n=a.closest("[type=submit]");if(0===n.length)return;r=n[0]}var i=this;if(i.clk=r,"image"==r.type)if(void 0!==t.offsetX)i.clk_x=t.offsetX,i.clk_y=t.offsetY;else if("function"==typeof e.fn.offset){var o=a.offset();i.clk_x=t.pageX-o.left,i.clk_y=t.pageY-o.top}else i.clk_x=t.pageX-r.offsetLeft,i.clk_y=t.pageY-r.offsetTop;setTimeout(function(){i.clk=i.clk_x=i.clk_y=null},100)}function a(){if(e.fn.ajaxSubmit.debug){var t="[jquery.form] "+Array.prototype.join.call(arguments,"");window.console&&window.console.log?window.console.log(t):window.opera&&window.opera.postError&&window.opera.postError(t)}}var n={};n.fileapi=void 0!==e("").get(0).files,n.formdata=void 0!==window.FormData;var i=!!e.fn.prop;e.fn.attr2=function(){if(!i)return this.attr.apply(this,arguments);var e=this.prop.apply(this,arguments);return e&&e.jquery||"string"==typeof e?e:this.attr.apply(this,arguments)},e.fn.ajaxSubmit=function(t){function r(r){var a,n,i=e.param(r,t.traditional).split("&"),o=i.length,s=[];for(a=0;o>a;a++)i[a]=i[a].replace(/\+/g," "),n=i[a].split("="),s.push([decodeURIComponent(n[0]),decodeURIComponent(n[1])]);return s}function o(a){for(var n=new FormData,i=0;a.length>i;i++)n.append(a[i].name,a[i].value);if(t.extraData){var o=r(t.extraData);for(i=0;o.length>i;i++)o[i]&&n.append(o[i][0],o[i][1])}t.data=null;var s=e.extend(!0,{},e.ajaxSettings,t,{contentType:!1,processData:!1,cache:!1,type:u||"POST"});t.uploadProgress&&(s.xhr=function(){var r=e.ajaxSettings.xhr();return r.upload&&r.upload.addEventListener("progress",function(e){var r=0,a=e.loaded||e.position,n=e.total;e.lengthComputable&&(r=Math.ceil(100*(a/n))),t.uploadProgress(e,a,n,r)},!1),r}),s.data=null;var l=s.beforeSend;return s.beforeSend=function(e,t){t.data=n,l&&l.call(this,e,t)},e.ajax(s)}function s(r){function n(e){var t=null;try{e.contentWindow&&(t=e.contentWindow.document)}catch(r){a("cannot get iframe.contentWindow document: "+r)}if(t)return t;try{t=e.contentDocument?e.contentDocument:e.document}catch(r){a("cannot get iframe.contentDocument: "+r),t=e.document}return t}function o(){function t(){try{var e=n(g).readyState;a("state = "+e),e&&"uninitialized"==e.toLowerCase()&&setTimeout(t,50)}catch(r){a("Server abort: ",r," (",r.name,")"),s(D),j&&clearTimeout(j),j=void 0}}var r=f.attr2("target"),i=f.attr2("action");w.setAttribute("target",d),u||w.setAttribute("method","POST"),i!=m.url&&w.setAttribute("action",m.url),m.skipEncodingOverride||u&&!/post/i.test(u)||f.attr({encoding:"multipart/form-data",enctype:"multipart/form-data"}),m.timeout&&(j=setTimeout(function(){T=!0,s(k)},m.timeout));var o=[];try{if(m.extraData)for(var l in m.extraData)m.extraData.hasOwnProperty(l)&&(e.isPlainObject(m.extraData[l])&&m.extraData[l].hasOwnProperty("name")&&m.extraData[l].hasOwnProperty("value")?o.push(e('').val(m.extraData[l].value).appendTo(w)[0]):o.push(e('').val(m.extraData[l]).appendTo(w)[0]));m.iframeTarget||(v.appendTo("body"),g.attachEvent?g.attachEvent("onload",s):g.addEventListener("load",s,!1)),setTimeout(t,15);try{w.submit()}catch(c){var p=document.createElement("form").submit;p.apply(w)}}finally{w.setAttribute("action",i),r?w.setAttribute("target",r):f.removeAttr("target"),e(o).remove()}}function s(t){if(!x.aborted&&!F){if(M=n(g),M||(a("cannot access response document"),t=D),t===k&&x)return x.abort("timeout"),S.reject(x,"timeout"),void 0;if(t==D&&x)return x.abort("server abort"),S.reject(x,"error","server abort"),void 0;if(M&&M.location.href!=m.iframeSrc||T){g.detachEvent?g.detachEvent("onload",s):g.removeEventListener("load",s,!1);var r,i="success";try{if(T)throw"timeout";var o="xml"==m.dataType||M.XMLDocument||e.isXMLDoc(M);if(a("isXml="+o),!o&&window.opera&&(null===M.body||!M.body.innerHTML)&&--O)return a("requeing onLoad callback, DOM not available"),setTimeout(s,250),void 0;var u=M.body?M.body:M.documentElement;x.responseText=u?u.innerHTML:null,x.responseXML=M.XMLDocument?M.XMLDocument:M,o&&(m.dataType="xml"),x.getResponseHeader=function(e){var t={"content-type":m.dataType};return t[e]},u&&(x.status=Number(u.getAttribute("status"))||x.status,x.statusText=u.getAttribute("statusText")||x.statusText);var l=(m.dataType||"").toLowerCase(),c=/(json|script|text)/.test(l);if(c||m.textarea){var f=M.getElementsByTagName("textarea")[0];if(f)x.responseText=f.value,x.status=Number(f.getAttribute("status"))||x.status,x.statusText=f.getAttribute("statusText")||x.statusText;else if(c){var d=M.getElementsByTagName("pre")[0],h=M.getElementsByTagName("body")[0];d?x.responseText=d.textContent?d.textContent:d.innerText:h&&(x.responseText=h.textContent?h.textContent:h.innerText)}}else"xml"==l&&!x.responseXML&&x.responseText&&(x.responseXML=X(x.responseText));try{L=_(x,l,m)}catch(b){i="parsererror",x.error=r=b||i}}catch(b){a("error caught: ",b),i="error",x.error=r=b||i}x.aborted&&(a("upload aborted"),i=null),x.status&&(i=x.status>=200&&300>x.status||304===x.status?"success":"error"),"success"===i?(m.success&&m.success.call(m.context,L,"success",x),S.resolve(x.responseText,"success",x),p&&e.event.trigger("ajaxSuccess",[x,m])):i&&(void 0===r&&(r=x.statusText),m.error&&m.error.call(m.context,x,i,r),S.reject(x,"error",r),p&&e.event.trigger("ajaxError",[x,m,r])),p&&e.event.trigger("ajaxComplete",[x,m]),p&&!--e.active&&e.event.trigger("ajaxStop"),m.complete&&m.complete.call(m.context,x,i),F=!0,m.timeout&&clearTimeout(j),setTimeout(function(){m.iframeTarget||v.remove(),x.responseXML=null},100)}}}var l,c,m,p,d,v,g,x,b,y,T,j,w=f[0],S=e.Deferred();if(r)for(c=0;h.length>c;c++)l=e(h[c]),i?l.prop("disabled",!1):l.removeAttr("disabled");if(m=e.extend(!0,{},e.ajaxSettings,t),m.context=m.context||m,d="jqFormIO"+(new Date).getTime(),m.iframeTarget?(v=e(m.iframeTarget),y=v.attr2("name"),y?d=y:v.attr2("name",d)):(v=e(''),v.css({position:"absolute",top:"-1000px",left:"-1000px"})),g=v[0],x={aborted:0,responseText:null,responseXML:null,status:0,statusText:"n/a",getAllResponseHeaders:function(){},getResponseHeader:function(){},setRequestHeader:function(){},abort:function(t){var r="timeout"===t?"timeout":"aborted";a("aborting upload... "+r),this.aborted=1;try{g.contentWindow.document.execCommand&&g.contentWindow.document.execCommand("Stop")}catch(n){}v.attr("src",m.iframeSrc),x.error=r,m.error&&m.error.call(m.context,x,r,t),p&&e.event.trigger("ajaxError",[x,m,r]),m.complete&&m.complete.call(m.context,x,r)}},p=m.global,p&&0===e.active++&&e.event.trigger("ajaxStart"),p&&e.event.trigger("ajaxSend",[x,m]),m.beforeSend&&m.beforeSend.call(m.context,x,m)===!1)return m.global&&e.active--,S.reject(),S;if(x.aborted)return S.reject(),S;b=w.clk,b&&(y=b.name,y&&!b.disabled&&(m.extraData=m.extraData||{},m.extraData[y]=b.value,"image"==b.type&&(m.extraData[y+".x"]=w.clk_x,m.extraData[y+".y"]=w.clk_y)));var k=1,D=2,A=e("meta[name=csrf-token]").attr("content"),E=e("meta[name=csrf-param]").attr("content");E&&A&&(m.extraData=m.extraData||{},m.extraData[E]=A),m.forceSync?o():setTimeout(o,10);var L,M,F,O=50,X=e.parseXML||function(e,t){return window.ActiveXObject?(t=new ActiveXObject("Microsoft.XMLDOM"),t.async="false",t.loadXML(e)):t=(new DOMParser).parseFromString(e,"text/xml"),t&&t.documentElement&&"parsererror"!=t.documentElement.nodeName?t:null},C=e.parseJSON||function(e){return window.eval("("+e+")")},_=function(t,r,a){var n=t.getResponseHeader("content-type")||"",i="xml"===r||!r&&n.indexOf("xml")>=0,o=i?t.responseXML:t.responseText;return i&&"parsererror"===o.documentElement.nodeName&&e.error&&e.error("parsererror"),a&&a.dataFilter&&(o=a.dataFilter(o,r)),"string"==typeof o&&("json"===r||!r&&n.indexOf("json")>=0?o=C(o):("script"===r||!r&&n.indexOf("javascript")>=0)&&e.globalEval(o)),o};return S}if(!this.length)return a("ajaxSubmit: skipping submit process - no element selected"),this;var u,l,c,f=this;"function"==typeof t&&(t={success:t}),u=t.type||this.attr2("method"),l=t.url||this.attr2("action"),c="string"==typeof l?e.trim(l):"",c=c||window.location.href||"",c&&(c=(c.match(/^([^#]+)/)||[])[1]),t=e.extend(!0,{url:c,success:e.ajaxSettings.success,type:u||"GET",iframeSrc:/^https/i.test(window.location.href||"")?"javascript:false":"about:blank"},t);var m={};if(this.trigger("form-pre-serialize",[this,t,m]),m.veto)return a("ajaxSubmit: submit vetoed via form-pre-serialize trigger"),this;if(t.beforeSerialize&&t.beforeSerialize(this,t)===!1)return a("ajaxSubmit: submit aborted via beforeSerialize callback"),this;var p=t.traditional;void 0===p&&(p=e.ajaxSettings.traditional);var d,h=[],v=this.formToArray(t.semantic,h);if(t.data&&(t.extraData=t.data,d=e.param(t.data,p)),t.beforeSubmit&&t.beforeSubmit(v,this,t)===!1)return a("ajaxSubmit: submit aborted via beforeSubmit callback"),this;if(this.trigger("form-submit-validate",[v,this,t,m]),m.veto)return a("ajaxSubmit: submit vetoed via form-submit-validate trigger"),this;var g=e.param(v,p);d&&(g=g?g+"&"+d:d),"GET"==t.type.toUpperCase()?(t.url+=(t.url.indexOf("?")>=0?"&":"?")+g,t.data=null):t.data=g;var x=[];if(t.resetForm&&x.push(function(){f.resetForm()}),t.clearForm&&x.push(function(){f.clearForm(t.includeHidden)}),!t.dataType&&t.target){var b=t.success||function(){};x.push(function(r){var a=t.replaceTarget?"replaceWith":"html";e(t.target)[a](r).each(b,arguments)})}else t.success&&x.push(t.success);if(t.success=function(e,r,a){for(var n=t.context||this,i=0,o=x.length;o>i;i++)x[i].apply(n,[e,r,a||f,f])},t.error){var y=t.error;t.error=function(e,r,a){var n=t.context||this;y.apply(n,[e,r,a,f])}}if(t.complete){var T=t.complete;t.complete=function(e,r){var a=t.context||this;T.apply(a,[e,r,f])}}var j=e('input[type=file]:enabled[value!=""]',this),w=j.length>0,S="multipart/form-data",k=f.attr("enctype")==S||f.attr("encoding")==S,D=n.fileapi&&n.formdata;a("fileAPI :"+D);var A,E=(w||k)&&!D;t.iframe!==!1&&(t.iframe||E)?t.closeKeepAlive?e.get(t.closeKeepAlive,function(){A=s(v)}):A=s(v):A=(w||k)&&D?o(v):e.ajax(t),f.removeData("jqxhr").data("jqxhr",A);for(var L=0;h.length>L;L++)h[L]=null;return this.trigger("form-submit-notify",[this,t]),this},e.fn.ajaxForm=function(n){if(n=n||{},n.delegation=n.delegation&&e.isFunction(e.fn.on),!n.delegation&&0===this.length){var i={s:this.selector,c:this.context};return!e.isReady&&i.s?(a("DOM not ready, queuing ajaxForm"),e(function(){e(i.s,i.c).ajaxForm(n)}),this):(a("terminating; zero elements found by selector"+(e.isReady?"":" (DOM not ready)")),this)}return n.delegation?(e(document).off("submit.form-plugin",this.selector,t).off("click.form-plugin",this.selector,r).on("submit.form-plugin",this.selector,n,t).on("click.form-plugin",this.selector,n,r),this):this.ajaxFormUnbind().bind("submit.form-plugin",n,t).bind("click.form-plugin",n,r)},e.fn.ajaxFormUnbind=function(){return this.unbind("submit.form-plugin click.form-plugin")},e.fn.formToArray=function(t,r){var a=[];if(0===this.length)return a;var i=this[0],o=t?i.getElementsByTagName("*"):i.elements;if(!o)return a;var s,u,l,c,f,m,p;for(s=0,m=o.length;m>s;s++)if(f=o[s],l=f.name,l&&!f.disabled)if(t&&i.clk&&"image"==f.type)i.clk==f&&(a.push({name:l,value:e(f).val(),type:f.type}),a.push({name:l+".x",value:i.clk_x},{name:l+".y",value:i.clk_y}));else if(c=e.fieldValue(f,!0),c&&c.constructor==Array)for(r&&r.push(f),u=0,p=c.length;p>u;u++)a.push({name:l,value:c[u]});else if(n.fileapi&&"file"==f.type){r&&r.push(f);var d=f.files;if(d.length)for(u=0;d.length>u;u++)a.push({name:l,value:d[u],type:f.type});else a.push({name:l,value:"",type:f.type})}else null!==c&&c!==void 0&&(r&&r.push(f),a.push({name:l,value:c,type:f.type,required:f.required}));if(!t&&i.clk){var h=e(i.clk),v=h[0];l=v.name,l&&!v.disabled&&"image"==v.type&&(a.push({name:l,value:h.val()}),a.push({name:l+".x",value:i.clk_x},{name:l+".y",value:i.clk_y}))}return a},e.fn.formSerialize=function(t){return e.param(this.formToArray(t))},e.fn.fieldSerialize=function(t){var r=[];return this.each(function(){var a=this.name;if(a){var n=e.fieldValue(this,t);if(n&&n.constructor==Array)for(var i=0,o=n.length;o>i;i++)r.push({name:a,value:n[i]});else null!==n&&n!==void 0&&r.push({name:this.name,value:n})}}),e.param(r)},e.fn.fieldValue=function(t){for(var r=[],a=0,n=this.length;n>a;a++){var i=this[a],o=e.fieldValue(i,t);null===o||void 0===o||o.constructor==Array&&!o.length||(o.constructor==Array?e.merge(r,o):r.push(o))}return r},e.fieldValue=function(t,r){var a=t.name,n=t.type,i=t.tagName.toLowerCase();if(void 0===r&&(r=!0),r&&(!a||t.disabled||"reset"==n||"button"==n||("checkbox"==n||"radio"==n)&&!t.checked||("submit"==n||"image"==n)&&t.form&&t.form.clk!=t||"select"==i&&-1==t.selectedIndex))return null;if("select"==i){var o=t.selectedIndex;if(0>o)return null;for(var s=[],u=t.options,l="select-one"==n,c=l?o+1:u.length,f=l?o:0;c>f;f++){var m=u[f];if(m.selected){var p=m.value;if(p||(p=m.attributes&&m.attributes.value&&!m.attributes.value.specified?m.text:m.value),l)return p;s.push(p)}}return s}return e(t).val()},e.fn.clearForm=function(t){return this.each(function(){e("input,select,textarea",this).clearFields(t)})},e.fn.clearFields=e.fn.clearInputs=function(t){var r=/^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i;return this.each(function(){var a=this.type,n=this.tagName.toLowerCase();r.test(a)||"textarea"==n?this.value="":"checkbox"==a||"radio"==a?this.checked=!1:"select"==n?this.selectedIndex=-1:"file"==a?/MSIE/.test(navigator.userAgent)?e(this).replaceWith(e(this).clone(!0)):e(this).val(""):t&&(t===!0&&/hidden/.test(a)||"string"==typeof t&&e(this).is(t))&&(this.value="")})},e.fn.resetForm=function(){return this.each(function(){("function"==typeof this.reset||"object"==typeof this.reset&&!this.reset.nodeType)&&this.reset()})},e.fn.enable=function(e){return void 0===e&&(e=!0),this.each(function(){this.disabled=!e})},e.fn.selected=function(t){return void 0===t&&(t=!0),this.each(function(){var r=this.type;if("checkbox"==r||"radio"==r)this.checked=t;else if("option"==this.tagName.toLowerCase()){var a=e(this).parent("select");t&&a[0]&&"select-one"==a[0].type&&a.find("option").selected(!1),this.selected=t}})},e.fn.ajaxSubmit.debug=!1})(jQuery);
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
341 |
--------------------------------------------------------------------------------
/site/js/jquery.dataTables.1.9.4.min.js:
--------------------------------------------------------------------------------
1 | /*
2 | * File: jquery.dataTables.min.js
3 | * Version: 1.9.4
4 | * Author: Allan Jardine (www.sprymedia.co.uk)
5 | * Info: www.datatables.net
6 | *
7 | * Copyright 2008-2012 Allan Jardine, all rights reserved.
8 | *
9 | * This source file is free software, under either the GPL v2 license or a
10 | * BSD style license, available at:
11 | * http://datatables.net/license_gpl2
12 | * http://datatables.net/license_bsd
13 | *
14 | * This source file is distributed in the hope that it will be useful, but
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 | * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
17 | */
18 | (function(X,l,n){var L=function(h){var j=function(e){function o(a,b){var c=j.defaults.columns,d=a.aoColumns.length,c=h.extend({},j.models.oColumn,c,{sSortingClass:a.oClasses.sSortable,sSortingClassJUI:a.oClasses.sSortJUI,nTh:b?b:l.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.oDefaults:d});a.aoColumns.push(c);if(a.aoPreSearchCols[d]===n||null===a.aoPreSearchCols[d])a.aoPreSearchCols[d]=h.extend({},j.models.oSearch);else if(c=a.aoPreSearchCols[d],
19 | c.bRegex===n&&(c.bRegex=!0),c.bSmart===n&&(c.bSmart=!0),c.bCaseInsensitive===n)c.bCaseInsensitive=!0;m(a,d,null)}function m(a,b,c){var d=a.aoColumns[b];c!==n&&null!==c&&(c.mDataProp&&!c.mData&&(c.mData=c.mDataProp),c.sType!==n&&(d.sType=c.sType,d._bAutoType=!1),h.extend(d,c),p(d,c,"sWidth","sWidthOrig"),c.iDataSort!==n&&(d.aDataSort=[c.iDataSort]),p(d,c,"aDataSort"));var i=d.mRender?Q(d.mRender):null,f=Q(d.mData);d.fnGetData=function(a,b){var c=f(a,b);return d.mRender&&b&&""!==b?i(c,b,a):c};d.fnSetData=
20 | L(d.mData);a.oFeatures.bSort||(d.bSortable=!1);!d.bSortable||-1==h.inArray("asc",d.asSorting)&&-1==h.inArray("desc",d.asSorting)?(d.sSortingClass=a.oClasses.sSortableNone,d.sSortingClassJUI=""):-1==h.inArray("asc",d.asSorting)&&-1==h.inArray("desc",d.asSorting)?(d.sSortingClass=a.oClasses.sSortable,d.sSortingClassJUI=a.oClasses.sSortJUI):-1!=h.inArray("asc",d.asSorting)&&-1==h.inArray("desc",d.asSorting)?(d.sSortingClass=a.oClasses.sSortableAsc,d.sSortingClassJUI=a.oClasses.sSortJUIAscAllowed):-1==
21 | h.inArray("asc",d.asSorting)&&-1!=h.inArray("desc",d.asSorting)&&(d.sSortingClass=a.oClasses.sSortableDesc,d.sSortingClassJUI=a.oClasses.sSortJUIDescAllowed)}function k(a){if(!1===a.oFeatures.bAutoWidth)return!1;da(a);for(var b=0,c=a.aoColumns.length;bj[f])d(a.aoColumns.length+j[f],b[i]);else if("string"===typeof j[f]){e=0;for(w=a.aoColumns.length;eb&&a[d]--; -1!=c&&a.splice(c,1)}function S(a,b,c){var d=a.aoColumns[c];return d.fnRender({iDataRow:b,iDataColumn:c,oSettings:a,aData:a.aoData[b]._aData,mDataProp:d.mData},v(a,b,c,"display"))}function ea(a,b){var c=a.aoData[b],d;if(null===c.nTr){c.nTr=l.createElement("tr");c.nTr._DT_RowIndex=b;c._aData.DT_RowId&&(c.nTr.id=c._aData.DT_RowId);c._aData.DT_RowClass&&
33 | (c.nTr.className=c._aData.DT_RowClass);for(var i=0,f=a.aoColumns.length;i=a.fnRecordsDisplay()?0:a.iInitDisplayStart,a.iInitDisplayStart=-1,y(a));if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++;else if(a.oFeatures.bServerSide){if(!a.bDestroying&&!wa(a))return}else a.iDraw++;if(0!==a.aiDisplay.length){var g=
39 | a._iDisplayStart;d=a._iDisplayEnd;a.oFeatures.bServerSide&&(g=0,d=a.aoData.length);for(;g")[0];a.nTable.parentNode.insertBefore(b,a.nTable);a.nTableWrapper=h('')[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var c=a.nTableWrapper,d=a.sDom.split(""),i,f,g,e,w,o,k,m=0;m")[0];w=d[m+
43 | 1];if("'"==w||'"'==w){o="";for(k=2;d[m+k]!=w;)o+=d[m+k],k++;"H"==o?o=a.oClasses.sJUIHeader:"F"==o&&(o=a.oClasses.sJUIFooter);-1!=o.indexOf(".")?(w=o.split("."),e.id=w[0].substr(1,w[0].length-1),e.className=w[1]):"#"==o.charAt(0)?e.id=o.substr(1,o.length-1):e.className=o;m+=k}c.appendChild(e);c=e}else if(">"==g)c=c.parentNode;else if("l"==g&&a.oFeatures.bPaginate&&a.oFeatures.bLengthChange)i=ya(a),f=1;else if("f"==g&&a.oFeatures.bFilter)i=za(a),f=1;else if("r"==g&&a.oFeatures.bProcessing)i=Aa(a),f=
44 | 1;else if("t"==g)i=Ba(a),f=1;else if("i"==g&&a.oFeatures.bInfo)i=Ca(a),f=1;else if("p"==g&&a.oFeatures.bPaginate)i=Da(a),f=1;else if(0!==j.ext.aoFeatures.length){e=j.ext.aoFeatures;k=0;for(w=e.length;k'):""===c?'':c+' ',d=l.createElement("div");d.className=a.oClasses.sFilter;d.innerHTML="";a.aanFeatures.f||(d.id=a.sTableId+"_filter");c=h('input[type="text"]',d);d._DT_Input=c[0];c.val(b.sSearch.replace('"',"""));c.bind("keyup.DT",function(){for(var c=a.aanFeatures.f,d=this.value===""?"":this.value,
51 | g=0,e=c.length;g=b.length)a.aiDisplay.splice(0,a.aiDisplay.length),a.aiDisplay=a.aiDisplayMaster.slice();else if(a.aiDisplay.length==a.aiDisplayMaster.length||i.sSearch.length>b.length||1==c||0!==b.indexOf(i.sSearch)){a.aiDisplay.splice(0,
54 | a.aiDisplay.length);la(a,1);for(b=0;b").html(c).text());
55 | return c.replace(/[\n\r]/g," ")}function ma(a,b,c,d){if(c)return a=b?a.split(" "):oa(a).split(" "),a="^(?=.*?"+a.join(")(?=.*?")+").*$",RegExp(a,d?"i":"");a=b?a:oa(a);return RegExp(a,d?"i":"")}function Ja(a,b){return"function"===typeof j.ext.ofnSearch[b]?j.ext.ofnSearch[b](a):null===a?"":"html"==b?a.replace(/[\r\n]/g," ").replace(/<.*?>/g,""):"string"===typeof a?a.replace(/[\r\n]/g," "):a}function oa(a){return a.replace(RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^|\\-)","g"),
56 | "\\$1")}function Ca(a){var b=l.createElement("div");b.className=a.oClasses.sInfo;a.aanFeatures.i||(a.aoDrawCallback.push({fn:Ka,sName:"information"}),b.id=a.sTableId+"_info");a.nTable.setAttribute("aria-describedby",a.sTableId+"_info");return b}function Ka(a){if(a.oFeatures.bInfo&&0!==a.aanFeatures.i.length){var b=a.oLanguage,c=a._iDisplayStart+1,d=a.fnDisplayEnd(),i=a.fnRecordsTotal(),f=a.fnRecordsDisplay(),g;g=0===f?b.sInfoEmpty:b.sInfo;f!=i&&(g+=" "+b.sInfoFiltered);g+=b.sInfoPostFix;g=ja(a,g);
57 | null!==b.fnInfoCallback&&(g=b.fnInfoCallback.call(a.oInstance,a,c,d,i,f,g));a=a.aanFeatures.i;b=0;for(c=a.length;b",c,d,i=a.aLengthMenu;if(2==i.length&&"object"===typeof i[0]&&"object"===typeof i[1]){c=0;for(d=i[0].length;c'+i[1][c]+""}else{c=0;for(d=i.length;c'+i[c]+""}b+="";i=l.createElement("div");a.aanFeatures.l||
61 | (i.id=a.sTableId+"_length");i.className=a.oClasses.sLength;i.innerHTML="";h('select option[value="'+a._iDisplayLength+'"]',i).attr("selected",!0);h("select",i).bind("change.DT",function(){var b=h(this).val(),i=a.aanFeatures.l;c=0;for(d=i.length;ca.aiDisplay.length||-1==a._iDisplayLength?a.aiDisplay.length:a._iDisplayStart+a._iDisplayLength}function Da(a){if(a.oScroll.bInfinite)return null;var b=l.createElement("div");b.className=a.oClasses.sPaging+a.sPaginationType;j.ext.oPagination[a.sPaginationType].fnInit(a,
63 | b,function(a){y(a);x(a)});a.aanFeatures.p||a.aoDrawCallback.push({fn:function(a){j.ext.oPagination[a.sPaginationType].fnUpdate(a,function(a){y(a);x(a)})},sName:"pagination"});return b}function qa(a,b){var c=a._iDisplayStart;if("number"===typeof b)a._iDisplayStart=b*a._iDisplayLength,a._iDisplayStart>a.fnRecordsDisplay()&&(a._iDisplayStart=0);else if("first"==b)a._iDisplayStart=0;else if("previous"==b)a._iDisplayStart=0<=a._iDisplayLength?a._iDisplayStart-a._iDisplayLength:0,0>a._iDisplayStart&&(a._iDisplayStart=
64 | 0);else if("next"==b)0<=a._iDisplayLength?a._iDisplayStart+a._iDisplayLengthh(a.nTable).height()-a.oScroll.iLoadGap&&a.fnDisplayEnd()d.offsetHeight||"scroll"==h(d).css("overflow-y")))a.nTable.style.width=q(h(a.nTable).outerWidth()-a.oScroll.iBarWidth)}else""!==a.oScroll.sXInner?a.nTable.style.width=
72 | q(a.oScroll.sXInner):i==h(d).width()&&h(d).height()i-a.oScroll.iBarWidth&&(a.nTable.style.width=q(i))):a.nTable.style.width=q(i);i=h(a.nTable).outerWidth();C(s,e);C(function(a){p.push(q(h(a).width()))},e);C(function(a,b){a.style.width=p[b]},g);h(e).height(0);null!==a.nTFoot&&(C(s,j),C(function(a){n.push(q(h(a).width()))},j),C(function(a,b){a.style.width=n[b]},o),h(j).height(0));C(function(a,b){a.innerHTML=
73 | "";a.style.width=p[b]},e);null!==a.nTFoot&&C(function(a,b){a.innerHTML="";a.style.width=n[b]},j);if(h(a.nTable).outerWidth()d.offsetHeight||"scroll"==h(d).css("overflow-y")?i+a.oScroll.iBarWidth:i;if(r&&(d.scrollHeight>d.offsetHeight||"scroll"==h(d).css("overflow-y")))a.nTable.style.width=q(g-a.oScroll.iBarWidth);d.style.width=q(g);a.nScrollHead.style.width=q(g);null!==a.nTFoot&&(a.nScrollFoot.style.width=q(g));""===a.oScroll.sX?D(a,1,"The table cannot fit into the current element which will cause column misalignment. The table has been drawn at its minimum possible width."):
74 | ""!==a.oScroll.sXInner&&D(a,1,"The table cannot fit into the current element which will cause column misalignment. Increase the sScrollXInner value or remove it to allow automatic calculation")}else d.style.width=q("100%"),a.nScrollHead.style.width=q("100%"),null!==a.nTFoot&&(a.nScrollFoot.style.width=q("100%"));""===a.oScroll.sY&&r&&(d.style.height=q(a.nTable.offsetHeight+a.oScroll.iBarWidth));""!==a.oScroll.sY&&a.oScroll.bCollapse&&(d.style.height=q(a.oScroll.sY),r=""!==a.oScroll.sX&&a.nTable.offsetWidth>
75 | d.offsetWidth?a.oScroll.iBarWidth:0,a.nTable.offsetHeightd.clientHeight||"scroll"==h(d).css("overflow-y");b.style.paddingRight=c?a.oScroll.iBarWidth+"px":"0px";null!==a.nTFoot&&(R.style.width=q(r),l.style.width=q(r),l.style.paddingRight=c?a.oScroll.iBarWidth+"px":"0px");h(d).scroll();if(a.bSorted||a.bFiltered)d.scrollTop=0}function C(a,b,c){for(var d=
76 | 0,i=0,f=b.length,g,e;itd",b));j=N(a,f);for(f=d=0;fc)return null;if(null===a.aoData[c].nTr){var d=l.createElement("td");d.innerHTML=v(a,c,b,"");return d}return J(a,c)[b]}function Pa(a,b){for(var c=-1,d=-1,i=0;i/g,"");e.length>c&&(c=e.length,d=i)}return d}function q(a){if(null===a)return"0px";if("number"==typeof a)return 0>a?"0px":a+"px";var b=a.charCodeAt(a.length-1);
82 | return 48>b||57/g,""),i=q[c].nTh,i.removeAttribute("aria-sort"),i.removeAttribute("aria-label"),q[c].bSortable?0d&&d++;f=RegExp(f+"[123]");var o;b=0;for(c=a.length;b