1<?php 2 3namespace dokuwiki\Search\Index; 4 5use dokuwiki\Search\Exception\IndexWriteException; 6 7/** 8 * Access to a single index file 9 * 10 * Access using this class always happens by loading the full index into memory. 11 * All modifications need to be explicitly made permanent using the save() method. 12 * Should be used for small indexes that receive many changes at once. 13 */ 14class MemoryIndex extends AbstractIndex 15{ 16 17 /** @var string the raw data lines of the index, no newlines */ 18 protected $data; 19 20 /** 21 * Loads the full contents of the index into memory 22 * 23 * @inheritdoc 24 */ 25 public function __construct($idx, $suffix = '') 26 { 27 parent::__construct($idx, $suffix); 28 29 $this->data = []; 30 if (!file_exists($this->filename)) return; 31 $this->data = file($this->filename, FILE_IGNORE_NEW_LINES); 32 33 } 34 35 /** @inheritdoc */ 36 public function changeRow($rid, $value) 37 { 38 if ($rid > count($this->data)) { 39 $this->data = array_pad($this->data, $rid, ''); 40 } 41 $this->data[$rid] = $value; 42 } 43 44 /** @inheritdoc */ 45 public function retrieveRow($rid) 46 { 47 if (isset($this->data[$rid])) return $this->data[$rid]; 48 return ''; 49 } 50 51 /** 52 * Save the changed index back to its file 53 * 54 * @throws IndexWriteException 55 */ 56 public function save() 57 { 58 global $conf; 59 60 $tempname = $this->filename . '.tmp'; 61 62 $fh = @fopen($tempname, 'w'); 63 if (!$fh) { 64 throw new IndexWriteException("Failed to write $tempname"); 65 } 66 fwrite($fh, implode("\n", $this->data)); 67 if (!empty($lines)) { 68 fwrite($fh, "\n"); 69 } 70 fclose($fh); 71 72 if ($conf['fperm']) { 73 chmod($tempname, $conf['fperm']); 74 } 75 76 if (!io_rename($tempname, $this->filename)) { 77 throw new IndexWriteException("Failed to write {$this->filename}"); 78 } 79 } 80 81} 82