function delete() { // cascading delete $query = $this->_db->getQuery(true); $ret = true; // joaktree_person_events if ($ret) { $table = 'joaktree_person_events'; //$query->clear(); $query->delete(' #__joaktree_person_events '); $query->where(' app_id = ' . $this->app_id . ' '); $query->where(' person_id = ' . $this->_db->quote($this->id) . ' '); $this->_db->setQuery($query); $ret = $this->_db->query(); } // joaktree_person_names if ($ret) { $table = 'joaktree_person_names'; $query->clear(); $query->delete(' #__joaktree_person_names '); $query->where(' app_id = ' . $this->app_id . ' '); $query->where(' person_id = ' . $this->_db->quote($this->id) . ' '); $this->_db->setQuery($query); $ret = $this->_db->query(); } // joaktree_person_notes if ($ret) { $table = 'joaktree_person_notes'; $query->clear(); $query->delete(' #__joaktree_person_notes '); $query->where(' app_id = ' . $this->app_id . ' '); $query->where(' person_id = ' . $this->_db->quote($this->id) . ' '); $this->_db->setQuery($query); $ret = $this->_db->query(); } // joaktree_person_documents + joaktree_documents if ($ret) { $table = 'joaktree_person_document'; $query->clear(); $query->delete(' #__joaktree_person_documents '); $query->where(' app_id = ' . $this->app_id . ' '); $query->where(' person_id = ' . $this->_db->quote($this->id) . ' '); $this->_db->setQuery($query); $ret = $this->_db->query(); } if ($ret) { $table = 'joaktree_documents'; $query->clear(); $query->delete(' #__joaktree_documents '); $query->where(' app_id = ' . $this->app_id . ' '); $query->where(' NOT EXISTS ( ' . ' SELECT 1 ' . ' FROM #__joaktree_person_documents jpd ' . ' WHERE jpd.app_id = app_id ' . ' AND jpd.document_id = id ' . ' ) '); $this->_db->setQuery($query); $ret = $this->_db->query(); } // joaktree_relations if ($ret) { $table = 'joaktree_relations'; $query->clear(); // First select which relations exists (one direction) $query->select(' person_id_1 '); $query->from(' #__joaktree_relations '); $query->where(' app_id = ' . $this->app_id . ' '); $query->where(' person_id_2 = ' . $this->_db->quote($this->id) . ' '); $this->_db->setQuery($query); $relations = $this->_db->loadColumn(); $query->clear(); // Second select which relations exists (second direction) $query->select(' person_id_2 '); $query->from(' #__joaktree_relations '); $query->where(' app_id = ' . $this->app_id . ' '); $query->where(' person_id_1 = ' . $this->_db->quote($this->id) . ' '); $this->_db->setQuery($query); $tmp = $this->_db->loadColumn(); $relations = array_merge($relations, $tmp); $query->clear(); // now we start deleting ... $query->delete(' #__joaktree_relations '); $query->where(' app_id = ' . $this->app_id . ' '); $query->where(' ( person_id_1 = ' . $this->_db->quote($this->id) . ' ' . ' OR person_id_2 = ' . $this->_db->quote($this->id) . ' ' . ' ) '); $this->_db->setQuery($query); $ret = $this->_db->query(); // Finally, we reset the relation indicators for the remaining relations if ($ret) { $table = 'joaktree_persons (relationIndicators)'; $ret = jt_relations::setRelationIndicators($this->app_id, $relations); } } // joaktree_relation_events if ($ret) { $table = 'joaktree_relation_events'; $query->clear(); $query->delete(' #__joaktree_relation_events '); $query->where(' app_id = ' . $this->app_id . ' '); $query->where(' ( person_id_1 = ' . $this->_db->quote($this->id) . ' ' . ' OR person_id_2 = ' . $this->_db->quote($this->id) . ' ' . ' ) '); $this->_db->setQuery($query); $ret = $this->_db->query(); } // joaktree_relation_notes if ($ret) { $table = 'joaktree_relation_notes'; $query->clear(); $query->delete(' #__joaktree_relation_notes '); $query->where(' app_id = ' . $this->app_id . ' '); $query->where(' ( person_id_1 = ' . $this->_db->quote($this->id) . ' ' . ' OR person_id_2 = ' . $this->_db->quote($this->id) . ' ' . ' ) '); $this->_db->setQuery($query); $ret = $this->_db->query(); } // joaktree_citations if ($ret) { $table = 'joaktree_citations'; $query->clear(); $query->delete(' #__joaktree_citations '); $query->where(' app_id = ' . $this->app_id . ' '); $query->where(' ( person_id_1 = ' . $this->_db->quote($this->id) . ' ' . ' OR person_id_2 = ' . $this->_db->quote($this->id) . ' ' . ' ) '); $this->_db->setQuery($query); $ret = $this->_db->query(); } // joaktree_notes if ($ret) { $table = 'joaktree_notes'; $query->clear(); $query->delete(' #__joaktree_notes '); $query->where(' app_id = ' . $this->app_id . ' '); $query->where(' NOT EXISTS ( ' . ' SELECT 1 ' . ' FROM #__joaktree_person_notes jpn ' . ' WHERE jpn.app_id = app_id ' . ' AND jpn.note_id = id ' . ' ) '); $query->where(' NOT EXISTS ( ' . ' SELECT 1 ' . ' FROM #__joaktree_relation_notes jrn ' . ' WHERE jrn.app_id = app_id ' . ' AND jrn.note_id = id ' . ' ) '); $this->_db->setQuery($query); $ret = $this->_db->query(); } // joaktree_tree_persons if ($ret) { $table = 'joaktree_tree_persons'; $query->clear(); $query->delete(' #__joaktree_tree_persons '); $query->where(' app_id = ' . $this->app_id . ' '); $query->where(' person_id = ' . $this->_db->quote($this->id) . ' '); $this->_db->setQuery($query); $ret = $this->_db->query(); } // joaktree_persons if ($ret) { $table = 'joaktree_persons'; $query->clear(); $query->delete(' #__joaktree_persons '); $query->where(' app_id = ' . $this->app_id . ' '); $query->where(' id = ' . $this->_db->quote($this->id) . ' '); $this->_db->setQuery($query); $ret = $this->_db->query(); } // joaktree_admin_persons if ($ret) { $table = 'joaktree_admin_persons'; $query->clear(); $query->delete(' #__joaktree_admin_persons '); $query->where(' app_id = ' . $this->app_id . ' '); $query->where(' id = ' . $this->_db->quote($this->id) . ' '); $this->_db->setQuery($query); $ret = $this->_db->query(); } if (!$ret) { $this->setError('Cascading table ' . $table . ': Error -> ' . $this->_db->getErrorMsg()); } return $ret; }
public function process($part) { // initialize parameters and paths / filename $params = JoaktreeHelper::getJTParams($this->procObject->id); $conversion_type = $params->get('unicode2utf'); $path = JPATH_ROOT . DS . $params->get('gedcomfile_path'); $filename = $path . DS . $params->get('gedcomfile_name'); $patronymSetting = (int) $params->get('patronym'); $truncate_rel_value = (int) $params->get('truncrelations'); // $procStep = (int) $params->get('processStep', 1); $procStepSize = (int) $params->get('procStepSize', 50); $ret = true; // $indAjax = ($procStep == 1); $indAjax = true; // check if gedcom file exists if (!JFile::exists($filename)) { $this->procObject->msg .= '<br />' . JText::sprintf('JTGEDCOM_MESSAGE_NOGEDCOM', $filename); $this->procObject->status = 'error'; return $this->procObject; } // initialize array $objectLine = array(); $this->objectLines = array(); // What type of conversion if ($conversion_type == 0) { // no conversion $conversion = false; } else { if ($conversion_type == 1) { // conversion from ANSEL to UTF-8 $conversion = true; $this->unicode2utf = true; } else { if ($conversion_type == 2) { // conversion from ANSEL to Unicode $conversion = true; $this->unicode2utf = false; } else { // parameter has unknown value: no conversion $conversion = false; } } } // remove double and trailing characters, like comma's if ($params->get('removeChar')) { $removeChar = $params->get('removeChar'); } else { $removeChar = false; } // initialize counters $teller0 = 0; // counter for gedcom objects $tellert = 0; // counter for total number of lines in file // Loop through the array looking for header info. $ansel = false; $char_done = false; $vers_done = false; // open file $handle = @fopen($filename, "r"); if ($handle && $this->procObject->status == 'new') { // loop through the lines while (!feof($handle)) { $line = fgets($handle, 4096); $line = trim($line); // we are ready if ($char_done and $vers_done) { break; } // remove end-of-line characters $line = rtrim($line, "\r\n"); // split line into three parts with space as deviding character $elements = explode(" ", $line, 3); if (!isset($elements[0])) { $elements[0] = null; } else { $elements[0] = trim($elements[0]); } if (!isset($elements[1])) { $elements[1] = null; } else { $elements[1] = trim($elements[1]); } if (!isset($elements[2])) { $elements[2] = null; } else { $elements[2] = trim($elements[2]); } // first part of line is the level; $level = $elements[0]; // process only the header: so is this the header if ($level == 0) { if ($elements[1] == 'HEAD') { $ind_header = true; } else { $ind_header = false; } } // process only the header if ($ind_header == true) { // see whether we have to transer ANSEL to UTF-8 // other character sets are left alone. if ($elements[1] == 'CHAR') { $char_done = true; if ($elements[2] == 'ANSEL') { $ansel = true; } } // check the version of GEDCOM: is this the GEDCOM and not SOURCE? if ($elements[1] == 'GEDC') { $ind_get_vers = true; } else { $ind_get_vers = false; } // check version of GEDCOM if ($elements[1] == 'VERS' and $ind_get_vers) { $vers_done = true; $version = substr($elements[2], 0, 3); if ($version != '5.5' and $version != '5.5.1') { $this->procObject->msg .= '<br />' . JText::_('JTGEDCOM_MESSAGE_NOV55'); $this->procObject->status = 'error'; return $this->procObject; } } } // end of if ind_header == true } // end of loop } // if charcter set is ANSEL if ($conversion == true and $ansel == true) { $result = $this->prepareANSEL(); if ($result) { $this->procObject->msg .= $result; } } $this->objectType = 'START'; switch ($part) { case "person": $filterTag = 'INDI'; break; case "family": $filterTag = 'FAM'; // remove relations if ($truncate_rel_value == 1 && $this->procObject->status == 'new') { $relation_notes =& JMFPKTable::getInstance('joaktree_relation_notes', 'Table'); $retdelete = $relation_notes->truncateApp($this->procObject->id); $relation_events =& JMFPKTable::getInstance('joaktree_relation_events', 'Table'); $retdelete = $relation_events->truncateApp($this->procObject->id); $relations =& JMFPKTable::getInstance('joaktree_relations', 'Table'); $retdelete = $relations->truncateApp($this->procObject->id); $relation_citations =& JMFPKTable::getInstance('joaktree_citations', 'Table'); $retdelete = $relation_citations->truncateRelationCitations($this->procObject->id); } break; case "source": $filterTag = 'SOUR'; break; case "repository": $filterTag = 'REPO'; break; case "note": $filterTag = 'NOTE'; break; case "document": $filterTag = 'OBJE'; break; case "all": // same as default // same as default default: $filterTag = null; // remove relations if ($truncate_rel_value == 1 && $this->procObject->status == 'new') { $relation_notes =& JMFPKTable::getInstance('joaktree_relation_notes', 'Table'); $retdelete = $relation_notes->truncateApp($this->procObject->id); $relation_events =& JMFPKTable::getInstance('joaktree_relation_events', 'Table'); $retdelete = $relation_events->truncateApp($this->procObject->id); $relations =& JMFPKTable::getInstance('joaktree_relations', 'Table'); $retdelete = $relations->truncateApp($this->procObject->id); $relation_citations =& JMFPKTable::getInstance('joaktree_citations', 'Table'); $retdelete = $relation_citations->truncateRelationCitations($this->procObject->id); } break; } $indProcess = false; if (!$indAjax) { // we will not be looping back to the caller // instead we will go one time through the whole GedCom file // so status is set now to 'progress' $this->procObject->status = 'progress'; } // Loop through the array. if ($handle && ($this->procObject->status == 'progress' || $this->procObject->status == 'new')) { // move to the beginning fseek($handle, $this->procObject->cursor); // loop through the lines while (!feof($handle)) { $line = fgets($handle); $line = trim($line); $tellert++; // remove end-of-line characters $line = rtrim($line, "\r\n"); // if ANSEL convert the line if ($conversion == true and $ansel == true) { $line = $this->convertANSEL($line); } // remove double or trailing characters if ($removeChar) { $remove = true; while ($remove) { $line = str_replace($removeChar . $removeChar, $removeChar, $line, $countReplace); if ($countReplace == 0) { $remove = false; } } $line = trim($line, $removeChar); } // split line into three parts with space as deviding character $elements = explode(" ", $line, 3); if (!isset($elements[0])) { $elements[0] = null; } else { $elements[0] = trim($elements[0]); } if (!isset($elements[1])) { $elements[1] = null; } else { $elements[1] = trim($elements[1]); } if (!isset($elements[2])) { $elements[2] = null; } else { $elements[2] = trim($elements[2]); } // first part of line is the level; $level = $elements[0]; // the level 0 lines are the main lines (=gedcom objects) // these lines are stored in object table // when level is greater than 0, it is a depending line and // stored in object-line table if ($level == 0) { // level = 0: we dealing with the object // first process the previous object (if existing) if ($indProcess) { $this->process_object(); if ($indAjax && $teller0 == $procStepSize) { $this->procObject->cursor = $fileCursor; $this->procObject->status = 'progress'; fclose($handle); return $this->procObject; } } // set boolean to check the first objectline $indFirstLine = true; if ($elements[2] == null) { // third element is empty for level 0 line // tag is in the second element // there is no value. this will be filled with value from counter object_value_id $this->objectType = $elements[1]; $this->objectKey = null; } else { // third element is not empty. this countains the tag // second element contains the value // value has to be stripped from @ characters // However third element may also contain a value ... it is weird but true $subelems = explode(" ", $elements[2], 2); if (!isset($subelems[0])) { $subelems[0] = null; } else { $subelems[0] = trim($subelems[0]); } if (!isset($subelems[1])) { $subelems[1] = null; } else { $subelems[1] = trim($subelems[1]); } if ($subelems[1] == null) { // everything is ok and normal $this->objectType = $elements[2]; $this->objectKey = ltrim(rtrim($elements[1], '@'), '@'); } else { // extra value found in the line!! $this->objectType = $subelems[0]; $this->objectKey = ltrim(rtrim($elements[1], '@'), '@'); // this is really a new tag. $objectLine['object_id'] = $this->objectKey; $objectLine['level'] = 1; $objectLine['tag'] = "TEXT"; $objectLine['value'] = $subelems[1]; // keep the object line $this->objectLines[] = $objectLine; $indFirstLine = false; } } $teller0++; if ($filterTag) { if ($filterTag == $this->objectType) { $indProcess = true; } else { $indProcess = false; } } else { $indProcess = true; } } else { if ($indProcess) { // level <> 0: we dealing with object lines // element 2 contains the tag; element 3 contains the value $tag = $elements[1]; $value = $elements[2]; // replace special characters in value // & (= ampersand) $value = str_replace("&", "&", $value); // < (= less than sign) $value = str_replace("<", "<", $value); // > (= greater than sign) $value = str_replace(">", ">", $value); // ' (= single quote) //$value = str_replace("'", "'", $value); //$value = htmlspecialchars($value, ENT_QUOTES, 'UTF-8'); // Deal with the first line if it is not a real tag if ($indFirstLine) { // Aldfaer uses for notes as first line CONC. // This should be text, and here we fix it. if ($tag == 'CONC' or $tag == 'CONT') { $tag = 'TEXT'; } $indFirstLine = false; } if ($tag == 'CONC' or $tag == 'CONT') { // this line is a continutation of the previouse line $objectLine = array_pop($this->objectLines); if ($tag == 'CONC') { $objectLine['value'] = $objectLine['value'] . $value; } else { if ($tag == 'CONT') { $objectLine['value'] = $objectLine['value'] . ' ' . $value; } } // keep the object line $this->objectLines[] = $objectLine; } else { // this is really a new tag. $objectLine['object_id'] = $this->objectKey; $objectLine['level'] = $level; $objectLine['tag'] = $tag; $objectLine['value'] = $value; // keep the object line $this->objectLines[] = $objectLine; } } } // end of check on level = 0 $fileCursor = ftell($handle); } // end of loop through array } if ($handle) { fclose($handle); } // if the number of objects is smaller than the step size // status never reached 'progress'. It is still 'new'. if ($indAjax && $this->procObject->status == 'new' && $teller0 < $procStepSize) { $this->procObject->cursor = $fileCursor; $this->procObject->status = 'progress'; return $this->procObject; } $this->procObject->cursor = isset($fileCursor) ? $fileCursor : 0; if ($this->procObject->status == 'progress') { // status is progress: this means our last action was reading the file // we are done with that for now - time for a new status $this->procObject->status = 'endload'; if ($indAjax) { // we are looping back to the caller return $this->procObject; } } if ($patronymSetting != 0 && $patronymSetting != 1 && $this->procObject->status == 'endload') { // we are not setting the patronyms - just update the status to the next $this->procObject->status = 'endpat'; if ($indAjax) { // we are looping back to the caller return $this->procObject; } } // if setting is NOT to retrieve patronyms from name string, patronyms have to determined now if (($patronymSetting == 0 || $patronymSetting == 1) && $this->procObject->status == 'endload') { $ret = jt_names::setPatronyms($this->procObject->id); if (!$ret) { // if no result - an error occured and we stop $this->procObject->status = 'error'; $this->procObject->msg .= JText::_('JTGEDCOM_MESSAGE_NOSUCPATRONYMS'); return $this->procObject; } else { // we are done - so change the status $this->procObject->status = 'endpat'; if ($indAjax) { // we are looping back to the caller $this->procObject->msg .= JText::_('JTGEDCOM_MESSAGE_SUCPATRONYMS'); return $this->procObject; } } } // Set the indicators for different types of relationships after processing all persons if ($this->procObject->status == 'endpat') { $ret = jt_relations::setRelationIndicators($this->procObject->id); // if no result - an error occured and we stop if (!$ret) { $this->procObject->status = 'error'; $this->procObject->msg .= JText::_('JTGEDCOM_MESSAGE_NOSUCRELINDICATORS'); return $this->procObject; } else { $this->procObject->status = 'endrel'; if ($indAjax) { // we are looping back to the caller $this->procObject->msg .= JText::_('JTGEDCOM_MESSAGE_SUCRELINDICATORS'); return $this->procObject; } } } return $this->procObject; }
public function save(&$form) { $canDo = JoaktreeHelper::getActions(); $ret = false; // Edit changes if (is_object($canDo)) { // in case we need to set relation indicators $this->relationIds = array(); if ($canDo->get('core.create')) { // in case of a new person the id is empty and we are filling it now if ($form['person']['status'] == 'new') { // retreive ID and double check that it is not used $continue = true; $i = 0; while ($continue) { $tmpId = JoaktreeHelper::generateJTId(); $i++; if ($this->check($tmpId, 'person')) { $form['person']['id'] = $tmpId; $continue = false; break; } if ($i > 100) { $continue = false; return JText::_('JTAPPS_MESSAGE_NOSAVE'); } } } switch ($form['type']) { case "newperson": $ret = $this->save_events($form, 'person'); break; case "addparent": case "addpartner": case "addchild": $ret = $this->add_person_relations($form); if ($ret) { $ret = $this->save_events($form, 'person'); } break; default: // continue break; } } if ($canDo->get('core.edit')) { switch ($form['type']) { case "pevents": $ret = $this->save_events($form, 'person'); break; case "revents": $ret = $this->save_events($form, 'relation'); break; case "names": $ret = $this->save_names($form, 'all'); break; case "notes": $ret = $this->save_notes($form, 'person', null); break; case "references": $ret = $this->save_references($form, 'person'); break; case "media": $ret = $this->save_media($form); break; case "medialist": $ret = $this->save_medialist($form); break; case "parents": case "partners": case "children": $ret = $this->update_person_relations($form); break; default: // continue break; } } if ($canDo->get('core.edit.state')) { // State changes switch ($form['type']) { case "state": $ret = $this->save_state($form); break; default: // continue break; } } // always save / update the person if ($ret) { $ret = $this->save_person($form); } // set relation indicators - if applicable if ($ret && count($this->relationIds) > 0) { $ret = jt_relations::setRelationIndicators($form['person']['app_id'], $this->relationIds); } } // Deal with errors $errors = $this->getErrors(); if (count($errors) > 0) { $text = implode(' ##### ', $errors); $ret = false; } else { $text = $ret ? 'JT_SAVED' : 'JT_NOTAUTHORISED'; } return JText::_($text); }