Exemplo n.º 1
0
 /**
  * Get Meta Info from language translation file content.
  * @param mixed 		The contents of the file using file() or get_file_contents().
  * @param array  	A blank array, strings will be returned by association
  * @param array  	Optional associative array of reference strings
  * @return array		The Meta Info in an array
  */
 function getINIMeta($content, &$strings, $ref_strings = null)
 {
     // convert a string to an array
     if (is_string($content)) {
         $content = explode("\n", $content, 10);
     } else {
         if (!is_array($content)) {
             $content = array();
         }
     }
     // look for a Byte-Order-Marker at the start of the file
     $file['bom'] = 'UTF-8';
     if ($content) {
         $bom = strtolower(bin2hex(substr($content[0], 0, 4)));
         if ($bom == '0000feff') {
             $file['bom'] = 'UTF-32 BE';
         } else {
             if ($bom == 'feff0000') {
                 $file['bom'] = 'UTF-32 LE';
             } else {
                 if (substr($bom, 0, 4) == 'feff') {
                     $file['bom'] = 'UTF-16 BE';
                 } else {
                     if (substr($bom, 0, 4) == 'fffe') {
                         $file['bom'] = 'UTF-16 LE';
                     }
                 }
             }
         }
     }
     // parse the top line from one of these two formats
     //	# $Id: en-GB.mod_poll.ini 6167 2007-01-04 01:16:01Z eddiea $
     //	# version 1.5.0 2007-01-25 10:40:16 ~0 +0
     if (strpos($content[0], '.ini')) {
         $line = preg_replace('/^.*[.]ini[ ]+/', '', $content[0]);
         list($file['version'], $file['date'], $file['time'], $file['owner'], $file['complete']) = explode(' ', $line . '   ', 6);
         $file['headertype'] = 1;
     } else {
         $line = preg_replace('/^.*version/i', '', $content[0]);
         $line = trim($line);
         list($file['version'], $file['date'], $file['time'], $file['complete']) = explode(' ', $line . '   ', 5);
         $file['owner'] = '';
         $file['headertype'] = 2;
     }
     // tidy up the values
     $file['complete'] = preg_replace('/[^0-9]/', '', $file['complete']);
     $file['author'] = preg_replace('/^.*author[ ]+/i', '', trim($content[1], '# '));
     $file['copyright'] = preg_replace('/^.*copyright[ ]+/i', '', trim($content[2], '# '));
     $file['license'] = preg_replace('/^.*license[ ]+/i', '', trim($content[3], '# '));
     // parse the strings in the file into an associative array
     $strings = array();
     foreach ($content as $line) {
         $line = trim($line);
         // 1: skip comments and blanks
         // 2: get the ucase key and value
         if (empty($line) || $line[0] == '#' || $line[0] == ';') {
             continue;
         } else {
             if (strpos($line, '=')) {
                 list($key, $value) = explode('=', $line, 2);
                 $key = strtoupper($key);
                 $strings[$key] = $value;
             }
         }
     }
     // get the status compared to the ref strings
     $file = array_merge($file, TranslationsHelper::getINIstatus($ref_strings, $strings));
     // set a complete flag
     if ($file['complete'] == $file['unchanged'] && $file['missing'] == 0) {
         $file['status'] = 100;
     }
     // return
     return $file;
 }
Exemplo n.º 2
0
 /**
  * Create Edit or Save a Translation File
  */
 function edit()
 {
     // import file functions
     jimport('joomla.filesystem.file');
     // variables
     global $mainframe;
     $options =& $this->getOptions();
     // build the search highlight array
     $options['filter_search'] = $mainframe->getUserStateFromRequest('com_translationsmanager.files.filter_search', 'filter_search', '');
     // we are creating a new file
     // always in the reference language
     if ($options['task'] == 'add') {
         $options['newprocess'] = 1;
         if (!$options['isReference']) {
             $mainframe->enqueueMessage(JText::_('Always create in reference language'));
         }
     }
     // we are in the process of creating a new file
     // the filename is set by the 'newfilename' field
     if ($options['newprocess']) {
         $options['newfilename'] = strtolower(JRequest::getVar('newfilename', '', '', 'string'));
         // validate the filename
         if ($options['newfilename']) {
             // strip off ini
             if (substr($options['newfilename'], -4) == '.ini') {
                 $options['newfilename'] = substr($options['newfilename'], 0, -4);
             }
             // strip off language
             if (preg_match('/^[a-z]{2}-[a-z]{2}[.].*/', $options['newfilename'])) {
                 $options['newfilename'] = substr($options['newfilename'], 6);
             }
             // set variables
             $options['filename'] = $options['lang'] . '.' . $options['newfilename'] . '.ini';
         } else {
             // report error
             $mainframe->enqueueMessage(JText::_('filename desc'));
             // change task
             if ($options['task'] != 'add') {
                 $options['task'] = 'edit';
                 $options['field_error_list']['filename'] = JText::_('filename');
             }
         }
     } else {
         if (empty($options['filename'])) {
             $mainframe->enqueueMessage(JText::_('You must select a file to edit'));
             $mainframe->redirect('index.php?option=com_translationsmanager&task=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=com_translationsmanager&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=com_translationsmanager&task=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']) && $options['task'] != 'add') {
         $mainframe->enqueueMessage(sprintf(JText::_('Values Required'), implode(', ', $options['field_error_list'])));
         $options['task'] = 'edit';
     }
     // create a new file or save an existing file
     if ($options['task'] == 'apply' || $options['task'] == 'save') {
         // 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'] = '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') {
         $this->_multitask('checkin', $options['filename'], 'files', false);
     } else {
         $view = $this->getView($this->_name, 'html');
         $view->setLayout('edit');
         $view->assignRef('data', $editData);
         $view->assignRef('meta', $editMeta);
         $view->assignRef('options', $options);
         $view->display();
         if (!$options['newprocess']) {
             $this->_multitask('checkout', $options['filename'], false, false);
         }
     }
 }