Ejemplo n.º 1
0
 function handle($params)
 {
     if (!defined('DISABLE_reCAPTCHA')) {
         define('DISABLE_reCAPTCHA', 1);
     }
     import('Dataface/QuickForm.php');
     Dataface_QuickForm::$TRACK_SUBMIT = false;
     $app = Dataface_Application::getInstance();
     $query = $app->getQuery();
     $errors = null;
     try {
         if (!@$_POST['-table']) {
             throw new Exception("No table specified");
         }
         $table = $_POST['-table'];
         $rec = new Dataface_Record($table, array());
         $tableObj = $rec->_table;
         $fields = array();
         if (!$rec->checkPermission('new')) {
             throw new Exception("Failed to insert record.  Permission denied");
         }
         foreach ($_POST as $k => $v) {
             if ($k[0] == '-') {
                 continue;
             }
             $fields[] = $k;
             $rec->setValue($k, $v);
             if (!$rec->checkPermission('new', array('field' => $k))) {
                 throw new Exception(sprintf("Failed to insert record because you do not have permission to insert data into the %s column", $k));
             }
         }
         $form = df_create_new_record_form($table, $fields);
         $form->_flagSubmitted = true;
         $res = $form->validate();
         if (!$res) {
             $errors = $form->_errors;
             throw new Exception('Validation error', REST_INSERT_VALIDATION_ERROR);
         }
         $res = $rec->save(null, true);
         if (PEAR::isError($res)) {
             throw new Exception("Failed to insert record due to a server error: " . $res->getMessage(), 500);
         }
         $out = array();
         $vals = $rec->strvals();
         foreach ($vals as $k => $v) {
             if ($rec->checkPermission('view')) {
                 $out[$k] = $v;
             }
         }
         $this->out(array('code' => 200, 'message' => 'Record successfully inserted', 'record' => $out));
         exit;
     } catch (Exception $ex) {
         $this->out(array('code' => $ex->getCode(), 'message' => $ex->getMessage(), 'errors' => $errors));
         exit;
     }
 }
Ejemplo n.º 2
0
 function field__properties($record)
 {
     $p = df_get_record('webpage_properties', array('webpage_id' => '=' . $record->val('webpage_id')));
     if (!$p) {
         $p = new Dataface_Record('webpage_properties', array());
         $p->setValue('webpage_id', $record->val('webpage_id'));
         $p->pouch['webpage'] = $record;
         $p->save();
     }
     return $p;
 }
Ejemplo n.º 3
0
 function addExistingRelatedRecord(&$relatedRecord)
 {
     $record =& $relatedRecord->_record;
     $relationshipName =& $relatedRecord->_relationshipName;
     $values = $relatedRecord->getAbsoluteValues(true);
     if (!is_a($record, 'Dataface_Record')) {
         throw new Exception("In Dataface_QueryBuilder::addExistingRelatedRecord() expected first argument to be of type 'Dataface_Record' but received '" . get_class($record) . "'.\n<br>", E_USER_ERROR);
     }
     if (!is_array($values)) {
         throw new Exception("In Dataface_QueryBuilder::addExistingRelatedRecord() expected third argument to be an array but received a scalar.", E_USER_ERROR);
     }
     $relationship =& $record->_table->getRelationship($relationshipName);
     $foreignKeys = $relationship->getForeignKeyValues();
     $foreignKeys_withValues = $relatedRecord->getForeignKeyValues();
     if (count($this->errors) > 0) {
         $error = array_pop($this->errors);
         $error->addUserInfo("Error getting foreign key values for relationship '{$relationship_name}'");
         throw new Exception($error->toString());
     }
     $sql = array();
     foreach ($foreignKeys as $table => $cols) {
         $skip = true;
         foreach ($cols as $field_name => $field_value) {
             if ($field_value != "__" . $table . "__auto_increment__") {
                 $skip = false;
                 break;
             }
         }
         if ($skip) {
             continue;
         }
         $cols = $foreignKeys_withValues[$table];
         if (isset($recordObj)) {
             unset($recordObj);
         }
         $recordObj = new Dataface_Record($table, $cols);
         $recordVals =& $recordObj->vals();
         if (isset($recordVals[$recordObj->_table->getAutoIncrementField()])) {
             // We don't want the auto-increment field to be inserted - though it may
             // have a placeholder value.
             $recordObj->setValue($recordObj->_table->getAutoIncrementField(), null);
         }
         $qb = new Dataface_QueryBuilder($table);
         $sql[$table] = $qb->insert($recordObj);
         /*
         $skip = true;
         	// indicator to say whether or not to skip this table
         	// we skip the table if it contains an unresolved autoincrement value
         	
         foreach ($cols as $field_name=>$field_value){
         	if ( $field_value != "__".$table."__auto_increment__" ) {
         		$skip = false;
         		break;
         	}
         }
         
         if ( $skip == true ) continue;
         	
         
         $cols = $foreignKeys_withValues[$table];
         
         
         $query = "INSERT INTO `$table`";
         $colnames = "";
         $colvals = "";
         
         foreach ( $cols as $colname=>$colval){
         	$colnames .= $colname.',';
         	$colvals .= "'".addslashes($colval)."',";
         }
         
         $colnames = substr($colnames, 0, strlen($colnames)-1);
         $colvals = substr($colvals, 0, strlen($colvals)-1);
         
         $query .= " ($colnames) VALUES ($colvals)";
         
         $sql[$table] = $query;
         */
     }
     return $sql;
 }
