/** * Create Edit or Save a Translation File */ function edit_language() { global $option; // import file functions jimport('joomla.filesystem.file'); // variables global $mainframe; $options = Language_manager::getOptions(); $options['newprocess'] = 0; // build the search highlight array $options['filter_search'] = $mainframe->getUserStateFromRequest($option . '.files.filter_search', 'filter_search', ''); // 2: otherwise verify that we have a filename // 3: otherwise validate the checkout status of the selected file if (empty($options['filename'])) { $mainframe->enqueueMessage(JText::_('You must select a file to edit')); $mainframe->redirect('index.php?option=' . $option . '&task=language_files'); } else { if ($content = @file_get_contents($options['langPath'] . DS . 'chk.' . $options['filename'])) { list($timestamp, $userid, $username) = explode('#', $content . '##'); $user =& JFactory::getUser(); // validate the checkout if (time() - $timestamp < 3600 && $userid != 0 && $userid != $user->get('id', '0')) { // report and redirect $checkin = '<a href="index.php?option=' . $option . '&task=checkin&id=' . $options['filename'] . '" title="' . JText::_('Force Checkin') . '" style="font-size:smaller">[' . JText::_('Checkin') . ']</a>'; $mainframe->enqueueMessage(sprintf(JText::_('checked out by'), $options['filename'], $username, $checkin)); $mainframe->redirect('index.php?option=' . $option . '&task=language_files'); } } } // set the reference language filename from the selected filename $options['refFilename'] = str_replace($options['lang'], $options['refLang'], $options['filename']); // find the published reference language file // default to an unpublished reference file if (JFile::exists($options['refLangPath'] . DS . $options['refFilename'])) { $options['ref_path_file'] = $options['refLangPath'] . DS . $options['refFilename']; } else { $options['ref_path_file'] = $options['refLangPath'] . DS . 'xx.' . $options['refFilename']; } // find the published selected language file // default to an unpublished new file if (JFile::exists($options['langPath'] . DS . $options['filename'])) { $options['path_file'] = $options['langPath'] . DS . $options['filename']; } else { $options['path_file'] = $options['langPath'] . DS . 'xx.' . $options['filename']; } // STRINGS: initialise $editData from the reference language file contents // $editData is an analogue of the reference file // header lines are skipped // comments and blank lines are strings with an integer index // key=value pairs are arrays with the key as an index $editData = array(); $header = 0; $refStrings = array(); if ($refContent = @file($options['ref_path_file'])) { foreach ($refContent as $k => $v) { $v = trim($v); // grab the comments (but skip up to 6 lines before we have any strings in the file) // grab the strings if (empty($v) || $v[0] == '#' || $v[0] == ';') { if ($header++ > 6) { $editData[$k] = $v; } } else { if (strpos($v, '=')) { $header = 7; list($key, $value) = explode('=', $v, 2); $key = strtoupper($key); $refStrings[$key] = $value; $editData[$key] = array('ref' => $value, 'edit' => $value); if ($options['isReference']) { $editData[$key]['lang_file'] = $value; } } } } } // STRINGS: load the selected file contents and process into $editData // only when the selected language is not the same as the reference language if ($options['isReference']) { $fileContent = $refContent; $fileStrings = array(); $fileMeta = TranslationsHelper::getINIMeta($fileContent, $fileStrings); $editStrings = $fileStrings; } else { if ($fileContent = @file($options['path_file'])) { $fileStrings = array(); $fileMeta = TranslationsHelper::getINIMeta($fileContent, $fileStrings); $editStrings = $fileStrings; foreach ($fileStrings as $k => $v) { $editData[$k]['edit'] = $v; $editData[$k]['lang_file'] = $v; } } else { $fileContent = array(); $fileStrings = array(); $fileMeta = array('headertype' => 1, 'owner' => 'ff', 'complete' => 0); $editStrings = array(); } } // STRINGS: load the user form contents and process into $editData $editFormOnly = array(); if ($FormKeys = JRequest::getVar('ffKeys', array(), '', 'ARRAY', JREQUEST_ALLOWRAW)) { $FormValues = JRequest::getVar('ffValues', array(), '', 'ARRAY', JREQUEST_ALLOWRAW); // process each key=value pair from the form into $editData foreach ($FormKeys as $k => $v) { if ($v && isset($FormValues[$k])) { $key = strtoupper(trim(stripslashes($v))); $value = trim(stripslashes(str_replace('\\n', "\n", $FormValues[$k]))); $editStrings[$key] = $value; $editData[$key]['edit'] = $value; $editData[$key]['user_form'] = $value; } } // every element of $editData must have a form entry foreach ($editData as $k => $v) { if (is_array($v) && !isset($v['user_form'])) { unset($editStrings[$k]); unset($editData[$k]); } } } // META: get the XML and status meta then initialise $options['XMLmeta'] = TranslationsHelper::getXMLMeta($options['langPath'] . DS . $options['lang'] . '.xml'); $statusMeta = TranslationsHelper::getINIstatus($refStrings, $editStrings); $editMeta = array_merge($options['XMLmeta'], $fileMeta, $statusMeta); $editMeta['filename'] = $options['filename']; // META: apply any user form values foreach ($editMeta as $k => $v) { $editMeta[$k] = JRequest::getVar($k, $v, '', 'string'); } // META: require meta values foreach (array('version', 'author') as $v) { if (empty($editMeta[$v])) { $options['field_error_list'][$v] = JText::_($v); } } // ERRORS: report any errors and change the task if (!empty($options['field_error_list'])) { $mainframe->enqueueMessage(sprintf(JText::_('Values Required'), implode(', ', $options['field_error_list']))); $options['task'] = 'language_edit'; } // create a new file or save an existing file if ($options['task'] == 'apply_language' || $options['task'] == 'save_language') { // ensure the file does not already exist when we are creating a new file if ($options['newprocess'] && JFile::exists($options['path_file'])) { // report error and set task flag $mainframe->enqueueMessage(sprintf(JText::_('Language INI Exists'), $options['newfilename'])); $options['task'] = 'language_edit'; } else { // check the complete status // we set the complete value to the number of strings that are 'unchanged' // so that if the reference INI file should change the 'complete' flag is unset/broken $editMeta['complete'] = JRequest::getVar('complete', '', 'post', 'string'); $editMeta['complete'] = $editMeta['complete'] == 'COMPLETE' ? $editMeta['unchanged'] : 0; // build the header if ($editMeta['headertype'] == 1) { $saveContent = '# $Id: ' . $options['filename'] . ' ' . $editMeta['version'] . ' ' . date('Y-m-d H:i:s') . ' ' . $editMeta['owner'] . ' ~' . $editMeta['complete'] . ' $'; } else { $saveContent = '# version ' . $editMeta['version'] . ' ' . date('Y-m-d H:i:s') . ' ~' . $editMeta['complete']; } $saveContent .= "\n" . '# author ' . $editMeta['author']; $saveContent .= "\n" . '# copyright ' . $editMeta['copyright']; $saveContent .= "\n" . '# license ' . $editMeta['license']; $saveContent .= "\n\n" . '# Note : All ini files need to be saved as UTF-8'; $saveContent .= "\n\n"; // process the $editData array to get the remaining content $changedStrings = array(); $header = 0; foreach ($editData as $k => $v) { // 1: add a blank line or comment // 2: add a key=value line (no need to addslashes on quote marks) if (!is_array($v)) { $saveContent .= $v . "\n"; } else { // change newlines in the value $value = preg_replace('/(\\r\\n)|(\\n\\r)|(\\n)/', '\\n', $v['edit']); // change single-quotes or backticks in the value if ($options['backticks'] > 0) { $value = strtr($value, "'", '`'); } else { if ($options['backticks'] < 0) { $value = strtr($value, '`', "'"); } } // set back to $editData $editData[$k]['edit'] = $value; // add to file content $saveContent .= $k . '=' . $value . "\n"; // if the string is in the selected language file if (isset($v['lang_file'])) { // and it has changed (via the user form) if ($v['lang_file'] != $v['edit']) { // log the change in a translation array $changedStrings["\n" . $k . '=' . $v['lang_file']] = "\n" . $k . '=' . $v['edit']; } } } } // if there is no reference Language File, automatically initialise/create one which is the same as the selected language file if ($options['refLangMissing']) { if (JFile::write($options['refLangPath'] . DS . $options['refLangFile'], trim($saveContent))) { $mainframe->enqueueMessage(sprintf(JText::_('Language INI Created'), $options['refLangFile'])); } } // 1: write the selected language file and clear newprocess flag // 2: report failure if (JFile::write($options['path_file'], trim($saveContent))) { $mainframe->enqueueMessage(sprintf(JText::_('Language INI ' . ($options['newprocess'] ? 'Created' : 'Saved')), $options['clientName'], $options['filename'])); $options['newprocess'] = 0; } else { $mainframe->enqueueMessage(sprintf(JText::_('Could not write to file'), $options['path_file'])); } // process changed strings globally across all the the ini files from the selected language directory if (count($changedStrings) && $options['globalChanges']) { $write = 0; $writeFiles = array(); if ($files = JFolder::files($options['langPath'])) { foreach ($files as $file) { // skip non-INI files // skip this file // skip this file (unpublished) // skip checked out files if (strtolower(substr($file, -4) != '.ini') || $file == $options['filename'] || $file == 'xx.' . $options['filename'] || array_search($options['langPath'] . DS . 'chk.' . $file, $files)) { continue; } // otherwise grab the file content if ($content = file_get_contents($options['langPath'] . DS . $file)) { // parse the changed strings $new_content = strtr($content, $changedStrings); // check for changes then write to the file if ($new_content != $content) { if (JFile::write($options['langPath'] . DS . $file, trim($new_content))) { $writeFiles[$write++] = $file; } } } } } // report if ($write) { $mainframe->enqueueMessage(sprintf(JText::_('Global String Change'), $write, implode('; ', $writeFiles))); } } } } // 1: checkin when we are saving (this will redirect also) // 2: call the html when we are editing or applying (and checkout existing files) if ($options['task'] == 'save_language') { Language_manager::multitask('checkin', $options['filename'], 'language_files', false); } else { Language_manager_html::Show_edit($editData, $editMeta, $options); if (!$options['newprocess']) { Language_manager::multitask('checkout', $options['filename'], false, false); } } }
/** * Package INI files into an installation zip file */ function package() { // variables global $mainframe; $options =& $this->getOptions(); $files = array(); // set the zip path // optionally change the tag if there is a [tag=xx-XX] in the path $zippath = '/' . $options['config']->get('zippath', 'tmp/[tag].[client].zip'); $ziptag = $options['lang']; if (preg_match('/\\[tag=([^\\]]*)\\]/', $zippath, $match)) { $zippath = str_replace($match[0], '[tag]', $zippath); if (preg_match('/^[a-z]{2}-[a-z]{2}$/i', $match[1])) { $ziptag = strtolower(substr($match[1], 0, 2)) . '-' . strtoupper(substr($match[1], -2)); $mainframe->enqueueMessage(sprintf(JText::_('ZIP Translate Tag'), $options['lang'], $ziptag)); } } // process all the files in the selected language directory into an array ready to be packaged // translate the language tag if configured jimport('joomla.filesystem.file'); foreach (JFolder::files($options['langPath']) as $k => $filename) { // 1: grab the XML data and info // 2a: skip checkout marker files // 2b: grab the INI data into the files array if ($filename == $options['lang'] . '.xml') { $xmlname = $filename; $xmldata = file_get_contents($options['langPath'] . DS . $filename); $xmltime = filemtime($options['langPath'] . DS . $filename); $xml = TranslationsHelper::getXMLMeta($options['langPath'] . DS . $filename); $xml['client'] = $options['clientKey']; $xml['tag'] = $ziptag; $xmlname = str_replace($options['lang'], $ziptag, $xmlname); $xmldata = str_replace($options['lang'], $ziptag, $xmldata); } else { if (substr($filename, -4) == '.ini') { if (substr($filename, 0, 4) == 'chk.') { continue; } else { $k = substr($filename, 0, 3) == 'xx.' ? substr($filename, 3) : $filename; $k = str_replace($options['lang'], $ziptag, $k); $files[$k]['name'] = $k; $files[$k]['data'] = file_get_contents($options['langPath'] . DS . $filename); $files[$k]['time'] = filemtime($options['langPath'] . DS . $filename); } } } } // check we have XML data and files if (!isset($xml)) { JError::raiseNotice(500, sprintf(JText::_('ZIP No XML'), $options['clientKey'] . 'DS' . $options['lang'] . '.xml')); } else { if (!count($files)) { JError::raiseNotice(500, sprintf(JText::_('ZIP No Files'), $options['clientKey'])); } else { // sort the files ksort($files); // build the XML install file $install = '<?xml version="1.0" encoding="utf-8" ?> <install version="1.5" client="' . $xml['client'] . '" type="language"> <name>' . $xml['name'] . '</name> <tag>' . $xml['tag'] . '</tag> <version>' . $xml['version'] . '</version> <creationDate>' . $xml['creationDate'] . '</creationDate> <author>' . $xml['author'] . '</author> <authoremail>' . $xml['authorEmail'] . '</authoremail> <authorurl>' . $xml['authorUrl'] . '</authorurl> <copyright>' . $xml['copyright'] . '</copyright> <license>' . $xml['license'] . '</license> <description>' . $xml['description'] . '</description> <files>'; foreach ($files as $k => $v) { $install .= ' <filename>' . $v['name'] . '</filename>'; } $install .= ' <filename file="meta">' . $xmlname . '</filename> </files> <params /> </install>'; // finish the files array $files['xml']['name'] = $xmlname; $files['xml']['data'] = $xmldata; $files['xml']['date'] = $xmltime; $files['install']['name'] = 'install.xml'; $files['install']['data'] = $install; $files['install']['date'] = time(); // configure the package filename and type $type = substr($zippath, strrpos($zippath, '.') + 1); $zippath = str_replace('[client]', $xml['client'], $zippath); $zippath = str_replace('[tag]', $xml['tag'], $zippath); $ziproot = JPATH_ROOT . $zippath; $zipfile = substr($zippath, strrpos($zippath, DS) + 1); $ziplink = JURI::root() . $zipfile; // run the packager jimport('joomla.filesystem.archive'); if (!($packager =& JARchive::getAdapter($type))) { JError::raiseWarning(500, sprintf(JText::_('ZIP Adapter Failure'), $type)); } else { if ($packager->create($ziproot, $files, array())) { $mainframe->enqueueMessage(sprintf(JText::_('ZIP Create Success'), $ziplink, $zipfile)); } else { JError::raiseNotice(500, sprintf(JText::_('ZIP Create Failure'), $ziplink)); } } } } // Redirect to the default page $mainframe->redirect('index.php?option=com_translationsmanager'); }