private function request($latitude, $longitude, $time = null, $options = array()) { $request_url = self::API_ENDPOINT . '[APIKEY]' . '/' . $latitude . ',' . $longitude . (is_null($time) ? '' : ',' . $time); if (!empty($options)) { $request_url .= '?' . http_build_query($options); } \Debug::Audit('Calling API with: ' . $request_url); $request_url = str_replace('[APIKEY]', $this->api_key, $request_url); $httpOptions = array(CURLOPT_TIMEOUT => 20, CURLOPT_SSL_VERIFYPEER => true, CURLOPT_USERAGENT => 'Xibo Digital Signage', CURLOPT_HEADER => false, CURLINFO_HEADER_OUT => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_URL => $request_url); // Proxy support if (\Config::GetSetting('PROXY_HOST') != '' && !\Config::isProxyException($request_url)) { $httpOptions[CURLOPT_PROXY] = \Config::GetSetting('PROXY_HOST'); $httpOptions[CURLOPT_PROXYPORT] = \Config::GetSetting('PROXY_PORT'); if (\Config::GetSetting('PROXY_AUTH') != '') { $httpOptions[CURLOPT_PROXYUSERPWD] = \Config::GetSetting('PROXY_AUTH'); } } $curl = curl_init(); curl_setopt_array($curl, $httpOptions); $result = curl_exec($curl); // Get the response headers $outHeaders = curl_getinfo($curl); if ($outHeaders['http_code'] == 0) { // Unable to connect \Debug::Error('Unable to reach Forecast API. No Host Found (HTTP Code 0). Curl Error = ' . curl_error($curl)); return false; } else { if ($outHeaders['http_code'] != 200) { \Debug::Error('ForecastIO API returned ' . $outHeaders['http_code'] . ' status. Unable to proceed. Headers = ' . var_export($outHeaders, true)); // See if we can parse the error. $body = json_decode($result); \Debug::Error('ForecastIO Error: ' . (isset($body->errors[0]) ? $body->errors[0]->message : 'Unknown Error')); return false; } } // Parse out header and body $body = json_decode($result); return $body; }
/** * Replace media in all layouts. * @param <type> $oldMediaId * @param <type> $newMediaId */ private function ReplaceMediaInAllLayouts($replaceInLayouts, $replaceBackgroundImages, $oldMediaId, $newMediaId) { $count = 0; Debug::LogEntry('audit', sprintf('Replacing mediaid %s with mediaid %s in all layouts', $oldMediaId, $newMediaId), 'module', 'ReplaceMediaInAllLayouts'); try { $dbh = PDOConnect::init(); // Some update statements to use $sth = $dbh->prepare('SELECT lklayoutmediaid, regionid FROM lklayoutmedia WHERE mediaid = :media_id AND layoutid = :layout_id'); $sth_update = $dbh->prepare('UPDATE lklayoutmedia SET mediaid = :media_id WHERE lklayoutmediaid = :lklayoutmediaid'); // Loop through a list of layouts this user has access to foreach ($this->user->LayoutList() as $layout) { $layoutId = $layout['layoutid']; // Does this layout use the old media id? $sth->execute(array('media_id' => $oldMediaId, 'layout_id' => $layoutId)); $results = $sth->fetchAll(); if (count($results) <= 0) { continue; } Debug::LogEntry('audit', sprintf('%d linked media items for layoutid %d', count($results), $layoutId), 'module', 'ReplaceMediaInAllLayouts'); // Create a region object for later use (new one each time) $layout = new Layout(); $region = new region($this->db); // Loop through each media link for this layout foreach ($results as $row) { // Get the LKID of the link between this layout and this media.. could be more than one? $lkId = $row['lklayoutmediaid']; $regionId = $row['regionid']; if ($regionId == 'background') { Debug::Audit('Replacing background image'); if (!$replaceBackgroundImages) { continue; } // Straight swap this background image node. if (!$layout->EditBackgroundImage($layoutId, $newMediaId)) { return false; } } else { if (!$replaceInLayouts) { continue; } // Get the Type of this media if (!($type = $region->GetMediaNodeType($layoutId, '', '', $lkId))) { continue; } // Create a new media node use it to swap the nodes over Debug::LogEntry('audit', 'Creating new module with MediaID: ' . $newMediaId . ' LayoutID: ' . $layoutId . ' and RegionID: ' . $regionId, 'region', 'ReplaceMediaInAllLayouts'); try { $module = ModuleFactory::createForMedia($type, $newMediaId, $this->db, $this->user); } catch (Exception $e) { Debug::Error($e->getMessage()); return false; } // Sets the URI field if (!$module->SetRegionInformation($layoutId, $regionId)) { return false; } // Get the media xml string to use in the swap. $mediaXmlString = $module->AsXml(); // Swap the nodes if (!$region->SwapMedia($layoutId, $regionId, $lkId, $oldMediaId, $newMediaId, $mediaXmlString)) { return false; } } // Update the LKID with the new media id $sth_update->execute(array('media_id' => $newMediaId, 'lklayoutmediaid' => $row['lklayoutmediaid'])); $count++; } } } catch (Exception $e) { Debug::LogEntry('error', $e->getMessage()); if (!$this->IsError()) { $this->SetError(1, __('Unknown Error')); } return false; } Debug::LogEntry('audit', sprintf('Replaced media in %d layouts', $count), 'module', 'ReplaceMediaInAllLayouts'); }
/** * Get unused media entries * @param int $userId * @return array * @throws Exception */ public static function entriesUnusedForUser($userId) { $media = array(); try { $dbh = PDOConnect::init(); $sth = $dbh->prepare('SELECT media.mediaId, media.storedAs, media.type, media.isedited, media.fileSize, SUM(CASE WHEN IFNULL(lklayoutmedia.lklayoutmediaid, 0) = 0 THEN 0 ELSE 1 END) AS UsedInLayoutCount, SUM(CASE WHEN IFNULL(lkmediadisplaygroup.id, 0) = 0 THEN 0 ELSE 1 END) AS UsedInDisplayCount FROM `media` LEFT OUTER JOIN `lklayoutmedia` ON lklayoutmedia.mediaid = media.mediaid LEFT OUTER JOIN `lkmediadisplaygroup` ON lkmediadisplaygroup.mediaid = media.mediaid WHERE media.userId = :userId AND media.type <> \'module\' AND media.type <> \'font\' GROUP BY media.mediaid, media.storedAs, media.type, media.isedited'); $sth->execute(array('userId' => $userId)); foreach ($sth->fetchAll(PDO::FETCH_ASSOC) as $row) { // Check to make sure it is not used if ($row['UsedInLayoutCount'] > 0 || $row['UsedInDisplayCount'] > 0) { continue; } $media[] = $row; } } catch (Exception $e) { Debug::Error($e->getMessage()); throw new Exception(__('Cannot get entries')); } return $media; }
/** * GetResource * Return the rendered resource to be used by the client (or a preview) * for displaying this content. * @param integer $displayId If this comes from a real client, this will be the display id. * @return string */ public function GetResource($displayId = 0) { // Make sure we are set up correctly if ($this->GetSetting('apiKey') == '' || $this->GetSetting('apiSecret') == '') { Debug::Error('Twitter Module not configured. Missing API Keys'); return ''; } // Load in the template $template = file_get_contents('modules/preview/HtmlTemplate.html'); $isPreview = Kit::GetParam('preview', _REQUEST, _WORD, 'false') == 'true'; // Replace the View Port Width? if ($isPreview) { $template = str_replace('[[ViewPortWidth]]', $this->width, $template); } // Information from the Module $duration = $this->duration; // Generate a JSON string of substituted items. $items = $this->getTwitterFeed($displayId, $isPreview); // Return empty string if there are no items to show. if (count($items) == 0) { return ''; } $options = array('type' => $this->type, 'fx' => $this->GetOption('effect', 'none'), 'speed' => $this->GetOption('speed', 500), 'duration' => $duration, 'durationIsPerItem' => $this->GetOption('durationIsPerItem', 0) == 1, 'numItems' => count($items), 'itemsPerPage' => 1, 'originalWidth' => $this->width, 'originalHeight' => $this->height, 'previewWidth' => Kit::GetParam('width', _GET, _DOUBLE, 0), 'previewHeight' => Kit::GetParam('height', _GET, _DOUBLE, 0), 'scaleOverride' => Kit::GetParam('scale_override', _GET, _DOUBLE, 0)); // Replace the control meta with our data from twitter $controlMeta = '<!-- NUMITEMS=' . count($items) . ' -->' . PHP_EOL . '<!-- DURATION=' . ($this->GetOption('durationIsPerItem', 0) == 0 ? $duration : $duration * count($items)) . ' -->'; $template = str_replace('<!--[[[CONTROLMETA]]]-->', $controlMeta, $template); // Replace the head content $headContent = ''; // Add the CSS if it isn't empty $css = $this->GetRawNode('styleSheet'); if ($css != '') { $headContent .= '<style type="text/css">' . $css . '</style>'; } $backgroundColor = $this->GetOption('backgroundColor'); if ($backgroundColor != '') { $headContent .= '<style type="text/css">body, .page, .item { background-color: ' . $backgroundColor . ' }</style>'; } // Add our fonts.css file $headContent .= '<link href="' . ($isPreview ? 'modules/preview/' : '') . 'fonts.css" rel="stylesheet" media="screen">'; $headContent .= '<link href="' . ($isPreview ? 'modules/theme/twitter/' : '') . 'emoji.css" rel="stylesheet" media="screen">'; $headContent .= '<style type="text/css">' . file_get_contents(Theme::ItemPath('css/client.css')) . '</style>'; // Replace the Head Content with our generated javascript $template = str_replace('<!--[[[HEADCONTENT]]]-->', $headContent, $template); // Add some scripts to the JavaScript Content $javaScriptContent = '<script type="text/javascript" src="' . ($isPreview ? 'modules/preview/vendor/' : '') . 'jquery-1.11.1.min.js"></script>'; // Need the cycle plugin? if ($this->GetSetting('effect') != 'none') { $javaScriptContent .= '<script type="text/javascript" src="' . ($isPreview ? 'modules/preview/vendor/' : '') . 'jquery-cycle-2.1.6.min.js"></script>'; } // Need the marquee plugin? if (stripos($this->GetSetting('effect'), 'marquee')) { $javaScriptContent .= '<script type="text/javascript" src="' . ($isPreview ? 'modules/preview/vendor/' : '') . 'jquery.marquee.min.js"></script>'; } $javaScriptContent .= '<script type="text/javascript" src="' . ($isPreview ? 'modules/preview/' : '') . 'xibo-layout-scaler.js"></script>'; $javaScriptContent .= '<script type="text/javascript" src="' . ($isPreview ? 'modules/preview/' : '') . 'xibo-text-render.js"></script>'; $javaScriptContent .= '<script type="text/javascript">'; $javaScriptContent .= ' var options = ' . json_encode($options) . ';'; $javaScriptContent .= ' var items = ' . Kit::jsonEncode($items) . ';'; $javaScriptContent .= ' $(document).ready(function() { '; $javaScriptContent .= ' $("body").xiboLayoutScaler(options); $("#content").xiboTextRender(options, items); '; $javaScriptContent .= ' }); '; $javaScriptContent .= '</script>'; // Replace the Head Content with our generated javascript $template = str_replace('<!--[[[JAVASCRIPTCONTENT]]]-->', $javaScriptContent, $template); // Replace the Body Content with our generated text $template = str_replace('<!--[[[BODYCONTENT]]]-->', '', $template); return $template; }
/** * Check we haven't exceeded the bandwidth limits */ private function CheckBandwidth() { $xmdsLimit = Config::GetSetting('MONTHLY_XMDS_TRANSFER_LIMIT_KB'); if ($xmdsLimit <= 0) { return true; } try { $dbh = PDOConnect::init(); // Test bandwidth for the current month $sth = $dbh->prepare('SELECT IFNULL(SUM(Size), 0) AS BandwidthUsage FROM `bandwidth` WHERE Month = :month'); $sth->execute(array('month' => strtotime(date('m') . '/02/' . date('Y') . ' 00:00:00'))); $bandwidthUsage = $sth->fetchColumn(0); return $bandwidthUsage >= $xmdsLimit * 1024 ? false : true; } catch (Exception $e) { Debug::Error($e->getMessage(), $this->displayId); return false; } }
/** * Data Set Results * @param <type> $dataSetId * @param <type> $columnIds * @param <type> $filter * @param <type> $ordering * @param <type> $lowerLimit * @param <type> $upperLimit * @return <type> */ public function DataSetResults($dataSetId, $columnIds, $filter = '', $ordering = '', $lowerLimit = 0, $upperLimit = 0, $displayId = 0) { $blackList = array(';', 'INSERT', 'UPDATE', 'SELECT', 'DELETE', 'TRUNCATE', 'TABLE', 'FROM', 'WHERE'); try { $dbh = PDOConnect::init(); $params = array('dataSetId' => $dataSetId); $selectSQL = ''; $outserSelect = ''; $finalSelect = ''; $results = array(); $headings = array(); $allowedOrderCols = array(); $filter = str_replace($blackList, '', $filter); $filter = str_replace('[DisplayId]', $displayId, $filter); $columns = explode(',', $columnIds); // Get the Latitude and Longitude ( might be used in a formula ) if ($displayId == 0) { $defaultLat = Config::GetSetting('DEFAULT_LAT'); $defaultLong = Config::GetSetting('DEFAULT_LONG'); $displayGeoLocation = "GEOMFROMTEXT('POINT(" . $defaultLat . " " . $defaultLong . ")')"; } else { $displayGeoLocation = sprintf("(SELECT GeoLocation FROM `display` WHERE DisplayID = %d)", $displayId); } // Get all columns for the cross tab $sth = $dbh->prepare('SELECT DataSetColumnID, Heading, DataSetColumnTypeID, Formula, DataTypeID FROM datasetcolumn WHERE DataSetID = :dataSetId'); $sth->execute(array('dataSetId' => $dataSetId)); $allColumns = $sth->fetchAll(); foreach ($allColumns as $col) { $heading = $col; $heading['Text'] = $heading['Heading']; $allowedOrderCols[] = $heading['Heading']; $formula = str_replace($blackList, '', htmlspecialchars_decode($col['Formula'], ENT_QUOTES)); // Is this column a formula column or a value column? if ($col['DataSetColumnTypeID'] == 2) { // Formula $formula = str_replace('[DisplayGeoLocation]', $displayGeoLocation, $formula); $formula = str_replace('[DisplayId]', $displayId, $formula); $heading['Heading'] = $formula . ' AS \'' . $heading['Heading'] . '\''; } else { // Value $selectSQL .= sprintf("MAX(CASE WHEN DataSetColumnID = %d THEN `Value` ELSE null END) AS '%s', ", $col['DataSetColumnID'], $heading['Heading']); } $headings[] = $heading; } // Build our select statement including formulas foreach ($headings as $heading) { if ($heading['DataSetColumnTypeID'] == 2) { // This is a formula, so the heading has been morphed into some SQL to run $outserSelect .= ' ' . $heading['Heading'] . ','; } else { $outserSelect .= sprintf(' `%s`,', $heading['Heading']); } } $outserSelect = rtrim($outserSelect, ','); // For each heading, put it in the correct order (according to $columns) foreach ($columns as $visibleColumn) { foreach ($headings as $heading) { if ($heading['DataSetColumnID'] == $visibleColumn) { $finalSelect .= sprintf(' `%s`,', $heading['Text']); $results['Columns'][] = $heading; } } } $finalSelect = rtrim($finalSelect, ','); // We are ready to build the select and from part of the SQL $SQL = "SELECT {$finalSelect} "; $SQL .= " FROM ( "; $SQL .= " SELECT {$outserSelect} ,"; $SQL .= " RowNumber "; $SQL .= " FROM ( "; $SQL .= " SELECT {$selectSQL} "; $SQL .= " RowNumber "; $SQL .= " FROM ("; $SQL .= " SELECT datasetcolumn.DataSetColumnID, datasetdata.RowNumber, datasetdata.`Value` "; $SQL .= " FROM datasetdata "; $SQL .= " INNER JOIN datasetcolumn "; $SQL .= " ON datasetcolumn.DataSetColumnID = datasetdata.DataSetColumnID "; $SQL .= " WHERE datasetcolumn.DataSetID = :dataSetId "; $SQL .= " ) datasetdatainner "; $SQL .= " GROUP BY RowNumber "; $SQL .= " ) datasetdata "; if ($filter != '') { $SQL .= ' WHERE ' . $filter; } $SQL .= ' ) finalselect '; if ($ordering != '') { $order = ' ORDER BY '; $ordering = explode(',', $ordering); foreach ($ordering as $orderPair) { // Sanitize the clause $sanitized = str_replace(' ASC', '', str_replace(' DESC', '', $orderPair)); // Check allowable if (!in_array($sanitized, $allowedOrderCols)) { Debug::Info('Disallowed column: ' . $sanitized); continue; } // Substitute if (strripos($orderPair, ' DESC')) { $order .= sprintf(' `%s` DESC,', $sanitized); } else { if (strripos($orderPair, ' ASC')) { $order .= sprintf(' `%s` ASC,', $sanitized); } else { $order .= sprintf(' `%s`,', $sanitized); } } } $SQL .= trim($order, ','); } else { $SQL .= " ORDER BY RowNumber "; } if ($lowerLimit != 0 || $upperLimit != 0) { // Lower limit should be 0 based if ($lowerLimit != 0) { $lowerLimit = $lowerLimit - 1; } // Upper limit should be the distance between upper and lower $upperLimit = $upperLimit - $lowerLimit; // Substitute in $SQL .= sprintf(' LIMIT %d, %d ', $lowerLimit, $upperLimit); } Debug::Audit($SQL . ' ' . var_export($params, true)); $sth = $dbh->prepare($SQL); //$sth->debugDumpParams(); $sth->execute($params); $results['Rows'] = $sth->fetchAll(); return $results; } catch (Exception $e) { Debug::Error($e->getMessage()); if (!$this->IsError()) { $this->SetError(1, __('Unknown Error')); } return false; } }
public function RemoveMedia($layoutid, $regionid, $lkid, $mediaid) { //Load the XML for this layout $xml = new DOMDocument("1.0"); $xml->loadXML($this->GetLayoutXml($layoutid)); //Should we use the LkID or the mediaID if ($lkid != "") { //Get the media node $xpathQuery = "//region[@id='{$regionid}']/media[@lkid='{$lkid}']"; if (!$this->RemoveDbLink($lkid)) { return false; } } else { $xpathQuery = "//region[@id='{$regionid}']/media[@id='{$mediaid}']"; } //Find the region in question $xpath = new DOMXPath($xml); //Xpath for it $mediaNodeList = $xpath->query($xpathQuery); $mediaNode = $mediaNodeList->item(0); if ($mediaNode == null) { // Protect against corrupted layouts with left over lklayoutmedia records. Debug::Error('Cannot find this media in layoutId ' . $layoutid . ' using ' . $xpathQuery); return true; } $mediaNode->parentNode->removeChild($mediaNode); //Convert back to XML $xml = $xml->saveXML(); if (!$this->SetLayoutXml($layoutid, $xml)) { return false; } // Update layout status Kit::ClassLoader('Layout'); $layout = new Layout($this->db); $layout->SetValid($layoutid, true); return true; }
/** * Returns an array containing the type of children owned by the group * @param int $groupId * @return array[string] * @throws Exception */ public function getChildTypes($groupId) { try { $types = array(); if (PDOConnect::exists('SELECT GroupID FROM lkdatasetgroup WHERE GroupID = :groupId', array('groupId' => $groupId))) { $types[] = 'data sets'; } if (PDOConnect::exists('SELECT GroupID FROM lkdisplaygroupgroup WHERE GroupID = :groupId', array('groupId' => $groupId))) { $types[] = 'display groups'; } if (PDOConnect::exists('SELECT GroupID FROM lkcampaigngroup WHERE GroupID = :groupId', array('groupId' => $groupId))) { $types[] = 'layouts and campaigns'; } if (PDOConnect::exists('SELECT GroupID FROM lklayoutmediagroup WHERE GroupID = :groupId', array('groupId' => $groupId))) { $types[] = 'media on layouts'; } if (PDOConnect::exists('SELECT GroupID FROM lklayoutregiongroup WHERE GroupID = :groupId', array('groupId' => $groupId))) { $types[] = 'regions on layouts'; } if (PDOConnect::exists('SELECT GroupID FROM lkmediagroup WHERE GroupID = :groupId', array('groupId' => $groupId))) { $types[] = 'media'; } return $types; } catch (Exception $e) { Debug::Error($e->getMessage()); throw $e; } }
/** * Request from Yahoo API * @param $yql * @return array|bool */ private function request($yql) { // Encode the YQL and make the request $url = 'https://query.yahooapis.com/v1/public/yql?q=' . urlencode($yql) . '&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys'; //$url = 'https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quote%20where%20symbol%20in%20(%22TEC.PA%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback='; $httpOptions = array(CURLOPT_TIMEOUT => 20, CURLOPT_SSL_VERIFYPEER => true, CURLOPT_USERAGENT => 'Xibo Digital Signage', CURLOPT_HEADER => false, CURLINFO_HEADER_OUT => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_URL => $url); // Proxy support if (\Config::GetSetting('PROXY_HOST') != '' && !\Config::isProxyException($url)) { $httpOptions[CURLOPT_PROXY] = \Config::GetSetting('PROXY_HOST'); $httpOptions[CURLOPT_PROXYPORT] = \Config::GetSetting('PROXY_PORT'); if (\Config::GetSetting('PROXY_AUTH') != '') { $httpOptions[CURLOPT_PROXYUSERPWD] = \Config::GetSetting('PROXY_AUTH'); } } $curl = curl_init(); curl_setopt_array($curl, $httpOptions); $result = curl_exec($curl); // Get the response headers $outHeaders = curl_getinfo($curl); if ($outHeaders['http_code'] == 0) { // Unable to connect \Debug::Error('Unable to reach API. No Host Found (HTTP Code 0). Curl Error = ' . curl_error($curl)); return false; } else { if ($outHeaders['http_code'] != 200) { \Debug::Error('API returned ' . $outHeaders['http_code'] . ' status. Unable to proceed. Headers = ' . var_export($outHeaders, true)); // See if we can parse the error. $body = json_decode($result); \Debug::Error('Error: ' . (isset($body->errors[0]) ? $body->errors[0]->message : 'Unknown Error')); return false; } } // Parse out header and body $body = json_decode($result, true); return $body['query']['results']; }
/** * Returns an array containing the type of children owned by the user * @return array[string] * @throws Exception */ public function getChildTypes() { if (!isset($this->userId) || $this->userId == 0) { return $this->SetError(__('Missing userId')); } try { $types = array(); if (PDOConnect::exists('SELECT LayoutID FROM layout WHERE UserID = :userId', array('userId' => $this->userId))) { $types[] = 'layouts'; } if (PDOConnect::exists('SELECT MediaID FROM media WHERE UserID = :userId', array('userId' => $this->userId))) { $types[] = 'media'; } if (PDOConnect::exists('SELECT EventID FROM schedule WHERE UserID = :userId', array('userId' => $this->userId))) { $types[] = 'scheduled layouts'; } if (PDOConnect::exists('SELECT Schedule_DetailID FROM schedule_detail WHERE UserID = :userId', array('userId' => $this->userId))) { $types[] = 'schedule detail records'; } if (PDOConnect::exists('SELECT osr_id FROM oauth_server_registry WHERE osr_usa_id_ref = :userId', array('userId' => $this->userId))) { $types[] = 'applications'; } return $types; } catch (Exception $e) { Debug::Error($e->getMessage()); throw $e; } }
public static function EnsureLibraryExists() { $libraryFolder = Config::GetSetting('LIBRARY_LOCATION'); // Check that this location exists - and if not create it.. if (!file_exists($libraryFolder)) { mkdir($libraryFolder, 0777, true); } if (!file_exists($libraryFolder . '/temp')) { mkdir($libraryFolder . '/temp', 0777, true); } if (!file_exists($libraryFolder . '/cache')) { mkdir($libraryFolder . '/cache', 0777, true); } if (!file_exists($libraryFolder . '/screenshots')) { mkdir($libraryFolder . '/screenshots', 0777, true); } // Check that we are now writable - if not then error if (!is_writable($libraryFolder)) { Debug::Error('Library not writable'); return false; } return true; }
public function quota() { $response = new ResponseManager(); $groupId = Kit::GetParam('groupId', _POST, _INT); $libraryQuota = Kit::GetParam('libraryQuota', _POST, _INT); try { UserGroup::updateLibraryQuota($groupId, $libraryQuota); } catch (Exception $e) { Debug::Error($e->getMessage()); trigger_error(__('Problem setting quota'), E_USER_ERROR); } $response->SetFormSubmitResponse(__('Quota has been updated'), false); $response->Respond(); }