view models/extractapp.php @ 84:ecc4b22e9b05 extractapp

Bug fixed: missing section id variable in export table from LGservice.
author Zoe Hong <zhong@mpiwg-berlin.mpg.de>
date Thu, 23 Apr 2015 17:06:03 +0200
parents 7b05275b7a70
children 0141df465205
line wrap: on
line source

<?php
/*
 * extractapp.php
 * This file is part of Extraction-interface.
 *
 * Extraction-interface is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Extraction-interface is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Extraction-interface.  If not, see <http://www.gnu.org/licenses/>.
*/
/** 
 * ExtractappModel class is extended from the BaseModel class.
 * This is where we implement the functions/models to prepare data that been sent to views.
 * ExtractappModel is notified by Extractapp controller when there has been a change in its state,
 * and produces the output/data to the corresponding view in "views/Extractapp/". 
 * 
*/

class ExtractappModel extends BaseModel{
    
    protected $section_id = 0, $data_path, $file_id = 0, $current_fileId=0, 
        $branch_id = 0, $user_id = 0, $lg_text = "", $topic, $taglist_infile = "", $book_meta = "",$book_dynasty="";
    public $messages = array('info'=>"",'error'=>"",'warning'=>"",'debug'=>"");


    public function SetTextFromFileId() {   // remove $_postdata as input
        /**
         * Get text content from LGService by $this->file_id. 
         * After preprocessing the text string (replace space to circle symbol, link for page number, etc),
         * set $this->lg_text to the processed text gotten from LGService.
         */

        /*
        $this->file_id = $_postdata['fileId'];
        $branch_id = $_postdata['branchId'];
        $section_id = $_postdata['sectionId'];

        $this->branch_id = $branch_id;
        $this->user_id = $_postdata['userId'];
        $this->section_id = $section_id;

        $this->section_name = $_postdata['sectionName'];
        $this->book_id = $_postdata['bookId'];
        $this->book_name = $_postdata['bookName'];
        */

        // get from URL with file_id
        $lg_text_url = $this->get_text_from_fileId_url.$this->file_id;
        //$lg_text = file_get_contents($lg_text_url);
        // --- get/set text and parsing meta data from text file
        $lg_text = $this->ParseDataInFile($lg_text_url);


        $stringInput = $lg_text;
        $stringInput = preg_replace("/ /u", "○", $stringInput);
        $stringInput = preg_replace("/\n/u", "<br>", $stringInput);
        $stringInput = preg_replace("/【(.*?)】/u", "【<a href=\"review_index_xml_images.php?books_id=".$this->book_id."&pages=\\1&entry=0\" target=\"_bookImg\">\\1</a>】", $stringInput);
        $lg_text = $stringInput;

        $this->lg_text = $lg_text;

    }

    public function SetBookMetadataBySectionId() {

        // get book_meta from $$this->get_section_metadata_by_sectionId_url
        $section_meta_url = $this->get_section_metadata_by_sectionId_url.$this->section_id;
        $section_meta = json_decode(file_get_contents($section_meta_url), true);

        $b = $section_meta['section']['book'];

        $book_meta = array();
        array_push($book_meta, array($b['id'],$b['name'],$b['level1'],$b['level2'],
                    $b['period'],$b['dynasty'], $b['start_year'], $b['end_year'],$b['line'],
                    $b['volume'],$b['author'], $b['edition'],$b['in_jibengujiku'], $b['admin_type']));    // missing author,year,pagenumber
        $this->book_meta = $book_meta;

    }

    public function SetTextFromSectionId() {  // remove $_postdata as input
        /**
         * Get text content from LGService by $this->section_id. 
         * After preprocessing the text string (replace space to circle symbol, link for page number, etc),
         * set $this->lg_text to the processed text gotten from LGService.
         */

        /*
        $section_id = $_postdata['sectionId'];
        $this->section_id = $section_id;
        $this->user_id = $_postdata['userId'];

        $this->section_name = $_postdata['sectionName'];
        $this->book_id = $_postdata['bookId'];
        $this->book_name = $_postdata['bookName'];
        */

        // get from URL with file_id
        // $lg_text_url = $this->get_text_from_sectionId_url.$section_id;
        $lg_text_url = $this->get_text_from_sectionId_url.$this->section_id;
        $lg_text = file_get_contents($lg_text_url);


        $stringInput = $lg_text;
        $stringInput = preg_replace("/<(.*?)>/u", "○", $stringInput);
        $stringInput = preg_replace("/ /u", "○", $stringInput);
        $stringInput = preg_replace("/\n/u", "<br>", $stringInput);
        $stringInput = preg_replace("/【(.*?)】/u", "【<a href=\"review_index_xml_images.php?books_id=".$this->book_id."&pages=\\1&entry=0\" target=\"_bookImg\">\\1</a>】", $stringInput);
        $lg_text = $stringInput;

        $this->lg_text = $lg_text;
    }

    // This is only used on localhost
    public function SetTextFromLocal($_id){     
        $this->section_id = $_id;
        //$this->branch_id = 1;   // local test sets branch_id to 1
        $this->messages['debug'] .= "[Debug] from my local"."<br>";
        $this->lg_text = $this->GetSectionContent();
    }


    public function SetInfoFromPreviousPage($_postdata) {
        /**
         * Get information from post data passsed by the previous page, and set variables in $this.
         * The previous page could be: 
         *
         * (1) LGService: the first time user enters Extraction-interface, which should linked from LGService. 
         *
         * (2) Extraction-interface itself: changing topic then continue to tag, saving text to LGService, reload the text from LGService.
         * 
         */

        if (isset($_postdata['fileId'])) {
            $this->file_id = $_postdata['fileId'];
        }
        if (isset($_postdata['sectionId'])) {
            $this->section_id = $_postdata['sectionId'];
        }
        if (isset($_postdata['text'])) {
            $this->lg_text = $_postdata['text'];
        }
        if (isset($_postdata['branchId'])) {
            $this->branch_id = $_postdata['branchId'];
        }
        if (isset($_postdata['userId'])) {
            $this->user_id = $_postdata['userId'];
        }
        if (isset($_postdata['topic_id'])) {
            $this->topic = $_postdata['topic_id'];
        }
        if (isset($_postdata['sectionName'])) {
            $this->section_name = $_postdata['sectionName'];
        }
        if (isset($_postdata['bookName'])) {
            $this->book_name = $_postdata['bookName'];
        }
        if (isset($_postdata['bookId'])) {
            $this->book_id = $_postdata['bookId'];
        }
        if (isset($_postdata['currentFileId'])) {
            $this->current_fileId = $_postdata['currentFileId'];
        }
        if (isset($_postdata['taglistArray'])) {
            $this->taglist_infile = json_decode($_postdata['taglistArray']);
        }
        if (isset($_postdata['book_meta'])) {
            $this->book_meta = json_decode($_postdata['book_meta']);
        }

    }