Ejemplo n.º 4
0
 /**
  * Returns a join record for the give table.  A join record is one that contains
  * auxiliary data for the current record.  It is specified by the [__join__]
  * section of the fields.ini file or the __join__() method of the delegate
  * class.  It is much like a one-to-one relationship.  The key difference
  * between a join record and a related record is that a join record 
  * is assumed to be one-to-one, and an extra tab is added to the edit form 
  * to edit a join record.
  *
  * @param string $tablename The name of the table from which the join record
  * 				should be drawn.
  * @param boolean $nullIfNotFound If set, then this will return null if no join 
  *		record yet exists in the database.  Added in Xataface 2.0
  *
  * @returns Dataface_Record Join record from the specified join table or 
  * 			a new record with the correct primary key values if none exists.
  *
  * @returns PEAR_Error If the specified table in incompatible.
  *
  */
 function getJoinRecord($tablename, $nullIfNotFound = false)
 {
     $table =& Dataface_Table::loadTable($tablename);
     $query = $this->getJoinKeys($tablename);
     foreach ($query as $key => $val) {
         $query[$key] = '=' . $val;
     }
     $record = df_get_record($tablename, $query);
     if (!$record) {
         if ($nullIfNotFound) {
             return null;
         }
         // No record was found, so we create a new one.
         $record = new Dataface_Record($tablename, array());
         foreach ($query as $key => $value) {
             $record->setValue($key, substr($value, 1));
         }
     }
     return $record;
 }
