db = new Database(); $this->store = Store::getInstance('', $phpUnit); } /** * Deletes the record id=$recordId from table $form[F_TABLE_NAME]. * If the table has a column named COLUMN_PATH_FILE_NAME and the value of that specific record column points * to a file: delete such a file if their are no other records in the same table which also have a reference to * that file. * * @param string $tableName * @param integer $recordId * * @throws CodeException * @throws DbException * @throws UserFormException */ public function process($tableName, $recordId) { $msg = array(); if ($tableName === false || $tableName === '') { throw new CodeException('Missing table name', ERROR_MISSING_TABLE_NAME); } if ($recordId === 0 || $recordId === '') { throw new CodeException('Invalid record id', ERROR_MISSING_RECORD_ID); } // Take care the necessary target directories exist. $cwd = getcwd(); $sitePath = $this->store->getVar(SYSTEM_SITE_PATH, STORE_SYSTEM); if ($cwd === false || $sitePath === false || !chdir($sitePath)) { throw new UserFormException("getcwd() failed or SITE_PATH undefined or chdir('$sitePath') failed.", ERROR_IO_CHDIR); } // Read record first. $row = $this->db->sql("SELECT * FROM $tableName WHERE id=?", ROW_EXPECT_0_1, [$recordId]); if (count($row) > 0) { $this->deleteReferencedFiles($row, $tableName); $this->db->sql("DELETE FROM $tableName WHERE id =? LIMIT 1", ROW_REGULAR, [$recordId]); } else { throw new UserFormException("Record $recordId not found in table '$tableName'.", ERROR_RECORD_NOT_FOUND); } chdir($cwd); } /** * Iterates over array $row and searches for column names with substring COLUMN_PATH_FILE_NAME. * For any found, check if it references a writeable file. * If yes: check if there are other records (same table, same column) which references the same file. * If no: delete the file * If yes: do nothing, continue with the next column. * If no: do nothing, continue with the next column. * * @param array $row * @param $tableName * * @throws CodeException * @throws DbException * @throws UserFormException */ private function deleteReferencedFiles(array $row, $tableName) { foreach ($row AS $key => $file) { if (false === strpos($key, COLUMN_PATH_FILE_NAME)) { continue; } // check if there is a file referenced in the record which have to be deleted too. if ($file !== '' && is_writable($file)) { // check if there are other records referencing the same file: do not delete the file now. // This check won't find duplicates, if they are spread over different columns or tables. $samePathFileName = $this->db->sql("SELECT COUNT(id) AS cnt FROM $tableName WHERE $key LIKE ?", ROW_EXPECT_1, [$file]); if ($samePathFileName['cnt'] === 1) { if (!unlink($file)) { throw new UserFormException("Error deleting file: $file", ERROR_IO_UNLINK); } } } } } }