<?php
/**
 * Copyright (C) 2010  Wardiyono (wynerst@gmail.com), Arie Nugraha (dicarve@yahoo.com)
 *
 * This program 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.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

// be sure that this file not accessed directly
if (INDEX_AUTH != 1) {
    die("can not access this file directly");
}

class biblio_indexer
{
	public $total_records = 0;
	public $indexed = 0;
	public $failed = array();
	public $errors = array();
	public $indexing_time = 0;
	private $exclude = array();
	private $obj_db = false;
	private $verbose = false;
	private $max_indexed = 1000000;
	private $index_type = 'search_biblio';

	public function __construct($obj_db, $bool_verbose = false) {
		global $sysconf;
		if ($sysconf['index']['type'] == 'mongodb') {
	    if (!class_exists('MongoClient')) {
	      throw new Exception('PHP Mongodb extension library is not installed yet!');
	    } else {
				$this->index_type = 'nosql';
	      $Mongo = new MongoClient();
				// select database
				$this->biblio = $Mongo->slims->biblio;
			}
		}
		$this->obj_db = $obj_db;
		$this->verbose = $bool_verbose;
	}


	/**
	 * Creating full index database of bibliographic records
	 * @param	boolean		$bool_empty_first: Emptying current index first
	 * @return	void
	 */
	public function createFullIndex($bool_empty_first = false) {
		if ($bool_empty_first) {
			$this->emptyingIndex();
		}
		$bib_sql = 'SELECT biblio_id FROM biblio ORDER BY biblio_id ASC LIMIT '.$this->max_indexed;
		// query
		$rec_bib = $this->obj_db->query($bib_sql);
		$r = 0;
		if ($rec_bib->num_rows > 0) {
			// start time counter
			$_start = function_exists('microtime')?microtime(true):time();
			$this->total_records = $rec_bib->num_rows;
			// loop records and create index
			while ($rb_id = $rec_bib->fetch_row()) {
				$biblio_id = $rb_id[0];
				$index = $this->makeIndex($biblio_id);
			}
			// get end time
			$_end = function_exists('microtime')?microtime(true):time();
			$this->indexing_time = $_end-$_start;
		}
	}


	/**
	 * Emptying index table
	 * @return	boolean		true on success, false otherwise
	 */
	public function emptyingIndex() {
		@$this->obj_db->query('TRUNCATE TABLE `search_biblio`');
		if ($this->obj_db->errno) {
			$this->errors[] = $this->obj_db->error;
			return false;
		}
		return true;
	}


	/**
	 * Make index for one bibliographic record
	 * @param	int		$int_biblio_id: ID of biblio to index
	 * @return	boolean	false on Failed, true otherwise
	 */
	public function makeIndex($int_biblio_id) {
		$bib_sql = 'SELECT b.biblio_id, b.title, b.edition, b.publish_year, b.notes, b.series_title, b.classification, b.spec_detail_info,
			g.gmd_name AS `gmd`, pb.publisher_name AS `publisher`, pl.place_name AS `publish_place`, b.isbn_issn,
			lg.language_name AS `language`, b.call_number, b.opac_hide, b.promoted, b.labels, b.`collation`, b.image, b.input_date, b.last_update
			FROM biblio AS b
			LEFT JOIN mst_gmd AS g ON b.gmd_id = g.gmd_id
			LEFT JOIN mst_publisher AS pb ON b.publisher_id = pb.publisher_id
			LEFT JOIN mst_place AS pl ON b.publish_place_id = pl.place_id
			LEFT JOIN mst_language AS lg ON b.language_id = lg.language_id WHERE b.biblio_id='.$int_biblio_id;
		// query
		$rec_bib = $this->obj_db->query($bib_sql);

		if ($rec_bib->num_rows < 1) {
			return false;
		} else {
			$rb_id = $rec_bib->fetch_assoc();
		}

		if ($this->verbose) { echo 'Indexing: '.$rb_id['title'].'...'; }
		$data['biblio_id'] = $int_biblio_id;

		/* GMD , Title, Year  */
		$data['title'] = $this->obj_db->escape_string($rb_id['title']);
		$data['edition'] = $this->obj_db->escape_string($rb_id['edition']);
		$data['gmd'] = $this->obj_db->escape_string($rb_id['gmd']);
		$data['publisher'] = $this->obj_db->escape_string($rb_id['publisher']);
		$data['publish_place'] = $this->obj_db->escape_string($rb_id['publish_place']);
		$data['isbn_issn'] = $this->obj_db->escape_string($rb_id['isbn_issn']);
		$data['language'] = $this->obj_db->escape_string($rb_id['language']);
		$data['publish_year'] = $rb_id['publish_year'];
		$data['classification'] = $this->obj_db->escape_string($rb_id['classification']);
		$data['spec_detail_info'] = $this->obj_db->escape_string($rb_id['spec_detail_info']);
		$data['call_number'] = $this->obj_db->escape_string($rb_id['call_number']);
		$data['opac_hide'] = $rb_id['opac_hide'];
		$data['promoted'] = $rb_id['promoted'];
		if ($rb_id['labels']) {
		    $data['labels'] = $rb_id['labels'];
		} else {
		    $data['labels'] = 'literal{NULL}';
		}
		$data['collation'] = $this->obj_db->escape_string($rb_id['collation']);
		$data['image'] = $this->obj_db->escape_string($rb_id['image']);
		$data['input_date'] = $rb_id['input_date'];
		$data['last_update'] = $rb_id['last_update'];
		if ($rb_id['notes'] != '') {
		    $data['notes'] = trim($this->obj_db->escape_string(strip_tags($rb_id['notes'], '<br><p><div><span><i><em><strong><b><code>')));
		}
		if ($rb_id['series_title'] != '') {
		    $data['series_title'] = $this->obj_db->escape_string($rb_id['series_title']);
		}

		/* author  */
		$au_all = '';
		$au_sql = 'SELECT ba.biblio_id, ba.level, au.author_name AS `name`, au.authority_type AS `type`
			FROM biblio_author AS ba LEFT JOIN mst_author AS au ON ba.author_id = au.author_id
			WHERE ba.biblio_id ='. $int_biblio_id;
		$au_id = $this->obj_db->query($au_sql);
		while($rs_au = $au_id->fetch_assoc()) {
			$au_all .= $rs_au['name'] . ' - ';
		}
		if ($au_all !='') {
			$au_all = substr_replace($au_all, '', -3);
			$data['author'] = $this->obj_db->escape_string($au_all);
		}

		/* subject  */
		$topic_all = '';
		$topic_sql = 'SELECT bt.biblio_id, bt.level, tp.topic, tp.topic_type AS `type`
			FROM biblio_topic AS bt LEFT JOIN mst_topic AS tp ON bt.topic_id = tp.topic_id
			WHERE bt.biblio_id ='. $int_biblio_id;
		$topic_id = $this->obj_db->query($topic_sql);
		while ($rs_topic = $topic_id->fetch_assoc()) {
			$topic_all .= $rs_topic['topic'] . ' - ';
		}
		if ($topic_all != '') {
			$topic_all = substr_replace($topic_all, '', -3);
			$data['topic'] = $this->obj_db->escape_string($topic_all);
		}

		/* items */
		$barcode_all = '';
		$barcode_sql = 'SELECT i.item_code FROM item AS i WHERE i.biblio_id ='. $int_biblio_id;
		$barcode_q = $this->obj_db->query($barcode_sql);
		while ($rs_barcode = $barcode_q->fetch_assoc()) {
			$barcode_all .= $rs_barcode['item_code'] . ' - ';
		}
		if ($barcode_all != '') {
			$barcode_all = substr_replace($barcode_all, '', -3);
			$data['items'] = $barcode_all;
		}

		/* location  */
		$loc_all = '';
		$loc_sql = 'SELECT i.biblio_id, l.location_name AS `name`
			FROM item AS i LEFT JOIN mst_location AS l ON i.location_id = l.location_id
			WHERE i.biblio_id ='. $int_biblio_id;
		$loc_id = $this->obj_db->query($loc_sql);
		$_prev_loc = '';
		while ($rs_loc = $loc_id->fetch_assoc()) {
			if ($rs_loc['name'] == $_prev_loc) { continue; }
			$loc_all .= $rs_loc['name'] . ' - ';
			$_prev_loc = $rs_loc['name'];
		}
		if ($loc_all != '') {
			$loc_all = substr_replace($loc_all, '', -3);
			$data['location'] = $this->obj_db->escape_string($loc_all);
		}

		/* collection types */
		$colltype_all = '';
		$colltype_sql = 'SELECT ct.coll_type_name AS `name`
			FROM item AS i LEFT JOIN mst_coll_type AS ct ON i.coll_type_id = ct.coll_type_id
			WHERE i.biblio_id ='. $int_biblio_id;
		$colltype_q = $this->obj_db->query($colltype_sql);
		$_prev_colltype = '';
		while ($rs_colltype = $colltype_q->fetch_assoc()) {
			if ($rs_colltype['name'] == $_prev_colltype) { continue; }
			$colltype_all .= $rs_colltype['name'] . ' - ';
			$_prev_colltype = $rs_colltype['name'];
		}
		if ($colltype_all != '') {
			$colltype_all = substr_replace($colltype_all, '', -3);
			$data['collection_types'] = $this->obj_db->escape_string($colltype_all);
		}

    if ($this->index_type == 'nosql') {
      $this->biblio->insert($data);
			// create index
			$this->biblio->ensureIndex(array('title' => 1, 'author' => 1, 'topic' => 1));
			if ($this->verbose) { echo " indexed\n"; }
			$this->indexed++;
		} else {
		  /*  SQL operation object  */
		  $sql_op = new simbio_dbop($this->obj_db);
		  /*  Insert all variable  */
		  if ($sql_op->insert('search_biblio', $data)) {
		  	if ($this->verbose) { echo " indexed\n"; }
		  	$this->indexed++;
		  } else {
		  	if ($this->verbose) { echo " FAILED! (Error: '.$sql_op->error.')\n"; }
		  	$this->failed[] = $int_biblio_id;
		  	// line below is for debugging purpose only
		  	// echo '<div>'.$sql_op->error.'</div>';
		  }
		}

		return true;
	}


	/**
	 * Update index
	 *
	 * @return	void
	 */
	public function updateFullIndex() {
		$bib_sql = 'SELECT b.biblio_id FROM biblio AS b
			LEFT JOIN search_biblio AS sb ON b.biblio_id = sb.biblio_id
			WHERE sb.biblio_id is NULL ORDER BY b.biblio_id LIMIT '.$this->max_indexed;
		// query
		$rec_bib = $this->obj_db->query($bib_sql);
		$r = 0;
		if ($rec_bib->num_rows > 0) {
			// start time counter
			$_start = function_exists('microtime')?microtime(true):time();
			$this->total_records = $rec_bib->num_rows;
			while ($rb_id = $rec_bib->fetch_row()) {
				$biblio_id = $rb_id[0];
				$index = $this->makeIndex($biblio_id);
			}
			// end time
			$_end = function_exists('microtime')?microtime(true):time();
			$this->indexing_time = $_end-$_start;
		}
	}
}