Ejemplo n.º 5
0
 function writeConfigToDB()
 {
     import('Dataface/Table.php');
     import('Dataface/Record.php');
     import('Dataface/IO.php');
     if (!is_a($this, 'Dataface_ConfigTool')) {
         throw new Exception('ConfigWriter methods are only to be used via the Dataface_ConfigTool class.', E_USER_ERROR);
     }
     $this->loadAllConfig();
     $app =& Dataface_Application::getInstance();
     // first let's make copies of the current configuration.
     $timestamp = time();
     foreach ($this->configTypes as $type) {
         $res = xf_db_query("CREATE TABLE `__" . addslashes($type) . "__" . $timestamp . "` SELECT * FROM `__" . addslashes($type) . "__`", $app->db());
         if (!$res) {
             throw new Exception("Failed to make backup of table '__" . $type . "__'." . xf_db_error($app->db()), E_USER_ERROR);
         }
     }
     $res = xf_db_query("CREATE TABLE `__properties__" . $timestamp . "` SELECT * FROM `__properties__`", $app->db());
     if (!$res) {
         throw new Exception("Failed to make backup of table '__properties__'.", $app->db());
     }
     // Now that we have made our backups, we can continue to write the configuration to the database.
     //print_r($this->config);
     foreach ($this->configTypes as $type) {
         $res = xf_db_query("DELETE FROM `__" . addslashes($type) . "__`", $app->db());
         if (!$res) {
             throw new Exception("Failed to delete all records from table '__" . $type . "__'", $app->db());
         }
         foreach ($this->config[$type] as $tablename => $tableConfig) {
             foreach ($tableConfig as $sectionname => $section) {
                 $tableObj =& Dataface_Table::loadTable('__' . $type . '__');
                 $record = new Dataface_Record('__' . $type . '__', array());
                 $record->useMetaData = false;
                 // some of the field names begin with '__' which would conflict with dataface's handling of MetaData fields.
                 foreach (array_keys($tableObj->fields()) as $fieldname) {
                     $record->setValue($fieldname, @$section[$fieldname]);
                     unset($section[$fieldname]);
                 }
                 $record->setValue('name', $sectionname);
                 $record->setValue('table', $tablename);
                 //echo nl2br("Section name: $sectionname\nTable: $tablename\n");
                 //print_r($record->strvals());
                 echo nl2br("\nWriting section: {$sectionname} : ");
                 print_r($record->strvals());
                 // now that we have created the record, we write the record
                 $io = new Dataface_IO('__' . $type . '__');
                 $res = $io->write($record);
                 if (PEAR::isError($res)) {
                     throw new Exception($res->toString(), E_USER_ERROR);
                 } else {
                     if (!$res) {
                         throw new Exception("Failure to write to database for unknown reason.", E_USER_ERROR);
                     }
                 }
                 // now for the rest of the properties.
                 foreach ($section as $propertyName => $propertyValue) {
                     $res = xf_db_query("\n\t\t\t\t\t\t\tINSERT INTO \n\t\t\t\t\t\t\t `__properties__` \n\t\t\t\t\t\t\t (`parent_id`,`parent_type`,`property_name`,`property_value`)\n\t\t\t\t\t\t\tVALUES\n\t\t\t\t\t\t\t ('" . $record->val($type . '_id') . "', \n\t\t\t\t\t\t\t '" . addslashes($type) . "',\n\t\t\t\t\t\t\t '" . addslashes($propertyName) . "',\n\t\t\t\t\t\t\t '" . addslashes($propertyValue) . "')", $app->db());
                     if (!$res) {
                         throw new Exception("Failed to add property '{$propertyName}' to table '__properties__' with value '{$propertyValue}'" . xf_db_error($app->db()), E_USER_ERROR);
                     }
                 }
                 unset($tableObj);
                 unset($record);
                 unset($io);
             }
         }
     }
 }
