19bd7d62fSAndreas Gohr<?php 29bd7d62fSAndreas Gohr 39bd7d62fSAndreas Gohrnamespace dokuwiki\Search\Index; 49bd7d62fSAndreas Gohr 59bd7d62fSAndreas Gohruse dokuwiki\Search\Exception\IndexWriteException; 69bd7d62fSAndreas Gohr 79bd7d62fSAndreas Gohr/** 89bd7d62fSAndreas Gohr * Access to a single index file 99bd7d62fSAndreas Gohr * 109bd7d62fSAndreas Gohr * Access using this class always happens by loading the full index into memory. 119bd7d62fSAndreas Gohr * All modifications need to be explicitly made permanent using the save() method. 129bd7d62fSAndreas Gohr * Should be used for small indexes that receive many changes at once. 139bd7d62fSAndreas Gohr */ 149bd7d62fSAndreas Gohrclass MemoryIndex extends AbstractIndex 159bd7d62fSAndreas Gohr{ 169bd7d62fSAndreas Gohr 179bd7d62fSAndreas Gohr /** @var string the raw data lines of the index, no newlines */ 189bd7d62fSAndreas Gohr protected $data; 199bd7d62fSAndreas Gohr 209bd7d62fSAndreas Gohr /** 219bd7d62fSAndreas Gohr * Loads the full contents of the index into memory 229bd7d62fSAndreas Gohr * 239bd7d62fSAndreas Gohr * @inheritdoc 249bd7d62fSAndreas Gohr */ 259bd7d62fSAndreas Gohr public function __construct($idx, $suffix = '') 269bd7d62fSAndreas Gohr { 279bd7d62fSAndreas Gohr parent::__construct($idx, $suffix); 289bd7d62fSAndreas Gohr 299bd7d62fSAndreas Gohr $this->data = []; 309bd7d62fSAndreas Gohr if (!file_exists($this->filename)) return; 319bd7d62fSAndreas Gohr $this->data = file($this->filename, FILE_IGNORE_NEW_LINES); 329bd7d62fSAndreas Gohr 339bd7d62fSAndreas Gohr } 349bd7d62fSAndreas Gohr 359bd7d62fSAndreas Gohr /** @inheritdoc */ 369bd7d62fSAndreas Gohr public function changeRow($rid, $value) 379bd7d62fSAndreas Gohr { 389bd7d62fSAndreas Gohr if ($rid > count($this->data)) { 399bd7d62fSAndreas Gohr $this->data = array_pad($this->data, $rid, ''); 409bd7d62fSAndreas Gohr } 419bd7d62fSAndreas Gohr $this->data[$rid] = $value; 429bd7d62fSAndreas Gohr } 439bd7d62fSAndreas Gohr 449bd7d62fSAndreas Gohr /** @inheritdoc */ 459bd7d62fSAndreas Gohr public function retrieveRow($rid) 469bd7d62fSAndreas Gohr { 479bd7d62fSAndreas Gohr if (isset($this->data[$rid])) return $this->data[$rid]; 48*dec26820SAndreas Gohr $this->changeRow($rid, ''); // add to index 499bd7d62fSAndreas Gohr return ''; 509bd7d62fSAndreas Gohr } 519bd7d62fSAndreas Gohr 52d6396b6dSAndreas Gohr /** @inheritdoc */ 538ed35011SAndreas Gohr public function getRowIDs($values) 54d6396b6dSAndreas Gohr { 55d6396b6dSAndreas Gohr $values = array_map('trim', $values); 56d6396b6dSAndreas Gohr $values = array_fill_keys($values, 1); // easier access as associative array 57d6396b6dSAndreas Gohr 58d6396b6dSAndreas Gohr $result = []; 59d6396b6dSAndreas Gohr $count = count($this->data); 60d6396b6dSAndreas Gohr for ($ln = 0; $ln < $count; $ln++) { 61d6396b6dSAndreas Gohr $line = $this->data[$ln]; 62d6396b6dSAndreas Gohr if (isset($values[$line])) { 63d6396b6dSAndreas Gohr $result[$line] = $ln; 64d6396b6dSAndreas Gohr unset($values[$line]); 65d6396b6dSAndreas Gohr } 66d6396b6dSAndreas Gohr } 67d6396b6dSAndreas Gohr 68d6396b6dSAndreas Gohr // if there are still values, they have not been found and will be appended 69d6396b6dSAndreas Gohr foreach (array_keys($values) as $value) { 70d6396b6dSAndreas Gohr $this->data[] = $value; 71d6396b6dSAndreas Gohr $result[$value] = $ln++; 72d6396b6dSAndreas Gohr } 73d6396b6dSAndreas Gohr 74d6396b6dSAndreas Gohr return $result; 75d6396b6dSAndreas Gohr } 76d6396b6dSAndreas Gohr 779bd7d62fSAndreas Gohr /** 789bd7d62fSAndreas Gohr * Save the changed index back to its file 799bd7d62fSAndreas Gohr * 809bd7d62fSAndreas Gohr * @throws IndexWriteException 81*dec26820SAndreas Gohr * @fixme store a dirty marker and only save when needed 829bd7d62fSAndreas Gohr */ 839bd7d62fSAndreas Gohr public function save() 849bd7d62fSAndreas Gohr { 859bd7d62fSAndreas Gohr global $conf; 869bd7d62fSAndreas Gohr 879bd7d62fSAndreas Gohr $tempname = $this->filename . '.tmp'; 889bd7d62fSAndreas Gohr 899bd7d62fSAndreas Gohr $fh = @fopen($tempname, 'w'); 909bd7d62fSAndreas Gohr if (!$fh) { 919bd7d62fSAndreas Gohr throw new IndexWriteException("Failed to write $tempname"); 929bd7d62fSAndreas Gohr } 939bd7d62fSAndreas Gohr fwrite($fh, implode("\n", $this->data)); 94*dec26820SAndreas Gohr if (count($this->data)) { 959bd7d62fSAndreas Gohr fwrite($fh, "\n"); 969bd7d62fSAndreas Gohr } 979bd7d62fSAndreas Gohr fclose($fh); 989bd7d62fSAndreas Gohr 999bd7d62fSAndreas Gohr if ($conf['fperm']) { 1009bd7d62fSAndreas Gohr chmod($tempname, $conf['fperm']); 1019bd7d62fSAndreas Gohr } 1029bd7d62fSAndreas Gohr 1039bd7d62fSAndreas Gohr if (!io_rename($tempname, $this->filename)) { 1049bd7d62fSAndreas Gohr throw new IndexWriteException("Failed to write {$this->filename}"); 1059bd7d62fSAndreas Gohr } 1069bd7d62fSAndreas Gohr } 1079bd7d62fSAndreas Gohr 1089bd7d62fSAndreas Gohr} 109