public static function log($msg, $data = NULL, $depth = 0, $severity = WATCHDOG_NOTICE, $tag = '') { if ($severity == WATCHDOG_WARNING && variable_get('lingotek_warning_log', self::getDefault())) { return; } else { if (strcasecmp($tag, 'api') == 0 && !variable_get('lingotek_api_debug', self::getDefault())) { return; } } $backtrace = debug_backtrace(); $location = $backtrace[$depth]['file'] . ':' . $backtrace[$depth]['line']; $function = $backtrace[$depth + 1]['function']; $args = @json_encode($backtrace[$depth + 1]['args']); $data_output = ""; if (isset($data)) { $data_output = json_encode($data); } $suffix = is_string($tag) && strlen($tag) ? ' - ' . $tag : ''; $data_array = array(); if (is_array($data)) { foreach ($data as $k => $v) { $data_array[$k] = LingotekLog::format($v); } } watchdog('lingotek' . $suffix, t($msg, $data_array) . ' <div style="word-break: break-all; padding-top: 10px; color: #666;"><b>FUNCTION:</b> %function<br /><b>ARGS:</b> %args<br /><b>FILE:</b> %location<br /><b>MESSAGE:</b> %msg <br /><b>DATA:</b> %data <br /></div>', array('%msg' => $msg, '%data' => $data_output, '%location' => $location, '%function' => $function, '%args' => $args), $severity); if (variable_get('lingotek_error_log', FALSE)) { error_log("FUNCTION: {$function} ARGS: {$args} FILE: {$location} MESSAGE: {$msg} DATA: {$data_output} "); } }
public static function log($msg, $data = NULL, $depth = 0, $severity = WATCHDOG_NOTICE, $tag = '') { $backtrace = debug_backtrace(); $location = $backtrace[$depth]['file'] . ':' . $backtrace[$depth]['line']; $function = $backtrace[$depth + 1]['function']; $args = @json_encode($backtrace[$depth + 1]['args']); $data_output = ""; if (isset($data)) { $data_output = json_encode($data); } $data_array = array(); if (is_array($data)) { foreach ($data as $k => $v) { $data_array[$k] = LingotekLog::format($v); } } watchdog('lingotek', format_string(empty($tag) ? $msg : '[' . $tag . '] ' . $msg, $data_array) . ' <div style="word-break: break-all; padding-top: 10px; color: #666;"><b>FUNCTION:</b> %function<br /><b>ARGS:</b> %args<br /><b>FILE:</b> %location<br /><b>MESSAGE:</b> %msg <br /><b>DATA:</b> %data <br /></div>', array('%msg' => $msg, '%data' => $data_output, '%location' => $location, '%function' => $function, '%args' => $args), $severity); if (variable_get('lingotek_error_log', FALSE) && $tag == 'error') { error_log("FUNCTION: {$function} ARGS: {$args} FILE: {$location} MESSAGE: {$msg} DATA: {$data_output} "); } }
/** * Updates the local content of $target_code with data from a Lingotek Document * * @param string $lingotek_locale * The code for the language that needs to be updated. * @return bool * TRUE if the content updates succeeded, FALSE otherwise. */ public function downloadTriggered($lingotek_locale) { $metadata = $this->metadata(); $document_id = $metadata['document_id']; if (empty($document_id)) { LingotekLog::error('Unable to refresh local contents for config chunk @cid. Could not find Lingotek Document ID.', array('@cid' => $this->cid)); return FALSE; } $api = LingotekApi::instance(); $document_xml = $api->downloadDocument($document_id, $lingotek_locale); $target_language = Lingotek::convertLingotek2Drupal($lingotek_locale); /* FAST VERSION (git history for slow version) */ // 1. save the dirty targets associated with given language $dirty_lids = self::getDirtyLidsByChunkIdAndLanguage($this->cid, $target_language); // 2. delete all segment targets associated with given language self::deleteSegmentTranslationsByChunkIdAndLanguage($this->cid, $target_language); // 3. insert all segments for the given language self::saveSegmentTranslations($document_xml, $target_language); // 4. return the dirty targets' statuses self::restoreDirtyLids($dirty_lids); /* END FAST */ // set chunk status to current $this->setStatus(LingotekSync::STATUS_CURRENT); $this->setTargetsStatus(LingotekSync::STATUS_CURRENT, $lingotek_locale); return TRUE; }
/** * Returns whether the given language is supported. * * @return * Boolean value. */ public static function isSupportedLanguage($drupal_language_code, $enabled = TRUE) { //($drupal_language_code != LANGUAGE_NONE) $supported = self::convertDrupal2Lingotek($drupal_language_code, $enabled) !== FALSE; if (!$supported) { LingotekLog::warning("Unsupported language detected: [@language]", array('@language' => $drupal_language_code)); } return $supported; }
public function getTitle() { if (!empty($this->title)) { return $this->title; } if (!empty($this->info['entity keys']['label']) && !empty($this->entity->{$this->info['entity keys']['label']})) { $this->title = $this->entity->{$this->info['entity keys']['label']}; } elseif ($this->entity_type == 'comment') { $this->title = $this->entity->subject; } else { LingotekLog::info('Did not find a label for @entity_type #!entity_id, using default label.', array('@entity_type' => $this->entity_type, '@entity_id' => $this->entity_id)); $this->title = $this->entity_type . " #" . $this->entity_id; } return $this->title; }
public function getTitle() { if (!empty($this->title)) { return $this->title; } try { $title_field = field_get_items($this->entity_type, $this->entity, 'title_field', $this->language); $this->title = $title_field[0]['value']; if (!empty($this->title)) { return $this->title; } } catch (Exception $e) { // Must not have values in the title field, so continue. } if (!empty($this->info['entity keys']['label']) && !empty($this->entity->{$this->info['entity keys']['label']})) { $this->title = $this->entity->{$this->info['entity keys']['label']}; } elseif ($this->entity_type == 'comment') { $this->title = $this->entity->subject; } else { LingotekLog::info('Did not find a label for @entity_type #!entity_id, using default label.', array('@entity_type' => $this->entity_type, '@entity_id' => $this->entity_id)); $this->title = $this->entity_type . " #" . $this->entity_id; } return $this->title; }
public static function getDirtyChunkLids() { // return the list of all lids from the locale_source table *not* fully translated $source_language = language_default(); if (!isset($source_language->lingotek_locale)) { $source_language->lingotek_locale = Lingotek::convertDrupal2Lingotek($source_language->language); } $lingotek_codes = Lingotek::getLanguagesWithoutSource($source_language->lingotek_locale); if (!count($lingotek_codes)) { LingotekLog::error('No languages configured for this Lingotek account.', array()); return array(); } // get the drupal language for each associated lingotek locale $drupal_codes = array(); foreach ($lingotek_codes as $lc) { $drupal_codes[] = Lingotek::convertLingotek2Drupal($lc); } // get the list of all segments that need updating // that belong to the textgroups the user wants translated $textgroups = array_merge(array(-1), LingotekConfigChunk::getTextgroupsForTranslation()); $max_length = variable_get('lingotek_config_max_source_length', LINGOTEK_CONFIG_MAX_SOURCE_LENGTH); $query = db_select('{locales_source}', 'ls'); $query->fields('ls', array('lid'))->condition('ls.source', '', '!=')->condition('ls.lid', self::getQueryCompletedConfigTranslations($drupal_codes), 'NOT IN')->where('length(ls.source) < ' . (int) $max_length); if (in_array('misc', $textgroups)) { $or = db_or(); $or->condition('ls.textgroup', $textgroups, 'IN'); $or->where("ls.textgroup NOT IN ('default','menu','taxonomy','views','blocks','field')"); $query->condition($or); } else { $query->condition('ls.textgroup', $textgroups, 'IN'); } return $query->execute()->fetchCol(); }
/** * Get Account Status * NOTE: You shouldnt need to call this directly. Its called in the constructor. * Request: https://LINGOTEK_BILLING_SERVER/billing/account.json?community=B2MMD3X5&external_id=community_admin&oauth_key=28c279fa-28dc-452e-93af-68d194a2c366&oauth_secret=0e999486-3b4d-47e4-ba9a-d0f3f0bbda73 * Response: {"state":"active","plan":{"trial_ends_at":0,"state":"active","activated_at":1355267936,"type":"cosmopolitan_monthly","languages_allowed":2,"language_cost_per_period_in_cents":14900}} * Will return FALSE or a json decoded object. */ function getAccountStatus() { $result = FALSE; $parameters = array('community' => variable_get('lingotek_community_identifier', ''), 'external_id' => variable_get('lingotek_login_id', ''), 'oauth_key' => variable_get('lingotek_oauth_consumer_id', ''), 'oauth_secret' => variable_get('lingotek_oauth_consumer_secret', '')); if (!empty($parameters['community']) && !empty($parameters['external_id']) && !empty($parameters['oauth_key']) && !empty($parameters['oauth_secret'])) { $timer_name = 'GET -' . microtime(TRUE); timer_start($timer_name); $api_url = LINGOTEK_BILLING_SERVER; $ch = curl_init($api_url . '?' . http_build_query($parameters)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); //curl_setopt( $ch, CURLINFO_HEADER_OUT, TRUE ); $response = curl_exec($ch); $info = curl_getinfo($ch); curl_close($ch); $response_json = json_decode($response); //debug( $response ); //debug( $info ); $timer_results = timer_stop($timer_name); $message_params = array('@url' => $api_url, '@method' => 'GET account (billing API)', '!params' => $parameters, '!response' => $response_json, '@response_time' => number_format($timer_results['time']) . ' ms'); if (isset($response_json) && $info['http_code'] == 200) { // Did we get valid json data back? If not, $json is NULL. //debug ( $json ); LingotekLog::info('<h1>@method</h1> <strong>API URL:</strong> @url <br /><strong>Response Time:</strong> @response_time<br /><strong>Request Params</strong>: !params<br /><strong>Response:</strong> !response', $message_params, 'api'); $response_data = $response; $result = TRUE; // Not Found - {"state":"not_found"} - Account isn't setup yet. The state after autoprovisioning a community, but before setting up your billing account. if ($response_json->state == self::NOT_FOUND) { $this->setStatus(self::NOT_FOUND); $this->setPlan(self::NONE); } elseif ($response_json->state == self::ACTIVE) { $this->setStatus(self::ACTIVE); variable_set('lingotek_account_status', self::ACTIVE); if (is_object($response_json->plan)) { $this->setPlan($response_json->plan); } // END: Plan menu_rebuild(); } // END Active } else { LingotekLog::error('<h1>@method (Failed)</h1> <strong>API URL:</strong> @url <br /><strong>Response Time:</strong> @response_time<br /><strong>Request Params</strong>: !params<br /><strong>Response:</strong> !response<br/><strong>Full Request:</strong> !request', $message_params, 'api'); } } // END: has credentials return $result; }
/** * Updates the local content with data from a Lingotek Document. * * @return bool * TRUE if the content updates succeeded, FALSE otherwise. */ public function updateLocalContent() { $success = TRUE; $metadata = $this->metadata(); if (!empty($metadata['document_id'])) { $document_id = $metadata['document_id']; $api = LingotekApi::instance(); $document = $api->getDocument($document_id); foreach ($document->translationTargets as $target) { $document_xml = $api->downloadDocument($metadata['document_id'], $target->language); $target_language = Lingotek::convertLingotek2Drupal($target->language); foreach ($document_xml as $drupal_field_name => $content) { // Figure out which subkey of the field data we're targeting. // "value" for standard text fields, or some other key for // compound text fields (text with summary, for example). $target_key = 'value'; $subfield_parts = explode('__', $drupal_field_name); if (count($subfield_parts) == 2) { $drupal_field_name = $subfield_parts[0]; $target_key = $subfield_parts[1]; } $field = field_info_field($drupal_field_name); if (!empty($field['lingotek_translatable'])) { $comment_field =& $this->comment->{$drupal_field_name}; $index = 0; foreach ($content as $text) { $comment_field[$target_language][$index][$target_key] = decode_entities(lingotek_xml_decode($text)); // Copy filter format from source language field. if (!empty($comment_field[$this->comment->language][0]['format'])) { $comment_field[$target_language][$index]['format'] = $comment_field[$this->comment->language][0]['format']; } $index++; } } } $comment_node = LingotekNode::loadById($this->comment->nid); $comment_fields = array_keys(field_info_instances('comment', 'comment_node_' . $comment_node->type)); foreach ($comment_fields as $field) { // Copy any untranslated fields from the default language into this target. if (isset($this->comment->{$field}[$this->comment->language]) && !isset($this->comment->{$field}[$target_language])) { $this->comment->{$field}[$target_language] = $this->comment->{$field}[$this->comment->language]; } // Ensure that all fields get their LANGUAGE_NONE field data populated with the // comment's default language data, to support toggling off of comment translation // at some point in the future. if (!empty($this->comment->{$field}[$this->comment->language])) { $this->comment->{$field}[LANGUAGE_NONE] = $this->comment->{$field}[$this->comment->language]; } } } // This avoids an infitinite loop when hooks resulting from comment_save() are invoked. self::$content_update_in_progress = TRUE; comment_save($this->comment); self::$content_update_in_progress = FALSE; $this->comment = comment_load($this->comment->cid); } else { LingotekLog::error('Unable to refresh local contents for comment @cid. Could not find Lingotek Document ID.', array('@cid' => $this->comment->cid)); $success = FALSE; } return $success; }
/** * Calls a Lingotek API method. * * @return mixed * On success, a stdClass object of the returned response data, FALSE on error. */ public function request($method, $parameters = array(), $request_method = 'POST', $credentials = NULL) { global $user; LingotekLog::trace('<h2>@method</h2> (trace)', array('@method' => $method)); $response_data = FALSE; // Every v4 API request needs to have the externalID parameter present. // Defaults the externalId to the lingotek_login_id, unless externalId is passed as a parameter if (!isset($parameters['externalId'])) { $parameters['externalId'] = variable_get('lingotek_login_id', ''); } module_load_include('php', 'lingotek', 'lib/oauth-php/library/OAuthStore'); module_load_include('php', 'lingotek', 'lib/oauth-php/library/OAuthRequester'); $credentials = is_null($credentials) ? array('consumer_key' => variable_get('lingotek_oauth_consumer_id', ''), 'consumer_secret' => variable_get('lingotek_oauth_consumer_secret', '')) : $credentials; $timer_name = $method . '-' . microtime(TRUE); timer_start($timer_name); $response = NULL; try { OAuthStore::instance('2Leg', $credentials); $api_url = $this->api_url . '/' . $method; $request = @new OAuthRequester($api_url, $request_method, $parameters); // There is an error right here. The new OAuthRequester throws it, because it barfs on $parameters // The error: Warning: rawurlencode() expects parameter 1 to be string, array given in OAuthRequest->urlencode() (line 619 of .../modules/lingotek/lib/oauth-php/library/OAuthRequest.php). // The thing is, if you encode the params, they just get translated back to an array by the object. They have some type of error internal to the object code that is handling things wrong. // I couldn't find a way to get around this without changing the library. For now, I am just supressing the warning w/ and @ sign. $result = $request->doRequest(0, array(CURLOPT_SSL_VERIFYPEER => FALSE)); $response = $method == 'downloadDocument' ? $result['body'] : json_decode($result['body']); } catch (OAuthException2 $e) { LingotekLog::error('Failed OAuth request. <br />API URL: @url <br />Message: @message. <br />Method: @name. <br />Parameters: !params. <br />Response: !response', array('@url' => $api_url, '@message' => $e->getMessage(), '@name' => $method, '!params' => $parameters, '!response' => $response), 'api'); } $timer_results = timer_stop($timer_name); $message_params = array('@url' => $api_url, '@method' => $method, '!params' => $parameters, '!request' => $request, '!response' => $method == 'downloadDocument' ? 'Zipped Lingotek Document Data' : $response, '@response_time' => number_format($timer_results['time']) . ' ms'); /* Exceptions: downloadDocument - Returns misc data (no $response->results), and should always be sent back. assignProjectManager - Returns fails/falses if the person is already a community manager (which should be ignored) */ if ($method == 'downloadDocument' || $method == 'assignProjectManager' || !is_null($response) && $response->results == self::RESPONSE_STATUS_SUCCESS) { LingotekLog::info('<h1>@method</h1> <strong>API URL:</strong> @url <br /><strong>Response Time:</strong> @response_time<br /><strong>Request Params</strong>: !params<br /><strong>Response:</strong> !response<br/><strong>Full Request:</strong> !request', $message_params, 'api'); $response_data = $response; } else { LingotekLog::error('<h1>@method (Failed)</h1> <strong>API URL:</strong> @url <br /><strong>Response Time:</strong> @response_time<br /><strong>Request Params</strong>: !params<br /><strong>Response:</strong> !response<br/><strong>Full Request:</strong> !request', $message_params, 'api'); } return $response_data; }