Ejemplo n.º 6
0
 /**
  * Links (ie: URLs) can be associated with fields of a table by defining a "link"
  * property for a field in the fields.ini file or by defining a fieldname__link()
  * method in the delegate class.  These links are accessible via the Table::getLink()
  * method which resolves any variables in the link provided and returns the link
  * in the same format as it is defined in its place of origin (either the fields.ini file
  * or the delegate class.
  *
  * Links can be in the form of a query array, or in the form of a string (which should
  * be a url).
  * In this test, `fname`, `lname`, and `description` fields have links defined in the 
  * Profiles delegate class.  
  */
 function test_links()
 {
     $profiles = new Dataface_Record('Profiles', array());
     // Part I:  Testing links produced by the delegate *__link() methods.
     //--------------------------------------------------------------------
     // First test a link with explicit values where the delegate method __link() is defined
     // and the delegate method explicitly returns an array.
     $profiles->setValues(array("fname" => "John", "lname" => "Thomas"));
     $link = $profiles->getLink("fname");
     $this->assertEquals($link["fname"], "John");
     $this->assertEquals($link["lname"], "Thomas");
     $this->assertEquals($link["description"], "My name is John");
     // Try the same thing where no link is defined
     $link = $profiles->getLink("id");
     $this->assertEquals($link, null);
     // Now test a link with implicit values where the delegate method __link() is defined
     // and the delegate method returns an array.
     $table = new Dataface_Record('Profiles', array());
     $table->clearValues();
     $table->setValues(array("fname" => "John", "lname" => "Thomas"));
     $link = $profiles->getLink("fname");
     $this->assertEquals($link["fname"], "John");
     $this->assertEquals($link["lname"], "Thomas");
     $this->assertEquals($link["description"], "My name is John");
     // Try same thing when no link is defined
     $link = $profiles->getLink("id");
     $this->assertEquals($link, null);
     //Now test the link returned by a field that returns the link as a string with no
     // variables that need parsing.
     $link = $profiles->getLink("lname");
     $this->assertEquals("http://www.google.ca?fname=John&lname=Thomas", $link);
     // Now test the link returned by a field that returns a link that contains
     // variables (which should automatically be resolved by the getLink() method.
     // This tests the delegate still.
     $link = $profiles->getLink("description");
     $this->assertEquals("http://www.google.ca?fname=John&lname=Thomas", $link);
     // Part II: Testing links defined in the fields.ini file
     //-------------------------------------------------------------------------
     // Test a link with no variables requiring resolving
     $link = $profiles->getLink("dob");
     $this->assertEquals("http://www.google.ca", $link);
     // Test a link with variables that need to be resolved.
     $link = $profiles->getLink("phone1");
     $this->assertEquals("http://www.google.ca?fname=John", $link);
     $profiles->clearValues();
     $profiles->setValue("fname", "Thomas");
     $link = $profiles->getLink("phone1");
     $this->assertEquals("http://www.google.ca?fname=Thomas", $link);
 }
