/** * Imports a language from a language XML file * * @param string XML language string * @param integer Language to overwrite * @param string Override title for imported language * @param boolean Allow import of language from mismatched vBulletin version * @param boolean Allow user-select of imported language * @param boolean Echo output.. * @param boolean Read charset from XML header * * @return Returns false if the custom language was not imported (used in final_upgrade) OR * returns the languageid if, if the custom language import was successful (also used in final_upgrade) */ function xml_import_language($xml = false, $languageid = -1, $title = '', $anyversion = false, $userselect = true, $output = true, $readcharset = false) { global $vbulletin, $vbphrase; print_dots_start('<b>' . $vbphrase['importing_language'] . "</b>, {$vbphrase['please_wait']}", ':', 'dspan'); require_once DIR . '/includes/class_xml.php'; require_once DIR . '/includes/functions_misc.php'; $xmlobj = new vB_XML_Parser($xml, $GLOBALS['path'], $readcharset); if ($xmlobj->error_no() == 1) { print_dots_stop(); print_stop_message2('no_xml_and_no_path'); } else { if ($xmlobj->error_no() == 2) { print_dots_stop(); print_stop_message('please_ensure_x_file_is_located_at_y', 'vbulletin-language.xml', $GLOBALS['path']); } } if (!($arr =& $xmlobj->parse())) { print_dots_stop(); print_stop_message('xml_error_x_at_line_y', $xmlobj->error_string(), $xmlobj->error_line()); } if (!$arr['phrasetype']) { print_dots_stop(); print_stop_message2('invalid_file_specified'); } $title = empty($title) ? $arr['name'] : $title; $version = $arr['vbversion']; $master = $arr['type'] == 'master' ? 1 : 0; $just_phrases = $arr['type'] == 'phrases' ? 1 : 0; if (!empty($arr['settings'])) { $langinfo = $arr['settings']; } $officialcustom = false; //Check custom language revision. See also VBV-9215. if (!$master and $arr['product'] == 'vbulletin' and !empty($arr['revision']) and !empty($arr['vblangcode'])) { $test = $vbulletin->db->query_first("SELECT * FROM " . TABLE_PREFIX . "language WHERE vblangcode = '" . $vbulletin->db->escape_string($arr['vblangcode']) . "'"); if ($test['languageid']) { if (intval($test['revision']) >= intval($arr['revision'])) { // Same or newer language revision has been installed // We shouldn't print_stop_message() as the upgrader may continue processing other custom languages return false; } $languageid = $test['languageid']; } $langinfo['revision'] = intval($arr['revision']); $langinfo['vblangcode'] = trim($arr['vblangcode']); $officialcustom = true; } else { $langinfo['revision'] = 0; $langinfo['vblangcode'] = ''; } $langinfo['product'] = empty($arr['product']) ? 'vbulletin' : $arr['product']; // look for skipped groups $skipped_groups = array(); if (!empty($arr['skippedgroups'])) { $skippedgroups =& $arr['skippedgroups']['skippedgroup']; if (!is_array($skippedgroups)) { $skippedgroups = array($skippedgroups); } foreach ($skippedgroups as $skipped) { if (is_array($skipped)) { $skipped_groups[] = $vbulletin->db->escape_string($skipped['value']); } else { $skipped_groups[] = $vbulletin->db->escape_string($skipped); } } } if ($skipped_groups) { $sql_skipped = "AND " . TABLE_PREFIX . "phrase.fieldname NOT IN ('" . implode("', '", $skipped_groups) . "')"; } else { $sql_skipped = ''; } foreach ($langinfo as $key => $val) { $langinfo["{$key}"] = $vbulletin->db->escape_string(trim($val)); } $langinfo['options'] = intval($langinfo['options']); $langinfo['revision'] = intval($langinfo['revision']); if ($version != $vbulletin->options['templateversion'] and !$master) { if (strtok($version, '.') != strtok($vbulletin->options['templateversion'], '.')) { print_dots_stop(); print_stop_message('upload_file_created_with_different_major_version', $vbulletin->options['templateversion'], $version); } if (!$anyversion) { print_dots_stop(); print_stop_message('upload_file_created_with_different_version', $vbulletin->options['templateversion'], $version); } } //set up the phrase array $arr = $arr['phrasetype']; if (!is_array($arr[0])) { $arr = array($arr); } // check if we need to convert the phrases to the current board's charset. $convertPhrases = false; $boardCharset = strtolower(vB_Template_Runtime::fetchStyleVar('charset')); $phrasesCharset = isset($langinfo['charset']) ? strtolower($langinfo['charset']) : $boardCharset; if (!empty($boardCharset) and $boardCharset != $phrasesCharset) { $convertPhrases = true; $langinfo['charset'] = $boardCharset; // since we're converting the phrases to the board charset, make sure the inserted language uses the board's charset & informs the browser correctly. } //spin through the phrases to check validity. We want to do this *before* we prep for import //so that if we abort do to an error, we haven't made any changes first foreach (array_keys($arr) as $key) { $phraseTypes =& $arr["{$key}"]; if (is_array($phraseTypes['phrase'])) { foreach ($phraseTypes['phrase'] as $key2 => $phrase) { if (is_array($phrase)) { $check = $phrase['value']; } else { $check = $phrase; } if ($convertPhrases) { // convert it from the language file's encoding to the board's encoding $check = vB_String::toCharset($check, $phrasesCharset, $boardCharset); if (is_array($phrase)) { $arr[$key]['phrase'][$key2]['value'] = $check; } else { $arr[$key]['phrase'][$key2] = $check; } } if (!validate_string_for_interpolation($check)) { print_dots_stop(); print_stop_message2(array('phrase_text_not_safe', $phrase['name'])); } } } } // prepare for import if ($master) { // lets stop it from dieing cause someone borked a previous update $vbulletin->db->query_write("DELETE FROM " . TABLE_PREFIX . "phrase WHERE languageid = -10"); // master style if ($output and VB_AREA != 'Install' and VB_AREA != 'Upgrade') { echo "<h3>{$vbphrase['master_language']}</h3>\n<p>{$vbphrase['please_wait']}</p>"; vbflush(); } $vbulletin->db->query_write("\n\t\t\tUPDATE " . TABLE_PREFIX . "phrase SET\n\t\t\t\tlanguageid = -10\n\t\t\tWHERE languageid = -1\n\t\t\t\tAND (product = '" . $vbulletin->db->escape_string($langinfo['product']) . "'" . iif($langinfo['product'] == 'vbulletin', " OR product = ''") . ")\n\t\t\t\t{$sql_skipped}\n\t\t"); $languageid = -1; } else { if ($languageid == 0) { // creating a new language if ($just_phrases) { print_dots_stop(); print_stop_message2(array('language_only_phrases', $title)); } else { if ($test = $vbulletin->db->query_first("SELECT languageid FROM " . TABLE_PREFIX . "language WHERE title = '" . $vbulletin->db->escape_string($title) . "'")) { if ($officialcustom) { // Rename the old language $vbulletin->db->query_write("UPDATE " . TABLE_PREFIX . "language SET title = CONCAT(title, '_old') WHERE title = '" . $vbulletin->db->escape_string($title) . "' AND languagecode"); } else { print_dots_stop(); print_stop_message2(array('language_already_exists', $title)); } } } if ($output and VB_AREA != 'Install' and VB_AREA != 'Upgrade') { echo "<h3><b>" . construct_phrase($vbphrase['creating_a_new_language_called_x'], $title) . "</b></h3>\n<p>{$vbphrase['please_wait']}</p>"; vbflush(); } /*insert query*/ $vbulletin->db->query_write("\n\t\t\t\tINSERT INTO " . TABLE_PREFIX . "language (\n\t\t\t\t\ttitle, options, languagecode, charset, revision, vblangcode,\n\t\t\t\t\tdateoverride, timeoverride, decimalsep, thousandsep,\n\t\t\t\t\tregistereddateoverride, calformat1override, calformat2override, locale, logdateoverride\n\t\t\t\t) VALUES (\n\t\t\t\t\t'" . $vbulletin->db->escape_string($title) . "', {$langinfo['options']}, '{$langinfo['languagecode']}', '{$langinfo['charset']}', {$langinfo['revision']}, '" . $vbulletin->db->escape_string($langinfo['vblangcode']) . "',\n\t\t\t\t\t'{$langinfo['dateoverride']}', '{$langinfo['timeoverride']}', '{$langinfo['decimalsep']}', '{$langinfo['thousandsep']}',\n\t\t\t\t\t'{$langinfo['registereddateoverride']}', '{$langinfo['calformat1override']}', '{$langinfo['calformat2override']}', '{$langinfo['locale']}', '{$langinfo['logdateoverride']}'\n\t\t\t\t)\n\t\t\t"); $languageid = $vbulletin->db->insert_id(); } else { // overwriting an existing language if ($getlanguage = $vbulletin->db->query_first("SELECT title FROM " . TABLE_PREFIX . "language WHERE languageid = {$languageid}")) { if (!$just_phrases) { if ($output and VB_AREA != 'Install' and VB_AREA != 'Upgrade') { echo "<h3><b>" . construct_phrase($vbphrase['overwriting_language_x'], $getlanguage['title']) . "</b></h3>\n<p>{$vbphrase['please_wait']}</p>"; vbflush(); } $vbulletin->db->query_write("\n\t\t\t\t\t\tUPDATE " . TABLE_PREFIX . "language SET\n\t\t\t\t\t\t\toptions = {$langinfo['options']},\n\t\t\t\t\t\t\tlanguagecode = '{$langinfo['languagecode']}',\n\t\t\t\t\t\t\tcharset = '{$langinfo['charset']}',\n\t\t\t\t\t\t\tlocale = '{$langinfo['locale']}',\n\t\t\t\t\t\t\timagesoverride = '{$langinfo['imagesoverride']}',\n\t\t\t\t\t\t\tdateoverride = '{$langinfo['dateoverride']}',\n\t\t\t\t\t\t\ttimeoverride = '{$langinfo['timeoverride']}',\n\t\t\t\t\t\t\tdecimalsep = '{$langinfo['decimalsep']}',\n\t\t\t\t\t\t\tthousandsep = '{$langinfo['thousandsep']}',\n\t\t\t\t\t\t\tregistereddateoverride = '{$langinfo['registereddateoverride']}',\n\t\t\t\t\t\t\tcalformat1override = '{$langinfo['calformat1override']}',\n\t\t\t\t\t\t\tcalformat2override = '{$langinfo['calformat2override']}',\n\t\t\t\t\t\t\tlogdateoverride = '{$langinfo['logdateoverride']}',\n\t\t\t\t\t\t\trevision = {$langinfo['revision']}\n\t\t\t\t\t\tWHERE languageid = {$languageid}\n\t\t\t\t\t"); $vbulletin->db->query_write("\n\t\t\t\t\t\tUPDATE " . TABLE_PREFIX . "phrase, " . TABLE_PREFIX . "phrase AS phrase2\n\t\t\t\t\t\tSET " . TABLE_PREFIX . "phrase.languageid = -11\n\t\t\t\t\t\tWHERE " . TABLE_PREFIX . "phrase.languageid = {$languageid}\n\t\t\t\t\t\t\tAND (" . TABLE_PREFIX . "phrase.product = '" . $vbulletin->db->escape_string($langinfo['product']) . "'" . iif($langinfo['product'] == 'vbulletin', " OR " . TABLE_PREFIX . "phrase.product = ''") . ")\n\t\t\t\t\t\t\tAND (phrase2.product = '" . $vbulletin->db->escape_string($langinfo['product']) . "'" . iif($langinfo['product'] == 'vbulletin', " OR phrase2.product = ''") . ")\n\t\t\t\t\t\t\tAND " . TABLE_PREFIX . "phrase.varname = phrase2.varname\n\t\t\t\t\t\t\tAND phrase2.languageid = 0\n\t\t\t\t\t\t\tAND " . TABLE_PREFIX . "phrase.fieldname = phrase2.fieldname\n\t\t\t\t\t\t\t{$sql_skipped}\n\t\t\t\t\t"); $vbulletin->db->query_write("\n\t\t\t\t\t\tUPDATE " . TABLE_PREFIX . "phrase SET\n\t\t\t\t\t\t\tlanguageid = -10\n\t\t\t\t\t\tWHERE languageid = {$languageid}\n\t\t\t\t\t\t\tAND (product = '" . $vbulletin->db->escape_string($langinfo['product']) . "'" . iif($langinfo['product'] == 'vbulletin', " OR product = ''") . ")\n\t\t\t\t\t\t\t{$sql_skipped}\n\t\t\t\t\t"); } } else { print_stop_message2('cant_overwrite_non_existent_language'); } } } // get current phrase types $current_phrasetypes = fetch_phrasetypes_array(false); if (!$master) { $globalPhrases = array(); $getphrases = $vbulletin->db->query_read("\n\t\t\tSELECT varname, fieldname\n\t\t\tFROM " . TABLE_PREFIX . "phrase\n\t\t\tWHERE languageid IN (0, -1)\n\t\t"); while ($getphrase = $vbulletin->db->fetch_array($getphrases)) { $globalPhrases["{$getphrase['varname']}~{$getphrase['fieldname']}"] = true; } } // import language // track new phrasetypes $new_phrasetypes = array(); foreach (array_keys($arr) as $key) { $phraseTypes =& $arr["{$key}"]; $sql = array(); $strlen = 0; if ($phraseTypes['fieldname'] == '' or !preg_match('#^[a-z0-9_]+$#i', $phraseTypes['fieldname'])) { continue; } $fieldname = $phraseTypes['fieldname']; if (!is_array($phraseTypes['phrase'][0])) { $phraseTypes['phrase'] = array($phraseTypes['phrase']); } // check if the phrasetype is new if (!isset($current_phrasetypes[$fieldname]) and !empty($phraseTypes['phrase'])) { $new_phrasetypes[] = array('fieldname' => $fieldname, 'title' => $phraseTypes['name']); } // Send some output to the browser inside this loop so certain hosts // don't artificially kill the script. See bug #34585 if ($output) { echo ' '; vbflush(); } foreach ($phraseTypes['phrase'] as $phrase) { if ($master) { $insertLanguageId = -1; } else { if (!isset($globalPhrases["{$phrase['name']}~{$fieldname}"])) { $insertLanguageId = 0; } else { if ($phrase['custom']) { // this is a custom phrase (language 0) -- we don't want it to end up in the custom language continue; } else { $insertLanguageId = $languageid; } } } $sql[] = "\n\t\t\t\t({$insertLanguageId},\n\t\t\t\t'" . $vbulletin->db->escape_string($fieldname) . "',\n\t\t\t\t'" . $vbulletin->db->escape_string($phrase['name']) . "',\n\t\t\t\t'" . $vbulletin->db->escape_string($phrase['value']) . "',\n\t\t\t\t'" . $vbulletin->db->escape_string($langinfo['product']) . "',\n\t\t\t\t'" . $vbulletin->db->escape_string($phrase['username']) . "',\n\t\t\t\t" . intval($phrase['date']) . ",\n\t\t\t\t'" . $vbulletin->db->escape_string($phrase['version']) . "')\n\t\t\t"; $strlen += strlen(end($sql)); if ($strlen > 102400) { // insert max of 100k of phrases at a time /*insert query*/ $vbulletin->db->query_write("\n\t\t\t\t\tREPLACE INTO " . TABLE_PREFIX . "phrase\n\t\t\t\t\t\t(languageid, fieldname, varname, text, product, username, dateline, version)\n\t\t\t\t\tVALUES\n\t\t\t\t\t\t" . implode(",\n", $sql)); $sql = array(); $strlen = 0; } // Send some output to the browser inside this loop so certain hosts // don't artificially kill the script. See bug #34585 if ($output) { echo ' '; vbflush(); } } if ($sql) { /*insert query*/ $vbulletin->db->query_write("\n\t\t\t\tREPLACE INTO " . TABLE_PREFIX . "phrase\n\t\t\t\t\t(languageid, fieldname, varname, text, product, username, dateline, version)\n\t\t\t\tVALUES\n\t\t\t\t\t" . implode(",\n", $sql)); } unset($arr["{$key}"], $phraseTypes); } unset($sql, $arr, $current_phrasetypes); // insert any new phrasetypes foreach ($new_phrasetypes as $phrasetype) { add_phrase_type($phrasetype['fieldname'], $phrasetype['title'], $langinfo['product']); } $vbulletin->db->query_write("\n\t\tUPDATE IGNORE " . TABLE_PREFIX . "phrase\n\t\tSET " . TABLE_PREFIX . "phrase.languageid = {$languageid}\n\t\tWHERE " . TABLE_PREFIX . "phrase.languageid = -11\n\t\t\tAND (" . TABLE_PREFIX . "phrase.product = '" . $vbulletin->db->escape_string($langinfo['product']) . "'" . iif($langinfo['product'] == 'vbulletin', " OR " . TABLE_PREFIX . "phrase.product = ''") . ")\n\t\t\t{$sql_skipped}\n\t"); // now delete any phrases that were moved into the temporary language for safe-keeping $vbulletin->db->query_write("\n\t\tDELETE FROM " . TABLE_PREFIX . "phrase\n\t\tWHERE languageid IN (-10, -11)\n\t\t\tAND (product = '" . $vbulletin->db->escape_string($langinfo['product']) . "'" . iif($langinfo['product'] == 'vbulletin', " OR product = ''") . ")\n\t\t\t{$sql_skipped}\n\t"); vB_Api::instanceInternal('phrase')->setPhraseDate(); print_dots_stop(); return $languageid; }
/** * Used by parsePage() to extract the data to return * * @param array|string The return value of the vB_Url call * @param array The URL parts * * @return array Array containing: * 'title' => $title, * 'meta' => $meta, * 'images' => (array) $imgurls, */ protected function extractData($data, $urlparts) { if (!is_array($data)) { $data = array('body' => $data); } if (!$data['body']) { // Don't throw exception here. Just return empty results return array('title' => '', 'meta' => '', 'images' => null); } $charset = false; // Check if we have content-type header and try to get charset from it if (!empty($data['headers']['content-type'])) { $charset = substr($data['headers']['content-type'], strrpos($data['headers']['content-type'], '=') + 1); if ($charset) { $data['body'] = '<?xml encoding="' . $charset . '">' . $data['body']; } } $dom = new DOMDocument(); libxml_use_internal_errors(true); if (!$dom->loadHTML($data['body'])) { // Invalid HTML. return empty results. return array('title' => '', 'meta' => '', 'images' => null); } // Get title $title = ''; if ($titlenode = $dom->getElementsByTagName("title")->item(0)) { $title = $titlenode->nodeValue; } if (!$title) { // If no title, try to get meta open graph title try { foreach ($dom->getElementsByTagName("meta") as $metanode) { if ($metanode->hasAttributes()) { $metaItem = $metanode->attributes->getNamedItem('property'); if (!empty($metaItem)) { if ($metaItem->nodeValue == 'og:title') { $title = $metanode->attributes->getNamedItem('content')->nodeValue; break; } } } } } catch (exception $e) { } //nothing we can do- just continue; } // Get Meta $meta = ''; foreach ($dom->getElementsByTagName("meta") as $metanode) { if ($metanode->hasAttributes()) { try { $metaItem = $metanode->attributes->getNamedItem('name'); if (!empty($metaItem)) { if ($metaItem->nodeValue == 'description') { $meta = $metanode->attributes->getNamedItem('content')->nodeValue; break; } } } catch (exception $e) { } //nothing we can do- just continue; } } if (!$meta) { // If no meta description, try to get meta open graph og:description try { foreach ($dom->getElementsByTagName("meta") as $metanode) { if ($metanode->hasAttributes()) { $metaItem = $metanode->attributes->getNamedItem('property'); if (!empty($metaItem)) { if ($metaItem->nodeValue == 'og:description') { $meta = $metanode->attributes->getNamedItem('content')->nodeValue; break; } } } } } catch (exception $e) { } //nothing we can do- just continue; } if (!$meta) { // If no meta og:description, try to get meta keywords try { foreach ($dom->getElementsByTagName("meta") as $metanode) { if ($metanode->hasAttributes()) { $metaItem = $metanode->attributes->getNamedItem('name'); if (!empty($metaItem)) { if ($metaItem->nodeValue == 'keywords') { $meta = $metanode->attributes->getNamedItem('content')->nodeValue; break; } } } } } catch (exception $e) { } //nothing we can do- just continue; } // Get baseurl $baseurl = ''; if ($basenode = $dom->getElementsByTagName("base")->item(0)) { if ($basenode->hasAttributes()) { $item = $basenode->attributes->getNamedItem('href'); if (!empty($item)) { $baseurl = $item->nodeValue; } } } if (!$baseurl) { // We assume that the baseurl is domain+path of $url $baseurl = $urlparts['scheme'] . '://'; if (!empty($urlparts['user'])) { $baseurl .= $urlparts['user'] . ':' . $urlparts['pass'] . '@'; } $baseurl .= $urlparts['host']; if (!empty($urlparts['port'])) { $baseurl .= ':' . $urlparts['port']; } if (!empty($urlparts['path'])) { $path = $urlparts['path']; // Remove filename from path $pos = strrpos($path, '/'); if ($pos !== false and $pos !== 0) { $path = substr($path, 0, $pos); } $baseurl .= $path; } } $baseurl = rtrim($baseurl, '/'); // Get images $imgurls = array(); // We need to add og:image if exists try { foreach ($dom->getElementsByTagName("meta") as $metanode) { if ($metanode->hasAttributes()) { $metaItem = $metanode->attributes->getNamedItem('property'); if (!empty($metaItem)) { if ($metaItem->nodeValue == 'og:image') { $imgurls[] = $metanode->attributes->getNamedItem('content')->nodeValue; // Don't break here. Because Open Graph allows multiple og:image tags } } } } } catch (exception $e) { } //nothing we can do- just continue; foreach ($dom->getElementsByTagName("img") as $imgnode) { if ($imgnode->hasAttributes() && $imgnode->attributes->getNamedItem('src')) { if ($imgurl = $imgnode->attributes->getNamedItem('src')->nodeValue) { $imgurls[] = $imgurl; } } } foreach ($imgurls as &$imgurl) { if (!$imgurl) { unset($imgurl); } // protocol-relative URL (//domain.com/logo.png) if (preg_match('|^//[a-z0-9-]+(\\.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i', $imgurl)) { // We add url scheme to the url $imgurl = $urlparts['scheme'] . ':' . $imgurl; } // relative url? make it absolute $imgurl = $this->rel2abs($imgurl, $baseurl); } $imgurls = array_unique($imgurls); // sendAsJSON will convert it to UTF-8, so if the board is in ISO-8859-1, it'll double-encode & break multibyte UTF-8 characters. // So we encode it from detected charset to the board's charset, & convert it if necessary. // If charset is not detected, then do not convert (TODO: automatically detect charset if not set in header) $boardCharset = vB_String::getCharset(); if ($charset and strtolower($charset) !== strtolower($boardCharset)) { $title = vB_String::toCharset($title, $charset, $boardCharset); $meta = vB_String::toCharset($meta, $charset, $boardCharset); $imgurls = vB_String::toCharset($imgurls, $charset, $boardCharset); } return array('title' => $title, 'meta' => $meta, 'images' => $imgurls); }
function print_apioutput($data) { global $VB_API_REQUESTS; // We need to convert $data charset if we're not using UTF-8 if (vB_String::getCharset() != 'UTF-8') { $data = vB_String::toCharset($data, vB_String::getCharset(), 'UTF-8'); } //If this is IE9 we need to send type "text/html". //Yes, we know that's not the standard. if (!headers_sent() and isset($_SERVER['HTTP_USER_AGENT']) and strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) { header('Content-type: text/plain; charset=UTF-8'); } else { header('Content-type: application/json; charset=UTF-8'); } // IE will cache ajax requests, and we need to prevent this - VBV-148 header('Cache-Control: max-age=0,no-cache,no-store,post-check=0,pre-check=0'); header('Expires: Sat, 1 Jan 2000 01:00:00 GMT'); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); header("Pragma: no-cache"); $output = json_encode($data); //we can get here because we failed to create the session so let's make sure its //a proper API session (hack alert). $currentSession = vB::getCurrentSession(); $apiclient = array(); if ($currentSession instanceof vB_Session_Api) { $apiclient = $currentSession->getApiClient(); } $vboptions = vB::getDatastore()->getValue('options'); if ($apiclient and !in_array($VB_API_REQUESTS['api_m'], array('user.login', 'user.logout'))) { $sign = md5($output . $apiclient['apiaccesstoken'] . $apiclient['apiclientid'] . $apiclient['secret'] . $vboptions['apikey']); @header('Authorization: ' . $sign); } echo $output; exit; }
/** reBuilds the fastDS data. This is called if the cached value is lost, or after upgrade. * * @param integer the maximum space allowed for caching this data. * * @return integer estimate of the space used. Note that we can't be exact. **/ protected function buildPhrases($maxSize) { self::$building = true; $languageid = vB::getDatastore()->getOption('languageid'); // Still don't have a language, fall back to master language if (!$languageid) { $languageid = -1; } $phrases = array(); $this->language = $languageid; if ($languageid > -1) { $languages = vB::getDatastore()->getValue('languagecache'); } //We sort by languageid. First we'll populate the default language, // then overwrite phrases with language-specific copies. That way // we have something for every phrase, but translated phrases // where available. $phraseQry = vB::getDbAssertor()->assertQuery('phrase', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, 'languageid' => array($languageid, 0, -1)), array('field' => array('languageid'), 'direction' => array(vB_dB_Query::SORT_DESC))); $search = array('/%/s', '/\\{([0-9]+)\\}/siU'); $replace = array('%%', '%\\1$s'); $this->phrasesCached = true; $size = 0; $used = array(); foreach ($phraseQry as $phrasedata) { if (isset($used[$phrasedata['varname']])) { continue; } $used[$phrasedata['varname']] = 1; $phrase = $phrasedata['text']; if (strpos($phrase, '{1}') !== false) { $phrase = preg_replace($search, $replace, $phrase); } if ($size + strlen($phrase) > $maxSize) { self::$building = false; return false; } if ($phrasedata['languageid'] > -1 and !empty($languages[$phrasedata['languageid']]['charset']) and $languages[$phrasedata['languageid']]['charset'] !== 'UTF-8') { $phrase = vB_String::toCharset($phrase, $languages[$phrasedata['languageid']]['charset'], 'UTF-8'); } $size += strlen($phrase) + strlen($phrasedata['varname']); $this->setPhrase($phrasedata['varname'], $phrase); } $this->phRebuilt = vB::getRequest()->getTimeNow(); self::$building = false; return $size; }