Commit 7ddd8fad authored by Dashamir Hoxha's avatar Dashamir Hoxha

Customize drupal features.

parent 64476f7c
......@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
Qtr_server Copyright (C) 2013 Dashamir Hoxha
Q-Translate Server Copyright (C) 2013 Dashamir Hoxha
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
......
......@@ -26,7 +26,7 @@ DOXYFILE_ENCODING = UTF-8
# identify the project. Note that if you do not use Doxywizard you need
# to put quotes around the project name if it contains spaces.
PROJECT_NAME = "Qtr_server"
PROJECT_NAME = "Q-Translate Server"
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
# This could be handy for archiving the generated documentation or
......
#!/usr/local/bin/drush @bcl php-script
<?php
/**
* Modifies the configuration of a Qtr_server site
* Modifies the configuration of a Q-Translate site
* that is installed for development. Not required,
* but sometimes can be useful.
*
......
......@@ -6,7 +6,7 @@ source /host/settings.sh
db_name=qtr
db_user=qtr
db_pass=qtr
site_name="Qtr_server"
site_name="Q-Translate"
site_mail="$GMAIL_ADDRESS"
account_name=admin
account_pass="$ADMIN_PASS"
......
......@@ -3,7 +3,7 @@
source /host/settings.sh
### make sure that we have the right git branch on the make file
makefile="$CODE_DIR/build-qtr_server.make"
makefile="$CODE_DIR/build-qtrserver.make"
git_branch=$(git -C $CODE_DIR branch | cut -d' ' -f2)
sed -i $makefile \
-e "/qtr_server..download..branch/ c projects[qtr_server][download][branch] = $git_branch"
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Put any custom modules here.
<?php
/**
* @file
* Administrative pages for the qtrCore module.
*/
/**
* General configuration settings for the module qtrCore.
*
* @return
* An array containing form items to place on the module settings page.
*/
function qtrCore_config() {
$form['config'] = array(
'#type' => 'fieldset',
'#title' => t('Q-Translate Configuration'),
);
// qtr_languages
$form['config']['qtr_languages'] = array(
'#type' => 'textfield',
'#title' => t('Translation Languages'),
'#default_value' => variable_get('qtr_languages', 'en'),
'#description' => t('The list of translation languages supported by the server. Enter a space separated list of language codes.'),
);
// qtr_client
$form['config']['qtr_client'] = array(
'#type' => 'textfield',
'#title' => t('Client URL'),
'#default_value' => variable_get('qtr_client', 'https://qtranslate.net'),
'#description' => t('URL of the default client.'),
);
$form = system_settings_form($form);
$form['#submit'][] = 'qtrCore_config_set_languages';
return $form;
}
/**
* Update cached values of languages.
*/
function qtrCore_config_set_languages() {
// Update 'allowed_values' of 'field_translation_lng'.
$info = field_info_field('field_translation_lng');
$info['settings']['allowed_values'] = qtr::lng_get_list();
field_update_field($info);
}
<?php
/**
* @file
* Form for backup/restore of Q-Translate data.
*/
/**
* Backup and restore Q-Translate data.
*
* @return
* An array containing form items.
*/
function qtrCore_backup() {
$form = [
// Backup.
'data_backup' => [
'#type' => 'fieldset',
'#title' => t('Backup Q-Translate Data'),
'#description' => t('Backup users, translations and likes, etc.'),
'submit' => [
'#value' => t('Backup'),
'#type' => 'submit',
],
],
// Restore.
'data_restore' => [
'#type' => 'fieldset',
'#title' => t('Restote Q-Translate Data'),
'#description' => t('Restore users, translations and likes, etc.'),
'file' => [
'#type' => 'file',
'#title' => t('Backup File'),
'#description' => t('Upload a backup file.'),
],
'submit' => [
'#value' => t('Restore'),
'#type' => 'submit',
],
],
];
return $form;
}
/**
* Implement of hook form_submit() for the form qtrCore_backup.
*/
function qtrCore_backup_submit($form, &$form_state) {
$form_values = $form_state['values'];
$op = $form_values['op'];
if ($op == t('Backup')) {
// Make a backup.
_qtrCore_backup_make();
}
if ($op == t('Restore')) {
// Restore a backup.
_qtrCore_backup_restore();
}
}
/**
* Make a backup.
*/
function _qtrCore_backup_make() {
// Allow the backup script to run until completion.
set_time_limit(0);
// Execute the backup script.
$path = drupal_get_path('module', 'qtrCore');
exec("$path/data/db/backup.sh 2>&1", $output);
// Display any notification messages.
if (!empty($output)) {
foreach ($output as $line) {
if (trim($line) == '') continue;
if ($line == 'mysqldump: [Warning] Using a password on the command line interface can be insecure.') continue;
drupal_set_message($line, 'error');
}
}
// Get the name of the backup file.
$date = date('Ymd');
$backup_file = "/tmp/qtr-backup-$date.tgz";
// Send the headers.
$filename = basename($backup_file);
header('Content-Type: application/x-compressed');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Transfer-Encoding: binary');
header("Content-Length: " . filesize($backup_file));
// Open the file in a binary mode and send it to the browser.
$fp = fopen($backup_file, 'rb');
fpassthru($fp);
// Cleanup.
unlink($backup_file);
// Stop execution.
drupal_exit();
}
/**
* Restore a backup.
*/
function _qtrCore_backup_restore() {
// Check that a file is uploaded.
if (!$_FILES['files']['tmp_name']['file']) {
drupal_set_message(t('No file is uploaded.'), 'error');
return;
}
// Check for any other upload errors.
if ($_FILES['files']['error']['file'] != 0) {
drupal_set_message(t("Error !error happened during file upload.",
['!error' => $_FILES['files']['error']['file']]), 'error');
return;
}
// Restore the backup.
$filename = $_FILES['files']['tmp_name']['file'];
$path = drupal_get_path('module', 'qtrCore');
exec("$path/data/db/restore.sh $filename 2>&1", $output);
// Display any notification messages.
if (!empty($output)) {
foreach ($output as $line) {
if (trim($line) == '') continue;
if ($line == 'mysql: [Warning] Using a password on the command line interface can be insecure.') continue;
drupal_set_message($line, 'error');
}
}
else {
drupal_set_message(t('Backup restored successfully.'));
}
// Cleanup.
unlink($filename);
}
<?php
/**
* @file
* AJAX callback functions.
*/
/**
* Retrieve a JSON list of autocomplete suggestions for users.
*/
function qtrCore_user_autocomplete($lng, $str = '') {
$matches = array();
if ($str) {
$query = "SELECT name FROM {qtr_users}
WHERE name LIKE :str AND ulng = :ulng
ORDER BY name";
$args = array(
':str' => $str . '%',
':ulng' => $lng,
);
$result = qtr::db_query_range($query, 0, 10, $args);
foreach ($result as $user) {
$matches[$user->name] = check_plain($user->name);
}
}
print drupal_json_encode($matches);
exit();
}
<?php
/**
* Menu callback for 'chapters'.
* Returns a json list of chapters and their details.
*/
function qtrCore_chapters() {
drupal_json_output(qtr::chapters());
drupal_exit();
}
<?php
/**
* @file
* Callback function for menu path: export
*/
/**
* Callback function for the menu 'export'
*
* Return translations of a language as a text file.
*
* Does not allow concurrent exports because they may affect the performance
* of the server. Parameters are received from the request (either GET or
* POST). They are:
*
* - lng
* Translation to be exported.
*
* - chapter
* Number of the chapter to be exported.
*
* - mode
* Mode of export: most_liked | preference
*
* Default is 'most_liked' which exports the translations with the biggest
* number of likes.
*
* The export mode 'preference' gives priority to translations that are
* liked by a certain user or a group of users. It requires an additional
* argument (users) to specify the user (or a list of users) whose
* translations are preferred.
*
* - users
* Comma separated list of usernames of the preferred voters.
*
* Examples:
* curl -k 'https://qtranslate.org/export?lng=en' > quran_en.txt
* curl -k https://qtranslate.org/export \
* -d 'lng=en&chapter=1' > chapter1_en.txt
* curl -k https://qtranslate.org/export \
* -d chapter=2 -d lng=en \
* -d export_mode=preference \
* -d users=user1,user2 > chapter1_en.txt
*/
function qtrCore_export() {
// Try to avoid concurrent exports because they
// may affect the performance of the server.
if (!lock_acquire('export')) {
drupal_set_message(t("Error: Server is currently busy. Please try to export again later."), 'error');
drupal_goto();
}
// Get the parameters.
$lng = check_plain($_REQUEST['lng']);
if ($lng == '') {
drupal_set_message(t("The language parameter is required"), 'error');
drupal_goto();
}
else if (!qtr::lng_check($lng)) {
drupal_set_message(t("The language '!lng' does not exist.", ['!lng' => "$lng"]), 'error');
drupal_goto();
}
// Get the option 'chapter'
$chapter = check_plain($_REQUEST['chapter']);
if ($chapter != '' && ($chapter < 1 || $chapter > 114)) {
drupal_set_message(t("Chapter '!chapter' is out of range.", ['!chapter' => $chapter]), 'error');
drupal_goto();
}
// Get the export mode.
$mode = check_plain($_REQUEST['mode']);
if (empty($mode)) $mode = 'most_liked';
if ($mode != 'most_liked' && $mode != 'preference') {
drupal_set_message(t("Unknown export mode '!mode'.", ['!mode' => $mode]), 'error');
drupal_goto();
}
// Get and check the list of preferred voters.
$users = check_plain($_REQUEST['users']);
if ($mode == 'preference') {
if (empty($users)) {
if (user_is_anonymous()) {
drupal_set_message(t("No users given."), 'error');
drupal_goto();
}
else {
$users = $GLOBALS['user']->name;
}
}
list($emails, $messages) = qtr::utils_get_emails($users);
if (!empty($messages)) {
foreach ($messages as $msg) {
drupal_set_message($msg[0], 'error');
}
drupal_goto();
}
}
// Export translations of the project.
set_time_limit(0);
$file = qtr::export($lng, $chapter, $mode, $emails);
// Send the headers.
$filename = ($chapter ? "quran-$lng.$chapter.txt" : "quran-$lng.txt");
header('Content-Type: text/plain; charset=utf-8');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Transfer-Encoding: binary');
header("Content-Length: " . filesize($file));
// Open the file in a binary mode and dump it to the browser.
$fp = fopen($file, 'rb');
fpassthru($fp);
// Cleanup temporary file.
unlink($file);
// Stop execution.
lock_release('export');
drupal_exit();
}
<?php
/**
* Menu callback for 'languages'.
* Returns a json list of languages and their details.
*/
function qtrCore_languages() {
$languages = qtr::lng_get_details();
drupal_json_output($languages);
drupal_exit();
}
<?php
/**
* @file
* Return the latest translations in JSON format.
*/
/**
* Return the latest translations in JSON format.
*
* If the option $days is given, return all the translations since that many
* days ago. Otherwise, only the translations since yesterday.
*
* If the option $limit is given, then return that many translations from the
* latest ones, regardless of their time. This takes precedence over the option
* $days.
*
* Each of the returned translations has these fields:
* chapter_id, verse_nr, vid, lng, translation, tguid, time, username, usermail
*
* Results will be cached for 2 hours.
*/
function qtrCore_latest($lng ='en', $days = NULL, $limit = NULL) {
// Get the data from cache, if possible.
$cache_id = "qtrCore_latest:$lng:$days:$limit";
$cache = cache_get($cache_id, 'cache_qtrCore');
if (!empty($cache) && isset($cache->data) && !empty($cache->data)) {
$latest = $cache->data;
}
else {
// Get the latest translations from the database.
$latest = qtr::translation_latest($lng, $days, $limit);
// Cache them for 2 hours.
cache_set($cache_id, $latest, 'cache_qtrCore', strtotime('+2 hours'));
}
// Output latest translations in JSON format and exit.
print drupal_json_encode($latest);
exit();
}
<?php
/**
* @file
* Menu callbacks.
*/
/**
* Callback for 'rss-feed'.
*/
function qtrCore_rss_feed($lng = 'en') {
// Get the feed data from cache, if possible.
$cache = cache_get("qtrCore_rss_feed:$lng", 'cache_qtrCore');
if (!empty($cache) && isset($cache->data) && !empty($cache->data)) {
$rss_feed = $cache->data;
drupal_add_http_header('Content-Type', 'application/rss+xml; charset=utf-8');
print $rss_feed;
return;
}
// Get the latest translations.
$translations = qtr::translation_latest($lng);
// Get the url of the translation site.
module_load_include('inc', 'qtrCore', 'lib/sites');
$client_url = qtr::utils_get_client_url($lng);
// Start building the RSS feed output.
$rss_feed = '<?xml version="1.0" encoding="utf-8"?>' . "\n";
$rss_feed .= '<rss version="2.0">';
$link = url("rss-feed/$lng", array('absolute' => TRUE));
$title = variable_get('site_name', 'Q-Translate');
$description = t('Latest translations on Q-Translate');
$ttl = 180;
$site_mail = variable_get('site_mail');
$site_name = variable_get('site_name');
$web_master = "$site_mail ($site_name)";
$last_build_date = date('r');
$rss_feed .= "
<channel>
<title>$title</title>
<link>$link</link>
<description>$description</description>
<category>Q-Translate</category>
<language>$lng</language>
<ttl>$ttl</ttl>
<webMaster>$web_master</webMaster>
<lastBuildDate>$last_build_date</lastBuildDate>
";
// Append an item for each translation.
foreach ($translations as $trans) {
extract(get_object_vars($trans));
$title = "[$chapter_id:$verse_nr] " . qtr::utils_shorten($translation, 50);
$link = $client_url . "/qtr/$lng/$chapter_id/$verse_nr";
$description = "[$chapter_id:$verse_nr] $translation";
$pub_date = date('r', strtotime($time));
$rss_feed .= "
<item>
<title>$title</title>
<link>$link</link>
<description><![CDATA[$description]]></description>
<author>$usermail ($username)</author>
<guid isPermaLink='false'>$tguid</guid>
<pubDate>$pub_date</pubDate>
</item>
";
}
// Close the XML elements.
$rss_feed .= "</channel>\n";
$rss_feed .= "</rss>\n";
// Cache for 2 hours.
cache_set("qtrCore_rss_feed:$lng", $rss_feed, 'cache_qtrCore', strtotime('+2 hours'));
// Send the output.
drupal_add_http_header('Content-Type', 'application/rss+xml; charset=utf-8');
print $rss_feed;
}
<?php
/**
* @file
* Return a random translation in a suitable form for the twitter.
*
* If the request header 'Accept: application/json' is set, then
* the output will be in JSON. This can be useful for adding your custom
* hashtags, url, etc.
*
* Examples:
* curl -q -k https://qtranslate.org/tweet/en
* curl -q -k -H 'Accept: application/json' \
* https://qtranslate.org/tweet/en
*/
function qtrCore_tweet($lng =NULL) {
if (empty($lng)) $lng = 'en';
// Get a random translation.
$vid = rand(1, 6236);
$verse = qtr::db_query(
'SELECT * FROM {qtr_verses} WHERE vid = :vid',
[':vid' => $vid]
)->fetch();
$cid = $verse->cid;
$nr = $verse->nr;
$translations = qtr::db_query(
'SELECT translation FROM {qtr_translations} WHERE vid = :vid AND lng = :lng',
[':vid' => $vid, ':lng' => $lng ]
)->fetchCol();
// Build the tweet.
$i = rand(0, sizeof($translations) - 1);
$tweet = $translations[$i];
if (empty($tweet)) {
$tweet = t('Error: No string found!');
}
else {
if (strlen($tweet) > 80) {
$tweet = substr($tweet, 0, strrpos(substr($tweet, 0, 80-3), ' '));
$tweet .= '...';
}
}
// If the request has the header 'Accept: application/json'
// return the output in JSON format.
if ($_SERVER['HTTP_ACCEPT'] == 'application/json') {
//drupal_add_http_header('Content-Type', 'application/json; utf-8');
print drupal_json_encode(array(
'lng' => $lng,
'chapter' => $cid,
'verse' => $nr,
'tweet' => $tweet,
));
exit;
}
// Append hash tags, url, etc.
$tweet = "[Quran $cid:$nr] $tweet #quran_$lng";
if (isset($_GET['url'])) {
$url = $_GET['url'];
$tweet .= ' ' . $url;
}
else {
module_load_include('inc', 'qtrCore', 'includes/sites');
$client_url = qtr::utils_get_client_url($lng);
$tweet .= ' ' . $client_url . "/qtr/$lng/$cid/$nr";
}
print $tweet;
exit(0);
}