Ejemplo n.º 7
0
 public function process()
 {
     $this->translationStats = null;
     $this->translationMissLogRecord = null;
     $this->translatedPage = null;
     $proxyWriter = $this->site->getProxyWriter();
     $pageWrapper = $this->page;
     $page = $pageWrapper->getRecord();
     $tmid = null;
     if (!isset($this->translationMemory)) {
         $tmid = $pageWrapper->getTranslationMemoryId(true);
     } else {
         $tmid = $this->translationMemory->getRecord()->val('translation_memory_id');
     }
     $translatedContent = null;
     $untranslatedContent = $page->val('webpage_content');
     if (!trim($untranslatedContent)) {
         // There is nothing to process on this page.
         return;
     }
     if ($tmid or $this->translationMemory) {
         if ($this->translationMemory) {
             $tm = $this->translationMemory;
         } else {
             $tm = $this->getTranslationMemory($tmid);
         }
         if ($tm) {
             if ($tm->getSourceLanguage() != $pageWrapper->getLanguage()) {
                 throw new Exception("Translation memory language does not match the record language.  Translation memory source language is " . $tm->getSourceLanguage() . " but the page language is " . $pageWrapper->getLanguage() . '.');
             }
             $proxyWriter->setTranslationMemory($tm);
             $proxyWriter->setMinTranslationStatus($this->translateMinStatus);
             $translatedContent = $proxyWriter->translateHtml($untranslatedContent, $translationStats, $this->logTranslationMisses);
             $this->translationStats = $translationStats;
             $page->setValues(array('last_translation_memory_applied' => date('Y-m-d H:i:s'), 'last_translation_memory_misses' => $translationStats['misses'], 'last_translation_memory_hits' => $translationStats['matches']));
             // Let's record the strings in this page.
             $res = df_q("delete from webpage_strings where webpage_id='" . addslashes($page->val('webpage_id')) . "'");
             if ($proxyWriter->lastStrings) {
                 //print_r($proxyWriter->lastStrings);exit;
                 $sqlpre = "insert into webpage_strings (webpage_id,string_id) values ";
                 $sql = array();
                 $wpid = $page->val('webpage_id');
                 foreach ($proxyWriter->lastStrings as $str) {
                     if (!trim($str)) {
                         continue;
                     }
                     if (preg_match('/^[^\\w]+$/', trim($str))) {
                         // This is to skip any strings that contain only
                         // non-word characters(e.g. numbers)
                         continue;
                     }
                     $encStr = TMTools::encode($str, $params);
                     $strRec = XFTranslationMemory::addString($encStr, $tm->getSourceLanguage());
                     $sql[] = '(' . $wpid . ',' . $strRec->val('string_id') . ')';
                 }
                 $sql = $sqlpre . implode(',', $sql);
                 df_q($sql);
             }
             $translatedPage = SweteWebpage::loadById($page->val('webpage_id'), $this->site->getDestinationLanguage());
             $translatedPage->getRecord()->setValue('webpage_content', $translatedContent);
             $res = $translatedPage->getRecord()->save();
             if (PEAR::isError($res)) {
                 throw new Exception(mysql_error(df_db()));
             }
             $lastApproved = $translatedPage->getLastVersionWithStatus(SweteWebpage::STATUS_APPROVED);
             if ($lastApproved and $lastApproved->val('webpage_content') == $translatedContent) {
                 $page->setValue('webpage_status', SweteWebpage::STATUS_APPROVED);
             } else {
                 if ($translationStats['matches'] > 0 and $translationStats['misses'] == 0) {
                     // We have perfect matches in what we are supposed to be translating
                     // We are either approving this page or we are marking it pending approval
                     if ($translatedPage->getAutoApprove(true)) {
                         $page->setValue('webpage_status', SweteWebpage::STATUS_APPROVED);
                         $lastApproved = $translatedPage->setStatus(SweteWebpage::STATUS_APPROVED);
                     } else {
                         $page->setValue('webpage_status', SweteWebpage::STATUS_PENDING_APPROVAL);
                     }
                 } else {
                     if ($translationStats['misses'] > 0) {
                         $page->setValue('webpage_status', SweteWebpage::STATUS_CHANGED);
                     } else {
                         $page->setValue('webpage_status', null);
                     }
                 }
             }
             if ($this->logTranslationMisses and @$translationStats['log']) {
                 //print_r($translationStats);exit;
                 foreach ($translationStats['log'] as $str) {
                     $tlogEntry = new Dataface_Record('translation_miss_log', array());
                     $nstr = TMTools::normalize($str);
                     $estr = TMTools::encode($str, $junk);
                     $hstr = md5($estr);
                     $strRec = XFTranslationMemory::findString($estr, $this->site->getSourceLanguage());
                     if (!$strRec) {
                         $strRec = XFTranslationMemory::addString($estr, $this->site->getSourceLanguage());
                     }
                     $tlogEntry->setValues(array('string' => $str, 'normalized_string' => $nstr, 'encoded_string' => $estr, 'string_hash' => $hstr, 'date_inserted' => date('Y-m-d H:i:s'), 'webpage_id' => $page->val('webpage_id'), 'website_id' => $page->val('website_id'), 'source_language' => $this->site->getSourceLanguage(), 'destination_language' => $this->site->getDestinationLanguage(), 'translation_memory_id' => $tmid, 'string_id' => $strRec->val("string_id")));
                     if (isset($this->webpageRefreshLogId)) {
                         $tlogEntry->setValue('webpage_refresh_log_id', $this->webpageRefreshLogId);
                     }
                     if ($this->saveTranslationLogRecord) {
                         $res = $tlogEntry->save();
                         if (PEAR::isError($res)) {
                             //throw new Exception($res->getMessage());
                             // This will throw an error if there is a duplicate... we don't care... we're not interested in duplicates
                         }
                     }
                     $this->translationMissLogRecord = $tlogEntry;
                 }
             }
             if ($this->savePage) {
                 $res = $page->save();
                 if (PEAR::isError($res)) {
                     throw new Exception($res->getMessage());
                 }
             }
         }
     }
 }
Ejemplo n.º 8
0
 function test_add_existing_related_record_sql()
 {
     $s = new Dataface_Record('Profiles');
     $builder = new Dataface_QueryBuilder('Profiles');
     $existingRecord = new Dataface_RelatedRecord($s, 'addresses');
     $s->setValue('id', 15);
     $res = $builder->addExistingRelatedRecord($existingRecord);
     if (PEAR::isError($res)) {
         echo $res->toString();
     } else {
         //print_r($res);
     }
     $this->assertEquals(array('Addresses' => "INSERT INTO `Addresses` (`profileid`) VALUES ('15')"), $res);
     $existingCourse = new Dataface_RelatedRecord($s, 'courses', array('id' => 3));
     $res = $builder->addExistingRelatedRecord($existingCourse);
     if (PEAR::isError($res)) {
         echo $res->toString();
     } else {
         //print_r($res);
     }
     $this->assertEquals(array('Student_Courses' => "INSERT INTO `Student_Courses` (`studentid`,`courseid`) VALUES ('15','3')"), $res);
 }