    private function TaglistSubsetIn($list1, $list2) {    // $l1 is a subset of $l2 or not
        // l1 and l2: array( $row['id'], $row['name'], $row['tag'], $row['color'] )
        $cnt_list1 = count($list1);
        $cnt_list2 = count($list2);

        if ($cnt_list1 > $cnt_list2) {
            return false;
        }
        foreach ($list1 as $v1) {
            $cnt = 0;
            foreach ($list2 as $v2) {
                $num_field = count($v2);
                $matched = true;
                for ($i=0; $i < $num_field; $i++) { 
                    if ($v1[$i] != $v2[$i]) {
                        $matched = false;
                        break;
                    }
                }

                if (!$matched) {
                    // not match with this v2
                    $cnt += 1;
                } else {
                    break;
                }

            }
            if ($cnt == $cnt_list2) {
                return false; 
            }
        }
        return true;
       
    }

    // === for tagging ===
    public function StartTagging() {
        /**
         * This is the main method for tagging text. It passes all the information to "views/Extractapp/TaggingText.php" view.
         * The information contain the text string, taglist array, wordlis array, topic, etc.
         */
       
        $section_id = $this->section_id;
        $stringInput = $this->lg_text;

        $data = array();    // data array to be passed to view

        //$taglistArray = $this->GetTaglistArray();
        //for GetTaglistByTopicId: 
        $taglistArray = $this->GetTaglistByTopicId($this->GetTopic());
        
        // $this->taglist_infile is set (1) from file or (2) from _postdata['taglistArray'] which comes from frontend that user decided
        // $this->taglist_infile is the most up-to-date taglist decided by user. Should be written into file.
        if( $this->TaglistSubsetIn($this->taglist_infile, $taglistArray) ) {    // TaglistSubsetIn($l1,$l2): $l1 is a subset of $l2 or not
            $this->taglist_infile = "";
        } 
        $data['taglist_infile'] = $this->taglist_infile;    // if taglist_infile == "" means taglist in file is up-to-date (will use taglist in db), otherwise means the taglist in file

        
        // book_meta
        $data['book_meta'] = $this->book_meta;

        // topic list
        $topiclistArray = $this->GetTopiclistArray();


        $wordlistArray = $this->GetWordlistArray();

        $data['stringInput'] = $stringInput;
        $data['taglistArray'] = $taglistArray;
        $data['wordlistArray'] = $wordlistArray;
        $data['section_id'] = $section_id;
        $data['topiclistArray'] = $topiclistArray;
        $data['default_topic_id'] = $this->GetTopic();
        $data['topic_tag'] = $this->GetTopicTag($this->GetTopic());
        $data['topic_name'] = $this->GetTopicName($this->GetTopic());


        $data['info'] = array('file_id'=>$this->file_id, 'user_id'=>$this->user_id,
                'branch_id'=>$this->branch_id, 'section_id'=>$this->section_id, 'book_id'=>$this->book_id, 
                'book_name'=>$this->book_name, 'section_name'=>$this->section_name,
                'current_fileId'=>$this->current_fileId);

        $this->messages['debug'] .= "[Debug] ";
        $this->messages['debug'] .= "file_id=".$this->file_id.", section_id=".$this->section_id;
        $this->messages['debug'] .= ", user_id=".$this->user_id.", branch_id=".$this->branch_id.", topic_id=".$this->topic;
        $this->messages['debug'] .= ", book_id=".$this->book_id.", book_name=".$this->book_name.", section_name=".$this->section_name;
        $this->messages['debug'] .= ", current_fileId=".$this->current_fileId."<br>";

        $this->messages['info'] .= "[Info] book name: ".$this->book_name;
        $this->messages['info'] .= ", section id: ". $this->section_id;
        $this->messages['info'] .= ", branch id: ".$this->branch_id;
        $this->messages['info'] .= ", file id: ".$this->file_id;
        $this->messages['info'] .= "<br>";


        $data['messages'] = $this->messages;

        return $data;
        
    }

    public function SaveFullText($postdata) {
        // locally
        if ($postdata['text']){
            $date = date('Y_m_d_H_i_s', time());
            if ( file_exists("data/parsing_files/".$postdata['filename'].".txt") ) {
                $oldFile = file_get_contents("data/parsing_files/".$postdata['filename'].".txt");
                file_put_contents("data/parsing_files/".$postdata['filename']."_".$date.".txt", $oldFile);
            }
            
            if (get_magic_quotes_gpc()) {
                $require = stripslashes($postdata['text']);
            } else {
                $require = $postdata['text'];
            }
            
            $require = preg_replace("/【<a(.*?)>(.*?)<\/a>】/u", "【\\2】", $require);
            $require = preg_replace('/&amp;/u', "&", $require); 
            $require = preg_replace("/○/u", " ", $require); 
            $require = preg_replace("/<br>/u", "\n", $require);
            $require = preg_replace("/<br>/u", "\n", $require);
            file_put_contents("data/parsing_files/".$postdata['filename'].".txt", $require);
        }

    }

    public function UpdateInfoResponsedFromLGService($response) {
        /**
         *
         */


        if (isset($response["file"])) {
            $response_file = $response["file"];
        }
        if (isset($response["branch"])) {
            $response_branch = $response["branch"];
        }

        $status = (string)$response["status"];
        if ($status == "ok") {
            $this->messages['info'] .= "[Info] Saving success. <br>";
            $this->file_id = (string)$response_file["id"]; 
            $this->branch_id = (string)$response_branch["id"];

        } else if ($status == "error") {
            // saving not success
            $this->messages['error'] .= "[Error] Saving Failed! ".(string)$response["message"]."<br>";
            $this->messages['warning'] .= "[Warning] Please check branch ".$this->branch_id." in LGService, and modify from the latest version.";

            $response_currentFile = $response["currentFile"];
            $this->current_fileId = (string)$response_currentFile["id"];

        }
        

    }