Ejemplo n.º 9
0
 function test_foreign_key_values()
 {
     $s = new Dataface_Record('Profiles', array());
     $courses =& $this->table1->getRelationship('courses');
     $s->setValue('id', 15);
     $vals = $courses->getForeignKeyValues(null, null, $s);
     $this->assertEquals(array("Courses" => array("id" => "__Courses__auto_increment__"), "Student_Courses" => array("courseid" => "__Courses__auto_increment__", "studentid" => "15")), $vals);
     $vals = $courses->getForeignKeyValues(null, null);
     $this->assertEquals(array("Courses" => array("id" => "__Courses__auto_increment__"), "Student_Courses" => array("courseid" => "__Courses__auto_increment__", "studentid" => "\$id")), $vals);
     $vals = $courses->getForeignKeyValues(array('Courses.id' => 2), null, $s);
     $this->assertEquals(array("Courses" => array("id" => 2), "Student_Courses" => array("courseid" => 2, "studentid" => "15")), $vals);
 }
Ejemplo n.º 10
0
 /**
  * Compiles the job inputs into its final form so that it can be worked on.  Before
  * this step the job just has a loose set of input webpages strings and translation
  * misses.  This will grab all of the resources that it needs to be able to 
  * present the job to a translator.  This includes loading all resources for all
  * pages used into the data structure so that the job doesn't depend on outside
  * factors.
  */
 public function compile()
 {
     require_once 'inc/SweteJobPageSucker.php';
     try {
         $res = SweteDb::q("select tml.webpage_id, tml.translation_miss_log_id, tml.string\n\t\t\t\tfrom \n\t\t\t\t\ttranslation_miss_log tml \n\t\t\t\t\tinner join job_inputs_translation_misses jitm on jitm.translation_miss_log_id=tml.translation_miss_log_id\n\t\t\t\t\twhere jitm.job_id='" . addslashes($this->_rec->val('job_id')) . "' and\n\t\t\t\t\ttml.webpage_id is not null");
         $missedWebpageIds = array();
         while ($row = mysql_fetch_assoc($res)) {
             $missedWebpageIds[$row['webpage_id']][] = $row;
         }
         @mysql_free_result($res);
         // 1. Get all of the webpages
         $res = SweteDb::q("select webpage_id from job_inputs_webpages where job_id='" . addslashes($this->_rec->val('job_id')) . "'");
         $wpids = array();
         while ($row = mysql_fetch_row($res)) {
             $wpids[] = $row[0];
         }
         $site = $this->getSite();
         $proxyWriter = $site->getProxyWriter();
         $jobWordCount = 0;
         @mysql_free_result($res);
         foreach ($wpids as $webpageId) {
             $webpage = SweteWebpage::loadById($webpageId, $this->_rec->val('source_language'));
             if (!$webpage) {
                 throw new Exception("Could not find webpage with id {$webpageId}");
             }
             $webpage->setSite($site);
             // Use a page sucker to suck all of the resources used by this webpage.
             $pageSucker = new SweteJobPageSucker($this);
             $pageContent = $webpage->getRecord()->val('webpage_content');
             $pageUrl = $site->getSiteUrl() . $webpage->getRecord()->val('webpage_url');
             $pageContent = $pageSucker->processHtml($pageContent, $pageUrl);
             $translatable = new Dataface_Record('job_translatable', array());
             $translatable->setValues(array('job_id' => $this->_rec->val('job_id'), 'content_type' => $webpage->getRecord()->val('last_checked_content_type'), 'full_contents' => $pageContent->save(), 'webpage_id' => $webpageId, 'source_url' => $pageUrl));
             //strings from static sites
             $strings = array();
             $res = SweteDb::q("select `string` from job_inputs_webpages_strings where job_id='" . addslashes($this->_rec->val('job_id')) . "' and webpage_id='" . addslashes($webpageId) . "'");
             while ($row = mysql_fetch_row($res)) {
                 $strings[] = $row[0];
             }
             @mysql_free_result($res);
             // Lets see if there are any other strings that were added individually to this page.
             if (isset($missedWebpageIds[$webpageId])) {
                 foreach ($missedWebpageIds[$webpageId] as $row) {
                     $strings[] = $row['string'];
                 }
                 unset($missedWebpageIds[$webpageId]);
             }
             // We need to collapse duplicate strings
             $uniqueStringIndex = array();
             $uniqueStrings = array();
             foreach ($strings as $k => $str) {
                 $nstr = TMTools::normalize($str);
                 $estr = TMTools::encode($nstr, $temp);
                 if (!isset($uniqueStringIndex[$estr])) {
                     $uniqueStrings[] = $str;
                     $uniqueStringIndex[$estr] = 1;
                 }
             }
             $strings = $uniqueStrings;
             $translatable->setValue('translatable_contents', '<div>' . implode('</div><div>', $strings) . '</div>');
             //set the word count
             $pageWordCount = self::getPageWordCount($strings);
             $jobWordCount += $pageWordCount;
             $translatable->setValue('word_count', $pageWordCount);
             // Now we need to get the previous translations
             $tmid = $webpage->getTranslationMemoryId(true);
             $tm = XFTranslationMemory::loadTranslationMemoryById($tmid);
             if (!$tm) {
                 throw new Exception("Could not find translation memory with id {$tmid}");
             }
             $dict = $this->extractDictionaryFromHtml($tm, $webpage->getRecord()->val('webpage_content'));
             $translatable->setValue('previous_translations', serialize($dict));
             $res = $translatable->save();
             if (PEAR::isError($res)) {
                 throw new Exception($res->getMessage(), $res->getCode());
             }
         }
         // Add the remainder of the missed webpages.
         foreach ($missedWebpageIds as $webpageId => $strings) {
             $webpage = SweteWebpage::loadById($webpageId, $this->_rec->val('source_language'));
             if (!$webpage) {
                 throw new Exception("Could not find webpage with id {$webpageId}");
             }
             $webpage->setSite($site);
             // Use a page sucker to suck all of the resources used by this webpage.
             $pageSucker = new SweteJobPageSucker($this);
             $pageContent = $webpage->getRecord()->val('webpage_content');
             $pageUrl = $site->getSiteUrl() . $webpage->getRecord()->val('webpage_url');
             $pageContent = $pageSucker->processHtml($pageContent, $pageUrl);
             $translatable = new Dataface_Record('job_translatable', array());
             $translatable->setValues(array('job_id' => $this->_rec->val('job_id'), 'content_type' => $webpage->getRecord()->val('last_checked_content_type'), 'full_contents' => $pageContent->save(), 'webpage_id' => $webpageId, 'source_url' => $pageUrl));
             // We need to collapse duplicate strings
             $uniqueStringIndex = array();
             $uniqueStrings = array();
             foreach ($strings as $k => $missedstr) {
                 $str = $missedstr['string'];
                 $nstr = TMTools::normalize($str);
                 $estr = TMTools::normalize(TMTools::encode($nstr, $temp));
                 if (!isset($uniqueStringIndex[$estr])) {
                     $uniqueStrings[] = $str;
                     $uniqueStringIndex[$estr] = 1;
                 }
             }
             $strings = $uniqueStrings;
             $translatable->setValue('translatable_contents', '<div>' . implode('</div><div>', $strings) . '</div>');
             //set the word count
             $pageWordCount = self::getPageWordCount($strings);
             //strings
             $jobWordCount += $pageWordCount;
             $translatable->setValue('word_count', $pageWordCount);
             // Now we need to get the previous translations
             $tmid = $webpage->getTranslationMemoryId(true);
             $tm = XFTranslationMemory::loadTranslationMemoryById($tmid);
             if (!$tm) {
                 throw new Exception("Could not find translation memory with id {$tmid}");
             }
             $dict = $this->extractDictionaryFromHtml($tm, $webpage->getRecord()->val('webpage_content'));
             $translatable->setValue('previous_translations', serialize($dict));
             $res = $translatable->save();
             if (PEAR::isError($res)) {
                 throw new Exception($res->getMessage(), $res->getCode());
             }
         }
         // 2. Get all of the http requests without associated webpages.
         $res = SweteDb::q("select htl.http_request_log_id, tml.translation_miss_log_id, tml.string, htl.translation_memory_id\n\t\t\t\tfrom \n\t\t\t\t\ttranslation_miss_log tml \n\t\t\t\t\tinner join http_request_log htl on tml.http_request_log_id=htl.http_request_log_id \n\t\t\t\t\tinner join job_inputs_translation_misses jitm on jitm.translation_miss_log_id=tml.translation_miss_log_id\n\t\t\t\t\twhere jitm.job_id='" . addslashes($this->_rec->val('job_id')) . "'");
         $hrids = array();
         while ($row = mysql_fetch_assoc($res)) {
             $hrids[$row['http_request_log_id']][] = $row;
         }
         //$site = $this->getSite();
         //$proxyWriter = $site->getProxyWriter();
         @mysql_free_result($res);
         foreach ($hrids as $hrid => $tmlids) {
             $hrRecord = df_get_record('http_request_log', array('http_request_log_id' => '=' . $hrid));
             if (!$hrRecord) {
                 $ex = new Exception("Cannot add HTTP request to job because it could not be found");
                 $ex->http_request_log_id = $hrid;
                 throw $ex;
             }
             // Use a page sucker to suck all of the resources used by this webpage.
             $pageSucker = new SweteJobPageSucker($this);
             $pageContent = $hrRecord->val('response_body');
             $pageUrl = $hrRecord->val('proxy_request_url');
             if (!$pageUrl) {
                 $ex = new Exception("Failed to add HTTP request to job because it did not have an associated proxy_request_url.");
                 $ex->http_request_log = $hrid;
                 throw $ex;
             }
             $pageUrl = $proxyWriter->unproxifyUrl($pageUrl);
             $pageContent = $pageSucker->processHtml($pageContent, $pageUrl)->save();
             $translatable = new Dataface_Record('job_translatable', array());
             $translatable->setValues(array('job_id' => $this->_rec->val('job_id'), 'content_type' => 'text/html', 'full_contents' => $pageContent, 'webpage_id' => null, 'source_url' => $hrRecord->val('request_url')));
             $tmid = null;
             $strings = array();
             foreach ($tmlids as $tmlid) {
                 $strings[] = $tmlid['string'];
                 $tmid = $tmlid['translation_memory_id'];
             }
             $translatable->setValue('translatable_contents', '<div>' . implode('</div><div>', $strings) . '</div>');
             //set the word count
             $pageWordCount = self::getPageWordCount($strings);
             $jobWordCount += $pageWordCount;
             $translatable->setValue('word_count', $pageWordCount);
             // Now we need to get the previous translations
             //$tmid = $webpage->getTranslationMemoryId(true);
             $tm = XFTranslationMemory::loadTranslationMemoryById($tmid);
             if (!$tm) {
                 throw new Exception("Could not find translation memory with id {$tmid}");
             }
             $dict = $this->extractDictionaryFromHtml($tm, $pageContent);
             $translatable->setValue('previous_translations', serialize($dict));
             $res = $translatable->save();
             if (PEAR::isError($res)) {
                 throw new Exception($res->getMessage(), $res->getCode());
             }
         }
         if ($jobWordCount == 0) {
             throw new Exception("The job has no translatable content.");
         }
         $this->getRecord()->setValue('word_count', $jobWordCount);
         $this->getRecord()->setValue('compiled', 1);
         $res = $this->getRecord()->save();
         if (PEAR::isError($res)) {
             throw new Exception($res->getMessage());
         }
         SweteDb::q("commit");
     } catch (Exception $ex) {
         SweteDb::q("rollback");
         throw $ex;
     }
 }