    public function ReloadSetting() {
        if ($this->current_fileId != 0) {
            $this->file_id = $this->current_fileId;
            $this->current_fileId = 0;
        }
    }

    // This is only called by SaveFullTextToLGService()
    private function AppendMetadata($text_content) {
        $text = '<?xml version="1.0" encoding="UTF-8"?>';
        $text .= "\n<text>\n";
        // --- topic ---
        $text .= "<topic>".$this->topic."</topic>\n";
        // --- book meta data ---
        $book = $this->book_meta;
        foreach ($book as $b) {
            $text .= "<book>\n";
            $text .= "<id>".$b[0]."</id>\n";
            $text .= "<name>".$b[1]."</name>\n";
            $text .= "<level1>".$b[2]."</level1>\n";
            $text .= "<level2>".$b[3]."</level2>\n";
            $text .= "<period>".$b[4]."</period>\n";
            $text .= "<dynasty>".$b[5]."</dynasty>\n";
            $text .= "<start_year>".$b[6]."</start_year>\n";
            $text .= "<end_year>".$b[7]."</end_year>\n";
            $text .= "<line>".$b[8]."</line>\n";
            $text .= "<volume>".$b[9]."</volume>\n";
            $text .= "<author>".$b[10]."</author>\n";
            $text .= "<edition>".$b[11]."</edition>\n";
            $text .= "<in_jibengujiku>".$b[12]."</in_jibengujiku>\n";
            $text .= "<admin_type>".$b[13]."</admin_type>\n";
            $text .= "</book>\n";
            
        }
        // --- section info ---
        $text .= "<section>\n";
        $text .= "<id>".$this->section_id."</id>\n";
        $text .= "<name>".$this->section_name."</name>\n";
        $text .= "</section>\n";

        // ---- taglist ---
        // $taglist = $this->taglist_infile;
        // obtain the latest taglist from db
        $taglist = $this->GetTaglistByTopicId($this->GetTopic());

        foreach ($taglist as $tagitem) {
            $text .= "<tagitem>\n";
            $text .= "<id>".$tagitem[0]."</id>\n";
            $text .= "<name>".$tagitem[1]."</name>\n";
            $text .= "<tag>".$tagitem[2]."</tag>\n";
            $text .= "<color>".$tagitem[3]."</color>\n";
            $text .= "</tagitem>\n";
        }
        // ----
        // --- text_content ---
        $text .= $text_content;
        $text .= "</text>";
        // ----

        return $text;
    }

    public function SaveFullTextToLGService($_postdata) {
        /**
         * It saves the full tagged text string in postdata to LGService.
         * The responses returned by LGService will later be handled in 
         */

        // --------
        global $AT_LOCAL;

        if ($_postdata['text']){
            $date = date('Y_m_d_H_i_s', time());
            if ( file_exists("data/parsing_files/".$_postdata['sectionId'].".txt") ) {
                $oldFile = file_get_contents("data/parsing_files/".$_postdata['sectionId'].".txt");
                //saving in my local machine in developing phrase
                if ($AT_LOCAL) {
                    file_put_contents("data/parsing_files/".$_postdata['sectionId']."_".$date.".txt", $oldFile);
                }
            }
            
            if (get_magic_quotes_gpc()) {
                $require = stripslashes($_postdata['text']);
            } else {
                $require = $_postdata['text'];
            }
 
            $require = preg_replace("/【<a(.*?)>(.*?)<\/a>】/u", "【\\2】", $require);
            $require = preg_replace('/&amp;/u', "&", $require); 
            $require = preg_replace("/○/u", " ", $require); 
            $require = preg_replace("/<br(.*?)>/u", "\n", $require);
            //$require = preg_replace("/<br>/u", "\n", $require);

            $require = "<text_content>".$require."</text_content>\n";
            
            /*
            if ($_postdata['branchId'] == 0) {
                // -- new branch case
                $require = "<text_content>".$require."</text_content>\n";
            }
            */

            $require = $this->AppendMetadata($require);
                
            //saving in my local machine in developing phrase
            if ($AT_LOCAL) {
                file_put_contents("data/parsing_files/".$_postdata['sectionId'].".txt", $require);
            }
        } 

        // ------


        if ($_postdata['branchId'] != 0) {
            // -- exiting branch case
            $postfields = array(
                "text" => $require, 
                "branchId" => $_postdata['branchId'],
                "userId" => $_postdata['userId'],
                "userPreviousFileId" => $_postdata['fileId'],
            );  
            $save_url = $this->save_to_LGService_url;     

        } else {
            // -- new branch case
            // echo "saveNew!";
            $user_id = "0";
            if ($_postdata['userId']) {
                $user_id = $_postdata['userId'];
            }
            
            $postfields = array(
                "text" => $require, 
                "sectionId" => $_postdata['sectionId'],
                "userId" => $user_id,
                "label" => $_postdata['label'],
            ); 
            $save_url = $this->save_new_to_LGService_url;
        }   

        
        // set up the curl resource
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $save_url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
        //curl_setopt($ch, CURLOPT_HEADER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(                                                                          
            'Content-type: multipart/form-data;charset=utf-8'                                                          
        ));       

        if (!$AT_LOCAL) {
            // execute the request
            $output = curl_exec($ch);
        }


        // output the profile information - includes the header
        //echo($output) . PHP_EOL;

        // close curl resource to free up system resources
        curl_close($ch);
        
        $response = json_decode($output, true);
        return $response;

    }

    // --- for regex ----
    private function GetRegexFilenameById($topic_id) {
        $query = sprintf("SELECT regex_filename FROM `topic_regex_relation` WHERE  topic_id=\"%s\"", $topic_id);
        $result = mysql_query($query);
        if (!$result) {
            return json_encode("Failed during selecting topic_regex_relation table.");
        }

        $filenames = array();
        while ($row = mysql_fetch_assoc($result)) {
            array_push($filenames, $row['regex_filename']);
        }

        return $filenames;
    }
    public function LoadSmartRegex($topic_id) {

        // Load regex file based on current topic. Only shows the regex in this topic --
        $filenames = $this->GetRegexFilenameById($topic_id);
        
        // Get regex file from filesystem ----
        $data_path = "./data/"; // get the current file path, which is getcwd(), and concatenate with "/data/"
        $returnArray = array();
        $files1 = scandir($data_path."regex_files");
        foreach ( $files1 as $file ) {
            if ( $file != "." && $file != ".." && $file != ".DS_Store") {
                foreach ($filenames as $filename) {
                    if ($file == $filename) {
                        $returnArray[preg_replace("/\.txt/", "", $file)] = file_get_contents( $data_path."regex_files/".$file );
                        break;
                    }
                }
            }
        }
        echo json_encode($returnArray);
        return;
    }


    public function SaveSmartRegex($_postdata) {
        if ($_postdata['text']){

            // --- update topic_regex_relation table ---
            $topic_id = $_postdata['topic_id'];
            $filename = $_postdata['filename'].'.txt';
            
            // check if already existing a record for this regex file
            $query = "SELECT * FROM topic_regex_relation WHERE topic_id=".$topic_id." AND regex_filename='".$filename."'";
            $result = mysql_query($query);
            if (!$result) {
                echo json_encode("ErrorDB");
            }
            while ($row = mysql_fetch_assoc($result)) {
                if ($row && !$_postdata['forcesave']) {
                    // promt user a comfirm to force saving or not
                    echo json_encode("ForceSave");
                    return;
                }
            } 

        
            if (!$_postdata['forcesave']) {
                $query = "INSERT INTO topic_regex_relation (topic_id, regex_filename) VALUES (".$topic_id.",'".$filename."')";
                $result = mysql_query($query);
                if (!$result) {
                    echo json_encode("ErrorDB");
                }
            } 
            // --- write to filesystem ---
            
            /*
            $date = date('Y_m_d_H_i_s', time());
            if ( file_exists("regex_files/".$_POST['filename'].".txt") ) {
                $oldFile = file_get_contents("regex_files/".$_POST['filename'].".txt");
                file_put_contents("regex_files/".$_POST['filename']."_".$date.".txt", $oldFile);
            }
            */
            $data_path = "./data/"; // get the current file path, which is getcwd(), and concatenate with "/data/"
            
            if (get_magic_quotes_gpc()) {
                $require = stripslashes($_postdata['text']);
            } else {
                $require = $_postdata['text'];
            }

            file_put_contents( $data_path."regex_files/".$_postdata['filename'].".txt", $require);   


        }
    }


    private function GetTableArray($_taglistArray, $_topic_tag, $_content) {

        $outputTableArray = array();
        $outputTableArray[0]=array();
        $outputTableArray[0][0]=array();
        $outputTableArray[0][1]=array();
        foreach ( $_taglistArray as $value ) {
            $outputTableArray[0][0][$value[2]] = $value[1];
            $outputTableArray[0][1][$value[2]] = $value[1]."(Title)";
        }
        $outputTableArray[0]["other"] = "其他";
        $outputTableArray[0]["page"] = "頁數";
        $outputTableArray[0]["full"] = "全文";

        // id, name, tag, color in _taglistArray
        foreach ( $_taglistArray as $tagValue ) {
            $tag_name = $tagValue[2];   // $tagValue[2] is tag_name
            $content = preg_replace("/<\/".$tag_name.">○*<".$tag_name.">/u", "", $_content);
            $content = preg_replace("/<".$tag_name.">[ ]*<\/".$tag_name.">/u", "", $_content);
        }

        $contentLineArray = explode( "<br>", $content );

        $count=0;
        $pageNow=NULL;
        foreach ( $contentLineArray as $value ) {
            $count++;
            $recordString = $value;
            $otherString = $recordString;
            //echo $recordString."<br>\n";
            // find hyper link in pattern with <a>...</a>
            if ( preg_match("/【<a(.*?)>(.*?)<\/a>】/u", $recordString, $matches) ) {
                $pageNow = $matches[2];
            }
            foreach ( $_taglistArray as $tagValue ) {
                $tag_name = $tagValue[2];   // $tagValue[2] is tag_name

                if ( preg_match_all("/<".$tag_name.">(.*?)<\/".$tag_name.">/u", $recordString, $matches, PREG_SET_ORDER) ) {
                    foreach ( $matches as $matchesValue ) {
                        $matchesValue[1] = preg_replace("/○/u", "", $matchesValue[1]);

                        if ( preg_match_all("/〈(.*?)〉/u", $matchesValue[1], $matches2, PREG_SET_ORDER) ) {
                            foreach ( $matches2 as $matches2Value ) {
                                if ( isset($outputTableArray[$count][0][$tag_name]) ) {
                                    $outputTableArray[$count][0][$tag_name] .= ";".$matches2Value[1];
                                } else {
                                    $outputTableArray[$count][0][$tag_name] = $matches2Value[1];
                                }
                            }
                        } else {
                            if ( isset($outputTableArray[$count][0][$tag_name]) ) {
                                $outputTableArray[$count][0][$tag_name] .= ";".$matchesValue[1];
                            } else {
                                $outputTableArray[$count][0][$tag_name] = $matchesValue[1];
                            }
                        }
                    }
                    $otherString = preg_replace("/<".$tag_name.">(.*?)<\/".$tag_name.">/u", " ", $otherString);   
                }
            }
            $otherString = preg_replace("/○/u", "", $otherString);
            $outputTableArray[$count]["other"] = $otherString;
            $outputTableArray[$count]["page"] = $pageNow;
            $value = preg_replace("/>/u", "&gt;", $value);
            $value = preg_replace("/</u", "&lt;", $value);
            $outputTableArray[$count]["full"] = $value;
        }
        
        

        foreach ( $outputTableArray as $arrayIndex => $arrayValue ) {
            // output each row which the topic tag
            // e.g. the original version is for 'person'           
            if ( !isset($arrayValue[0][$_topic_tag]) ) {
                unset($outputTableArray[$arrayIndex]);
            }

        }
        // ----- 

        return $outputTableArray;
    }

    // === for export table ===

    public function ExportTable($postdata, $isFromFile) {
        if ($isFromFile) {
            $content = $this->lg_text;
            $topic = $this->topic;
            $section_id = $this->section_id;
            $sectionName = $this->section_name;
            $bookId = $this->book_id;
            $bookName = $this->book_name;

            $taglistArray = $this->taglist_infile;

        } else {
            $content = $postdata['content'];
            $topic = $postdata['topic'];

            $section_id = $postdata['sectionId'];
            $sectionName = $postdata['sectionName'];
            $bookId = $postdata['bookId'];
            $bookName = $postdata['bookName'];

            //$taglistArray = $this->GetTaglistArray();
            $taglistArray = $this->GetTaglistByTopicId($topic);
        }
        // =====

        $topic_tag = $this->GetTopicTag($topic);

        // input data: taglistArray, topic_tag, content; output: outputTableArray
        $outputTableArray = $this->GetTableArray($taglistArray, $topic_tag, $content);



        // data for view
        $data = array();
        $data['outputTableArray'] = $outputTableArray;
        $data['bookId'] = $bookId;
        $data['section_id'] = $section_id;
        $data['bookName'] = $bookName;
        $data['sectionName'] = $sectionName;

        return $data;

    }
    
    // === for manage tag list ===
    public function EditTaglist($_postdata) {
        /**
        */

        $query = "SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='taglist'";
        $result = mysql_query($query);
        if (!$result) {
            echo json_encode(mysql_error());
        }
        $row = mysql_fetch_assoc($result);
        $largest_id = $row['AUTO_INCREMENT']-1;


        $topic_id = $_postdata['topic_id'];
        $result = $this->GetTaglistByTopicId($topic_id);

        $taglistArray = array();

        foreach ($result as $row) {
            $taglistArray[$row[0]] = array($row[1], $row[2], $row[3]);
            //$taglistArray[$row['id']] = array($row['name'], $row['tag'], $row['color']);
        }

        $topic_tag_name = $this->GetTopicTag($topic_id);

        $query = "SELECT id FROM taglist WHERE taglist.tag='".$topic_tag_name."'";
        $result = mysql_query($query);
        if (!$result) {
            echo json_encode(mysql_error());
        }
        $row = mysql_fetch_assoc($result);
        $topic_tag_id = $row['id'];

        $data = array();
        $data['taglistArray'] = $taglistArray;
        $data['topic_id'] = $topic_id;
        $data['largest_id'] = $largest_id;
        $data['topic_tag_id'] = $topic_tag_id;


        return $data;
       
    }

    private function GetTag($_postdata) {
        if (get_magic_quotes_gpc()) {
            $id = stripslashes($_postdata['id']);
            $name = stripslashes($_postdata['name']);
            $tag = stripslashes($_postdata['tag']);
            $color = stripslashes($_postdata['color']);
        } else {
            $id = $_postdata['id'];
            $name = $_postdata['name'];
            $tag = $_postdata['tag'];
            $color = $_postdata['color'];
        }
        return array($id, $name, $tag, $color);
    }

    public function NewTagElement($postdata) {
        if ($postdata['id']){   
            list($id, $name, $tag, $color) = $this->GetTag($postdata);

            $query1 = sprintf("INSERT INTO `taglist` (`id`, `name`, `tag`, `color`, `systemName`) VALUES (%s, %s, %s, %s, %s)",
                                $this->GetSQLValueString($id, "int"),
                                $this->GetSQLValueString($name, "text"),
                                $this->GetSQLValueString($tag, "text"),
                                $this->GetSQLValueString($color, "text"),
                                $this->GetSQLValueString($this->systemNAME, "text"));
            $result1 = mysql_query($query1);


            // add it to topic_tag_relation table
            $topic_id = $postdata['topic_id'];

            // tag_id is $id;
            $query = sprintf("INSERT INTO `topic_tag_relation` (`topic_id`,`tag_id`) VALUES (%s,%s)", $topic_id, $id);
            $result = mysql_query($query);
            if (!$result) {
                echo json_encode("error when insert into topic_tag_relation table");
            }
        }

    }

    public function SaveTagElement($postdata) {
        if ($postdata['id']){   
            list($id, $name, $tag, $color) = $this->GetTag($postdata);
            
            $query = sprintf("UPDATE taglist SET `name`=%s, `tag`=%s, `color`=%s WHERE `id`=%s",
                                $this->GetSQLValueString($name, "text"),
                                $this->GetSQLValueString($tag, "text"),
                                $this->GetSQLValueString($color, "text"),
                                $this->GetSQLValueString($id, "int"));
            $result = mysql_query($query);
                     
        }

    }

    public function DeleteTag($postdata) {
        if ($postdata['id']) {
            $queryInsert = sprintf("DELETE FROM `taglist` WHERE `id` = %s", stripslashes($postdata['id']));
            $resultInsert = mysql_query($queryInsert);
        }

    }

    // === for config topic ===
    public function ConfigTagsInTopic($postdata) {
        /**
        * 
        */

        $topic = $postdata['topic'];
        $result = $this->GetTopicById($topic);
        $row = mysql_fetch_assoc($result);
        $topic_name_en = $row['name_en'];
        $topic_name_ch = $row['name_ch'];
        $topic_name_pinyin = $row['name_pinyin'];

        /*
        $query = "SELECT taglist.*, topic_tag_relation.topic_id FROM taglist LEFT JOIN topic_tag_relation ON taglist.id = topic_tag_relation.tag_id ORDER BY `topic_id`";
        $result = mysql_query($query);
        if (!$result) {
            return json_encode("Failed during selecting/joining taglist and topic_tag_relation table.");
        }
        $taglistArray = array();
        while ($row = mysql_fetch_assoc($result)) {
            array_push($taglistArray, array('id'=>$row['id'],'name'=>$row['name'], 'tag'=>$row['tag'], 'color'=>$row['color'], 'topic_id'=>$row['topic_id']) );
        }
        */

        // ------
        $query = "SELECT taglist.*, topic_tag_relation.topic_id FROM taglist LEFT JOIN topic_tag_relation ON taglist.id = topic_tag_relation.tag_id ORDER BY `topic_id`";
        $result = mysql_query($query);
        if (!$result) {
            return json_encode("Failed during selecting/joining taglist and topic_tag_relation table.");
        }

        $tag_intopic = array();
        $tag_others = array();
        $tag_tmp_others = array();
        while ($row = mysql_fetch_assoc($result)) {
            if ($row['topic_id'] == $topic) {
                array_push($tag_intopic, array('id'=>$row['id'],'name'=>$row['name'], 'tag'=>$row['tag'], 'color'=>$row['color'], 'topic_id'=>$row['topic_id']));
            } else {
                array_push($tag_tmp_others, array('id'=>$row['id'],'name'=>$row['name'], 'tag'=>$row['tag'], 'color'=>$row['color'], 'topic_id'=>$row['topic_id']));
            }
        }

        // --- check if there's any duplicated tags in tag_tmp_others. remove the duplicated tags
        $num_others = count($tag_tmp_others);
        for ($i=0; $i < $num_others; $i++) { 
            $cnt = 0;
            for ($j=$i+1; $j < $num_others; $j++) { 
                if ($tag_tmp_others[$i]['tag'] == $tag_tmp_others[$j]['tag']) {
                    break;
                } else {
                    $cnt++;
                }
            }
            if ($cnt == ($num_others-$i-1) ) {
                $row = $tag_tmp_others[$i];
                array_push($tag_others, array('id'=>$row['id'],'name'=>$row['name'], 'tag'=>$row['tag'], 'color'=>$row['color'], 'topic_id'=>$row['topic_id']) );
            }
        }

        // --- remove duplicated tags in tag_others that is duplicated with tags in tag_intopic
        $tag_tmp_others = $tag_others;
        $tag_others = array();
        
        foreach ($tag_tmp_others as $tmp) {
            $cnt = 0;
            foreach ($tag_intopic as $intopic) {
                if ($tmp['tag'] == $intopic['tag']) {
                    break;
                } else {
                    $cnt ++;
                }
            }
            if ($cnt == count($tag_intopic)) {
                // not appear in $tag_intopic
                array_push($tag_others, $tmp);
            }
        }
        
        // -----


        $data = array();
        //$data['taglistArray'] = $taglistArray;
        $data['topic'] = $topic;
        $data['topic_name'] = array('name_en'=>$topic_name_en,'name_ch'=>$topic_name_ch,'name_pinyin'=>$topic_name_pinyin);

        $data['tag_intopic'] = $tag_intopic;
        $data['tag_others'] = $tag_others;

        return $data;
    }


    public function UpdateTagsInTopic($_postdata) {
        $topic_id = $_postdata['topic_id'];
        $tag_ids = json_decode(str_replace('\\', '', $_postdata['ids']));

        // update topic_tag_relation by tags_ids array as `tag_id` and topic_id as `topic_id`
        // --- add new topic_tag_relation ---
        foreach ($tag_ids as $tag_id) {
            $query = "SELECT * FROM topic_tag_relation WHERE tag_id=".$tag_id;
            $result = mysql_query($query);
            if (!$result) {
                echo json_encode("error when select from topic_tag_relation");
            }
            $topic_tag = array();
            $flag = false;
            while ($row = mysql_fetch_assoc($result)) {
                if ($row['topic_id'] == $topic_id) {
                    $flag = true;
                    break;
                }
            }
            if (!$flag) {
                // insert a row into topic_tag_relation table
                $queryUpdate = "INSERT INTO topic_tag_relation (topic_id, tag_id) VALUES (".$topic_id.",".$tag_id.")";
                $resultUpdate = mysql_query($queryUpdate); 
                if (!$resultUpdate) {
                    return json_encode("error when insert topic_tag_relation table");
                }   
            }

        }

        // --- remove tags from this topic ---
        $query = "SELECT * FROM topic_tag_relation WHERE topic_id=".$topic_id;
        $result = mysql_query($query);
        if (!$result) {
            echo json_encode("error when select from topic_tag_relation");
        }

        while ($row = mysql_fetch_assoc($result)) {
            $cnt = 0;
            foreach ($tag_ids as $tag_id) {
                if ($row['tag_id'] == $tag_id) {
                    break;
                } else {
                    $cnt ++;
                }
            }
            $_id = $row['id'];
            if ($cnt == count($tag_ids)) {
                // delete row with (topic_id, tag_ids)
                $queryDelete = "DELETE FROM topic_tag_relation WHERE id=".$_id;
                $resultDelete = mysql_query($queryDelete);
                if (!$resultDelete) {
                    echo json_encode("error when delete from topic_tag_relation");
                }
            }
        }

    

        /*
        $query = "SELECT * FROM topic_tag_relation";
        $result = mysql_query($query);
        if (!$result) {
            echo json_encode("error when select from topic_tag_relation");
        }
        $topic_tag = array();
        while ($row = mysql_fetch_assoc($result)) {
            array_push($topic_tag, array('tag_id'=>$row['tag_id'], 'topic_id'=>$row['topic_id']));
        }


        foreach ($topic_tag as $value) {
            $flag = false;
            foreach ($tag_ids as $tag_id) {
                if ($value['tag_id'] == $tag_id) {
                    //update its topic_id to $topic_id
                    $queryUpdate = "UPDATE topic_tag_relation SET topic_id=".$topic_id." WHERE tag_id=".$tag_id;
                    $resultUpdate = mysql_query($queryUpdate); 
                    if (!$resultUpdate) {
                        return json_encode("error when update topic_tag_relation table");
                    }   
                    $flag = true;
                    break;
                }
            }
            if (!$flag && $value['topic_id'] == $topic_id) {
                // set its topic_id to 0, indicating unsigned
                $queryUpdate = "UPDATE topic_tag_relation SET topic_id=0 WHERE tag_id=".$value['tag_id'];
                $resultUpdate = mysql_query($queryUpdate); 
                if (!$resultUpdate) {
                    return json_encode("error when update topic_tag_relation table");
                }   
            }
        }
        */

    }


    private function GetTaglistByTopicId($topic_id) {
        $taglistArray = array();
        // select taglist ids from topic_tag_relation table
        $query = sprintf("SELECT * FROM `topic_tag_relation` WHERE `topic_id`='%s'", $topic_id);
        $result = mysql_query($query);
        if (!$result) {
            return json_encode("Failed during selecting topic_tag_relation table.");
        }
        $taglist_ids = array();

        while ($row = mysql_fetch_assoc($result)) {
            array_push($taglist_ids, $row['tag_id']);
        }

        // select taglist by tag ids
        foreach ($taglist_ids as $tag_id) {
            $query = sprintf("SELECT * FROM `taglist` WHERE `id`='%s'", $tag_id);
            $result = mysql_query($query);
            if (!$result) {
                echo mysql_error();
                return json_encode("Failed during selecting taglist table.");
            }

            $row = mysql_fetch_assoc($result);
            array_push($taglistArray, array( $row['id'], $row['name'], $row['tag'], $row['color'] ));

        }
        return $taglistArray;
    }

    public function SetTopic($topic) {
        $this->topic = $topic;
    }

    private function GetTopic() {
        return $this->topic;
    }

    private function GetTopiclistArray() {
        $topiclistArray = array();
        $result = $this->GetTopicList();
        while ($row = mysql_fetch_assoc($result)) {
            //array_push($topiclistArray, array('id'=>$row['id'],'name'=>$row['name'],'tag'=>$row['tag']));
            array_push($topiclistArray, array('id'=>$row['id'],'tag'=>$row['tag'],'name_en'=>$row['name_en'],'name_ch'=>$row['name_ch'],'name_pinyin'=>$row['name_pinyin'],));
        }
        return $topiclistArray;
    }


    private function GetTopicTag($topic_id) {
        $result = $this->GetTopicById($topic_id);
        $row = mysql_fetch_assoc($result);
        $tag = $row['tag'];
        return $tag;

    }
    private function GetTopicName($topic_id) {
        $result = $this->GetTopicById($topic_id);
        $row = mysql_fetch_assoc($result);
        //$name = $row['name'];
        $name = array('name_en'=>$row['name_en'], 'name_ch'=>$row['name_ch'], 'name_pinyin'=>$row['name_pinyin']);
        return $name;

    }


    // =========================== 

    // === for manage wordlist ===
    public function EditWordlist() {
        /**
        * EditWordlist shows the wordlist in a new window.
        * User can view each one of the wordlist and edit it, also s/he can create a new wordlist here.
        */

        $result = $this->GetWordlist();
        $wordlistArray = array();
        while ($row = mysql_fetch_assoc($result)) {
            $wordlistArray[$row['id']] = $row['name'];
        }

        $data = array();
        $data['wordlistArray'] = $wordlistArray;
        return $data;
    }


    public function AddNewList($postdata) {
        if ($postdata['text']){ 
            if (get_magic_quotes_gpc()) {
                $name = stripslashes($postdata['text']);
            } else {
                $name = $postdata['text'];
            }

            $query1 = sprintf("INSERT INTO `wordlist` (`name`, `systemName`) VALUES (%s, %s)",
                            $this->GetSQLValueString($name, "text"),
                            $this->GetSQLValueString($this->systemNAME, "text"));
            $result1 = mysql_query($query1);
            file_put_contents( "data/wordlist/".mysql_insert_id().".txt", "(empty now)");
        }
    }  


    public function SaveWordlist($postdata) {

        if ($postdata['text']){
            $date = date('Y_m_d_H_i_s', time());
            if ( file_exists("data/wordlist/".$postdata['filename'].".txt") ) {
                $filename = "data/wordlist/".$postdata['filename']."_".$date.".txt";
                $oldFile = file_get_contents("data/wordlist/".$postdata['filename'].".txt");
                file_put_contents($filename, $oldFile);
            } 
            /*else {
                $filename = "data/wordlist/".$postdata['filename'].".txt";
            }
            */


            if (get_magic_quotes_gpc()) {
                $require = stripslashes($postdata['text']);
            } else {
                $require = $postdata['text'];
            }

            $require = preg_replace("/<br>/u", "<br>", $require);
            file_put_contents("data/wordlist/".$postdata['filename'].".txt", $require);
        }
        /*
        if ($postdata['text']){
            $date = date('Y_m_d_H_i_s', time());
            if ( file_exists("data/wordlist/".$postdata['filename'].".txt") ) {
                $oldFile = file_get_contents("data/wordlist/".$postdata['filename'].".txt");
                file_put_contents("data/wordlist/".$postdata['filename']."_".$date.".txt", $oldFile);
            }
        
            if (get_magic_quotes_gpc()) {
                $require = stripslashes($postdata['text']);
            } else {
                $require = $postdata['text'];
            }

            // $require = preg_replace("/<br>/u", "", $require);
            file_put_contents("data/wordlist/".$postdata['filename'].".txt", $require);
        }
        */
    }


    // =======================================

    private function sortFunction($a,$b) {
        return strlen($b)-strlen($a);
    }

    private function GetSectionId() {

        if (is_numeric($this->section_id)) {
            return $this->section_id;
        } else {
            return json_encode("Error: No section id");
        }
    }
    
    private function GetSectionInfo() {
        $section_id = $this->GetSectionId();
        if (!is_numeric($section_id)){
            return $section_id;
        }

        $result = $this->GetSectionsById($section_id);

        
        while ($row = mysql_fetch_assoc($result)) {
            $bookId=$row['books_id'];
            $startPage=$row['start_page'];
            $endPage=$row['end_page'];
            $sectionName = $row['name'];
        }

        $data = array();
        $data['bookId'] = $bookId;
        $data['startPage'] = $startPage;
        $data['endPage'] = $endPage;
        $data['sectionName'] = $sectionName;


        return $data;
    }

    private function ParseDataInFile($filename) {
        $text = file_get_contents($filename);
        $xml = simplexml_load_string($text); //or die("Error: Cannot load from xml string");
        if (!$xml) {
            // when file created by section_id, read the plain text from file_get_contents
            return $text;
        }

        $this->topic = (string)$xml->topic; // set topic id

        // get taglist in file
        $taglist_infile = $xml->tagitem;
        $taglistArray = array();
        foreach ($taglist_infile as $row) {
            array_push($taglistArray, array((string)$row->id,(string)$row->name,(string)$row->tag,(string)$row->color ));
        }
        if ($taglistArray) {
            $this->taglist_infile = $taglistArray; 
        }

        // --- get book meta data from file, replaced by SetBookMetaDataBySectionId(), which retrives book meta data from LGService
        /*
        $book_meta = $xml->book;
        $book_metaArray = array();
        foreach ($book_meta as $row) {
            array_push($book_metaArray, array((string)$row->id,(string)$row->name,(string)$row->level1,(string)$row->level2,
                (string)$row->period,(string)$row->dynasty,(string)$row->start_year,(string)$row->end_year,(string)$row->line,
                (string)$row->volume,(string)$row->author,(string)$row->edition,(string)$row->in_jibengujiku,(string)$row->admin_type ));
        }
        if ($book_metaArray) {
            $this->book_meta = $book_metaArray;
        }
        */
        // -----
        // TODO: get section_id, section_name from file
        if ($this->section_id == 0 && isset($xml->section)) {
            if ($xml->section) {
                $this->section_id = (string)$xml->section->id;
                $this->section_name = (string)$xml->section->name;
            }
        }
        // book meta data
        if (!isset($this->book_id) && isset($xml->book)) {
            $this->book_id = (string)$xml->book->id;
            $this->book_name = (string)$xml->book->name;
        }



        $contentString = (string)($xml->text_content->asXML());

        $removed_str = array("<text_content>","</text_content>");
        $new_contentString = str_replace($removed_str, "", $contentString);

        return $new_contentString;
    }


    private function GetSectionContent() {  
        /** This is only been called by SetTextFromLocal().
        */

        $section_id = $this->GetSectionId();
        $section_info = $this->GetSectionInfo();

        $bookId = $section_info['bookId'];
        $startPage = $section_info['startPage'];
        $endPage = $section_info['endPage'];

        $contentString="";
        $data_path = $this->GetDataPath();
        if ( file_exists($data_path."parsing_files/".$section_id.".txt") ) {
            $filename = $data_path."parsing_files/".$section_id.".txt";
            
            // --- parsing meta data
            $stringInput = $this->ParseDataInFile($filename);
            // ----

            // if the text is from file system
            $stringInput = preg_replace("/ /u", "○", $stringInput);
            $stringInput = preg_replace("/\n/u", "<br>", $stringInput);
            $stringInput = preg_replace("/【(.*?)】/u", "【<a href=\"review_index_xml_images.php?books_id=".$bookId."&pages=\\1&entry=0\" target=\"_bookImg\">\\1</a>】", $stringInput);
            
            $this->branch_id = 1;   // testing at local

        } else {
            $query = sprintf("SELECT `content`, `line`, `books_id` FROM `contents` WHERE `books_id`=\"%s\" AND `line`>=%d AND `line`<=%d", $bookId, $startPage, $endPage);
            $result = mysql_query($query);
            if (!$result) {
                return json_encode("Failed during selecting content table.");
            }
            while ($row = mysql_fetch_assoc($result)) {
                $contentString.="【".$row['line']."】".$row['content']."\n";
            }
           
            // the text is from database
            $stringInput = $contentString;
            $stringInput = preg_replace("/<(.*?)>/u", "○", $stringInput);
            $stringInput = preg_replace("/ /u", "○", $stringInput);
            $stringInput = preg_replace("/\n/u", "<br>", $stringInput);
            $stringInput = preg_replace("/【(.*?)】/u", "【<a href=\"review_index_xml_images.php?books_id=".$bookId."&pages=\\1&entry=0\" target=\"_bookImg\">\\1</a>】", $stringInput);
        }

        /*
        // get book_meta from books table in db on localhost
        $book_meta = array();
        $books_result = $this->GetBooksById($bookId);
        while ($row = mysql_fetch_assoc($books_result)) {
            array_push($book_meta, array($row['id'],$row['name'],$row['author'],(string)$row['start_year'],(string)$row['line'],(string)$row['dynasty']));
                                    // use 'start_year' as year, 'line' is pagenumber
        }
        $this->book_meta = $book_meta;
        */

        return $stringInput;
    }
    
    private function GetDataPath() {
        return getcwd()."/data/"; // get the current file path, which is getcwd(), and concatenate with "/data/"
    }

    private function GetTaglistArray() {
        $taglistArray = array();
        $result = $this->GetTaglist();
        while ($row = mysql_fetch_assoc($result)) {
            array_push($taglistArray, array( $row['id'], $row['name'], $row['tag'], $row['color'] ));
        }

        return $taglistArray;
    }

    private function GetWordlistArray() {
        $wordlistArray="";
        $result = $this->GetWordlist();
        while ($row = mysql_fetch_assoc($result)) {
            $listString = file_get_contents("data/wordlist/".$row['id'].".txt");
            $listString = preg_replace("/<div>/u", "\n", $listString);
            $listString = preg_replace("/<\/div>/u", "", $listString);
            $listString = preg_replace("/<span(.*?)>/u", "", $listString);
            $listString = preg_replace("/<\/span>/u", "", $listString);
            //$listString = preg_replace("/\n/u", "|", $listString);
            
            $wordlistArray2 = explode( "\n", $listString );
            //usort($wordlistArray2,'sortFunction');
            foreach ( $wordlistArray2 as $index=>$value ) {
                $wordlistArray2[$index] = implode("○?", preg_split("/(?<!^)(?!$)/u", $value));
            }
            foreach ( $wordlistArray2 as $index=>$value ) {
                if ($value=="") unset($wordlistArray2[$index]);
                
            }
            $listString = implode("|", $wordlistArray2);
            
            if ( $listString[0]=="|" ) $listString = substr($listString, 1);
            $wordlistArray[] = array( $row['id'], $row['name'], $listString );
        }


        return $wordlistArray;

    }

    private function GetBooksInfo($bookId) {
        $result = $this->GetSectionsById($bookId);
        while ($row = mysql_fetch_assoc($result)) {
            $bookName = $row['name'];
        }

        $data = array();
        $data['bookName'] = $bookName;

        return $data;
    }

    
}



?>