Initial import
This commit is contained in:
@@ -0,0 +1,561 @@
|
||||
<?php
|
||||
|
||||
class DocumentController {
|
||||
|
||||
public static function browse($pid = 0) {
|
||||
|
||||
$product = new Product($pid);
|
||||
|
||||
return blade("documents", ["product" => $product]);
|
||||
}
|
||||
|
||||
public static function show($id) {
|
||||
$doc = new Document($id);
|
||||
$doc->load();
|
||||
|
||||
return blade("document", [
|
||||
"doc" => $doc
|
||||
]);
|
||||
}
|
||||
|
||||
public static function api_get($id) {
|
||||
return new Document($id);
|
||||
}
|
||||
|
||||
public static function api_set($id) {
|
||||
$doc = new Document($id);
|
||||
if ($doc->valid()) {
|
||||
foreach ($_POST as $k=>$v) {
|
||||
if ($k != "products") {
|
||||
$doc->$k = trim($v);
|
||||
}
|
||||
}
|
||||
$doc->save();
|
||||
|
||||
$pids = explode(",", $_POST['products']);
|
||||
|
||||
$dpl = DocProduct::find([["document", "=", $id]])->all();;
|
||||
|
||||
foreach ($dpl as $dp) {
|
||||
$e = array_search($dp->product, $pids);
|
||||
if ($e !== false) {
|
||||
unset($pids[$e]);
|
||||
continue;
|
||||
}
|
||||
$dp->delete();
|
||||
}
|
||||
|
||||
foreach ($pids as $pid) {
|
||||
$dp = new DocProduct;
|
||||
$dp->document = $id;
|
||||
$dp->product = $pid;
|
||||
$dp->save();
|
||||
}
|
||||
|
||||
$doc->cache_invalidate("products");
|
||||
|
||||
}
|
||||
return $doc;
|
||||
}
|
||||
|
||||
public static function api_get_products($id) {
|
||||
$doc = new Document($id);
|
||||
return $doc->products;
|
||||
}
|
||||
|
||||
public static function api_move($id) {
|
||||
$doc = new Document($id);
|
||||
$from = $_POST['from'];
|
||||
$to = $_POST['to'];
|
||||
|
||||
$dp = DocProduct([["document", "=", $id], ["product", "=", $from]])->first();
|
||||
if ($dp) {
|
||||
$dp->product = $to;
|
||||
$dp->save();
|
||||
}
|
||||
|
||||
$doc->cache_invalidate("products");
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
public static function del_docproduct($doc, $prod) {
|
||||
$dp = DocProduct::find([["document", "=", $doc], ["product", "=", $prod]])->first();
|
||||
if ($dp) {
|
||||
$dp->delete();
|
||||
}
|
||||
return back();
|
||||
}
|
||||
|
||||
public static function get_by_id($id) {
|
||||
return Document::find([["internal_id", "=", trim($id)]])->first();
|
||||
}
|
||||
|
||||
public static function api_merge($id) {
|
||||
$from = new Document($id);
|
||||
$to = new Document($_POST['to']);
|
||||
|
||||
if ($from->id == $to->id) return [];
|
||||
|
||||
if ($from && $to) {
|
||||
$revs = Revision::find([["document", "=", $from->id]]);
|
||||
for ($rev = $revs->first(); $rev = $revs->next(); ) {
|
||||
$rev->document = $to->id;
|
||||
$rev->save();
|
||||
}
|
||||
|
||||
$from->delete();
|
||||
}
|
||||
return new Document($to->id); // Force refresh
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static function api_drag_drop($_request) {
|
||||
$src_id = $_request->post("src_id");
|
||||
$dst_id = $_request->post("dst_id");
|
||||
|
||||
$src_type = $_request->post("src_type");
|
||||
$dst_type = $_request->post("dst_type");
|
||||
|
||||
$src_extra = $_request->post("src_extra");
|
||||
$dst_extra = $_request->post("dst_extra");
|
||||
|
||||
$copy = $_request->post("copy") == "true";
|
||||
|
||||
if (($src_type == "document") && ($dst_type == "document")) {
|
||||
// Merge src into dst
|
||||
$src = new Document($src_id);
|
||||
$dst = new Document($dst_id);
|
||||
|
||||
if ($src->id == $dst->id) return [];
|
||||
|
||||
foreach ($src->revisions as $r) {
|
||||
$r->document = $dst->id;
|
||||
$r->save();
|
||||
}
|
||||
|
||||
$src->delete();
|
||||
$dst->cache_invalidate("revisions");
|
||||
}
|
||||
|
||||
if (($src_type == "document") && ($dst_type == "product")) {
|
||||
|
||||
if ($copy) {
|
||||
$dp = new DocProduct();
|
||||
$dp->document = $src_id;
|
||||
$dp->product = $dst_id;
|
||||
$dp->save();
|
||||
} else {
|
||||
|
||||
// Move document into product
|
||||
$dpl = DocProduct::find([["document", "=", $src_id], ["product", "=", $src_extra]])->all();
|
||||
foreach ($dpl as $dp) {
|
||||
$dp->product = $dst_id;
|
||||
$dp->save();
|
||||
}
|
||||
$prod = new Product($src_extra);
|
||||
$prod->cache_invalidate("documents");
|
||||
}
|
||||
$doc = new Document($src_id);
|
||||
$doc->cache_invalidate("products");
|
||||
$prod = new Product($dst_id);
|
||||
$prod->cache_invalidate("documents");
|
||||
}
|
||||
|
||||
if (($src_type == "product") && ($dst_type == "product")) {
|
||||
|
||||
if ($src_id == $dst_id) return [];
|
||||
// Move product into product
|
||||
$sp = new Product($src_id);
|
||||
$dp = new Product($dst_id);
|
||||
$sp->parent = $dp->id;
|
||||
$sp->save();
|
||||
$sp->cache_invalidate("parent");
|
||||
$sp->cache_invalidate("children");
|
||||
$dp->cache_invalidate("parent");
|
||||
$dp->cache_invalidate("children");
|
||||
}
|
||||
|
||||
|
||||
return [200, ["didit" => "true"]];
|
||||
}
|
||||
|
||||
public static function merge($id) {
|
||||
|
||||
$doc = new Document($id);
|
||||
|
||||
$proc = new Process("pdftk");
|
||||
|
||||
foreach ($doc->revisions as $rev) {
|
||||
$proc->arg($rev->path() . "/doc.pdf");
|
||||
}
|
||||
|
||||
$nr = new Revision;
|
||||
$nr->document = $doc->id;
|
||||
$nr->revno = "NEW";
|
||||
$nr->save();
|
||||
|
||||
|
||||
$out = new File($nr->path() . "/doc.pdf");
|
||||
$out->parent()->mkdir();
|
||||
|
||||
$proc->arg("output");
|
||||
$proc->arg((string)$out);
|
||||
$r = $proc->execute();
|
||||
|
||||
if ($r != 0) {
|
||||
print("<pre>");
|
||||
print_r($proc->stderr());
|
||||
print("</pre>");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return redirect("/document/" . $doc->id);
|
||||
}
|
||||
|
||||
public static function create_overview($id, $move) {
|
||||
|
||||
$job = new GeminiJob($id, "document:$id");
|
||||
$job->move = ($move == "move");
|
||||
$jobid = $job->queue();
|
||||
flash("success", "Job queued as ID " . $jobid);
|
||||
|
||||
return redirect("/document/" . $id);
|
||||
}
|
||||
|
||||
public static function api_get_title_fragment($_request) {
|
||||
$q = $_request->post("title");
|
||||
$db = DB::getInstance();
|
||||
$q1 = $db->query("
|
||||
SELECT
|
||||
DISTINCT title
|
||||
FROM (
|
||||
SELECT
|
||||
DISTINCT title
|
||||
FROM
|
||||
document
|
||||
WHERE
|
||||
title LIKE :s
|
||||
UNION SELECT
|
||||
DISTINCT subtitle AS title
|
||||
FROM
|
||||
document
|
||||
WHERE
|
||||
subtitle LIKE :s
|
||||
UNION SELECT
|
||||
DISTINCT subsubtitle AS title
|
||||
FROM
|
||||
document
|
||||
WHERE subsubtitle LIKE :s
|
||||
) AS DERIVED", ["s" => $q . "%"]);
|
||||
$o = $db->all($q1);
|
||||
|
||||
if ($o->count() == 0) {
|
||||
return [404, "Not Found"];
|
||||
}
|
||||
if ($o->count() != 1) {
|
||||
return [413, "Content Too Large"];
|
||||
}
|
||||
return $o[0]->title;
|
||||
}
|
||||
|
||||
public static function separate($id) {
|
||||
|
||||
$doc = new Document($id);
|
||||
$firstprod = $doc->products[0];
|
||||
|
||||
$count = 0;
|
||||
|
||||
foreach ($doc->revisions as $rev) {
|
||||
$count++;
|
||||
if ($count == 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$newdoc = $doc->duplicate();
|
||||
$newdoc->subsubtitle .= " - $count";
|
||||
$rev->document = $newdoc->id;
|
||||
$rev->save();
|
||||
}
|
||||
|
||||
|
||||
return redirect("/documents/" . $firstprod);
|
||||
}
|
||||
|
||||
public static function api_get_metadata($id) {
|
||||
return DocMeta::find([["document", "=", $id]])->orderBy("metadata")->all();
|
||||
}
|
||||
|
||||
public static function api_new_metadata($_request, $id) {
|
||||
$doc = new Document($id);
|
||||
$doc->set_metadata($_request->put("item_id"), "");
|
||||
return DocMeta::find([["document", "=", $id]])->orderBy("metadata")->all();
|
||||
}
|
||||
|
||||
public static function api_set_metadata($_request, $id, $metadata) {
|
||||
$doc = new Document($id);
|
||||
$doc->set_metadata($metadata, $_request->post('data'));
|
||||
return DocMeta::find([["document", "=", $id]])->orderBy("metadata")->all();
|
||||
}
|
||||
|
||||
public static function api_delete_metadata($id, $metadata) {
|
||||
$doc = new Document($id);
|
||||
$doc->remove_metadata($metadata);
|
||||
return DocMeta::find([["document", "=", $id]])->orderBy("metadata")->all();
|
||||
}
|
||||
|
||||
public static function api_available_metadata($id) {
|
||||
$exist = DocMeta::find([["document", "=", $id]])->orderBy("metadata")->all();
|
||||
$metas = MetaType::find()->all();
|
||||
|
||||
|
||||
$out = new Collection();
|
||||
|
||||
foreach ($metas as $meta) {
|
||||
$e = false;
|
||||
foreach ($exist as $ex) {
|
||||
if ($ex->metadata == $meta->id) {
|
||||
$e = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$e) {
|
||||
$cl = new stdClass;
|
||||
$cl->key = $meta->id;
|
||||
$cl->value = $meta->name;
|
||||
$out->push($cl);
|
||||
}
|
||||
}
|
||||
|
||||
$out->sort("value");
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
public static function delete_metadata($id, $metadata) {
|
||||
$doc = new Document($id);
|
||||
$doc->remove_metadata($metadata);
|
||||
return redirect("/document/" . $id);
|
||||
}
|
||||
|
||||
public static function api_guess_docid($id) {
|
||||
$doc = new Document($id);
|
||||
$docid = $doc->guess_docid();
|
||||
|
||||
return new Collection(["id" => $id, "docid" => $docid]);
|
||||
}
|
||||
|
||||
public static function download_attachment($id, $filename) {
|
||||
$doc = new Document($id);
|
||||
$atts = $doc->get_attachments();
|
||||
foreach ($atts as $f) {
|
||||
if ($f->basename() == $filename) {
|
||||
$f->set_header("Content-Disposition", "attachment; filename=\"$filename\"");
|
||||
|
||||
return $f;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function upload_attachment($id) {
|
||||
$doc = new Document($id);
|
||||
return blade("upload.attachment", ["doc" => $doc]);
|
||||
}
|
||||
|
||||
public static function do_upload_attachment($_request, $id) {
|
||||
$doc = new Document($id);
|
||||
mkdir(ROOT . "/attachments/" . $doc->id, 0777);
|
||||
|
||||
$f = 0;
|
||||
while (($file = $_request->file("file", $f)) !== false) {
|
||||
$nf = new File($file['tmp_name']);
|
||||
$nf->rename(ROOT . "/attachments/" . $doc->id . "/" . $file['name']);
|
||||
$f++;
|
||||
}
|
||||
return redirect("/document/" . $doc->id);
|
||||
}
|
||||
|
||||
public static function upload_document($_request) {
|
||||
return blade("upload.document");
|
||||
}
|
||||
|
||||
public static function do_upload_document($_request) {
|
||||
$i = 0;
|
||||
while ($f = $_request->file("file", $i)) {
|
||||
|
||||
$file = new File($f['tmp_name']);
|
||||
$sha256 = $file->hash();
|
||||
|
||||
$rev = Revision::find([["sha256", "=", $sha256]])->first();
|
||||
|
||||
if ($rev) {
|
||||
return redirect("/uploads/duplicate/" . $rev->id);
|
||||
}
|
||||
|
||||
$u = new Upload();
|
||||
$u->filename = $f['name'];
|
||||
$u->sha256 = $sha256;
|
||||
$u->ocr = "N";
|
||||
$u->ai = "N";
|
||||
$u->owner = get_user()->id;
|
||||
$u->save();
|
||||
copy($f['tmp_name'], ROOT . "/uploads/" . $u->id . ".pdf");
|
||||
$j = new ImportGeminiJob($u->id);
|
||||
$j->queue();
|
||||
$j = new ImportOCRJob($u->id);
|
||||
$j->queue();
|
||||
$i++;
|
||||
}
|
||||
return redirect("/uploads");
|
||||
}
|
||||
|
||||
public static function rerun_upload($id) {
|
||||
$u = new Upload($id);
|
||||
if ($u->ocr == "F") {
|
||||
$u->ocr = "N";
|
||||
$u->save();
|
||||
$j = new ImportOCRJob($u->id);
|
||||
$j->queue();
|
||||
}
|
||||
|
||||
if ($u->ai == "F") {
|
||||
$u->ai = "N";
|
||||
$u->save();
|
||||
$j = new ImportGeminiJob($u->id);
|
||||
$j->queue();
|
||||
}
|
||||
return redirect("/uploads");
|
||||
}
|
||||
|
||||
public static function rerun_all() {
|
||||
$ai = Upload::find([["ai", "=", "F"], ["owner", "=", get_user()->id]])->all();
|
||||
foreach ($ai as $u) {
|
||||
$u->ai = "N";
|
||||
$u->save();
|
||||
$j = new ImportGeminiJob($u->id);
|
||||
$j->queue();
|
||||
}
|
||||
$ocr = Upload::find([["ocr", "=", "F"], ["owner", "=", get_user()->id]])->all();
|
||||
foreach ($ocr as $u) {
|
||||
$u->ocr = "N";
|
||||
$u->save();
|
||||
$j = new ImportOCRJob($u->id);
|
||||
$j->queue();
|
||||
}
|
||||
return redirect("/uploads");
|
||||
}
|
||||
|
||||
public static function uploads($_request) {
|
||||
return DocumentController::uploads_page($_request, 0);
|
||||
}
|
||||
|
||||
public static function uploads_page($_request, $page) {
|
||||
$uploads = Upload::find([["owner", "=", get_user()->id]])->orderBy("id")->limit($page * 20, 20)->all();
|
||||
return blade("upload.list", ["uploads" => $uploads, "page" => $page]);
|
||||
}
|
||||
|
||||
public static function discard_upload($_request, $id) {
|
||||
$u = new Upload($id);
|
||||
if ($u->owner != get_user()->id) {
|
||||
return [403, "Not yours, punk!"];
|
||||
}
|
||||
|
||||
DB::getInstance()->query("delete from job where source=:source", ["source" => "upload:" . $u->id]);
|
||||
|
||||
unlink($u->getPDF());
|
||||
$u->delete();
|
||||
return redirect("/uploads");
|
||||
}
|
||||
|
||||
public static function import($_request, $id, $source) {
|
||||
$u = new Upload($id);
|
||||
if ($u->owner != get_user()->id) {
|
||||
return [403, "Not yours, punk!"];
|
||||
}
|
||||
|
||||
$doc = false;
|
||||
|
||||
if ($source == "ai") {
|
||||
$doc = Document::find_by_docid($u->ai_docid);
|
||||
} else if ($source == "ocr") {
|
||||
$doc = Document::find_by_docid($u->ocr_docid);
|
||||
}
|
||||
|
||||
if (!$doc) {
|
||||
$doc = new Document;
|
||||
if ($source == "ai") {
|
||||
$doc->internal_id = $u->ai_docid;
|
||||
} else if ($source == "ocr") {
|
||||
$doc->internal_id = $u->ocr_docid;
|
||||
} else {
|
||||
$doc->internal_id = "XX-XXXXX-XX";
|
||||
}
|
||||
$doc->title = $u->title;
|
||||
$doc->subtitle = $u->subtitle;
|
||||
$doc->subsubtitle = $u->subsubtitle;
|
||||
$doc->overview = $u->overview;
|
||||
$doc->save();
|
||||
|
||||
$incoming = Product::find([["title", "=", "Incoming"]])->first();
|
||||
$dp = new DocProduct();
|
||||
$dp->document = $doc->id;
|
||||
$dp->product = $incoming->id;
|
||||
$dp->save();
|
||||
}
|
||||
|
||||
|
||||
$rev = new Revision();
|
||||
$rev->document = $doc->id;
|
||||
$rev->revid="";
|
||||
$rev->sha256 = $u->sha256;
|
||||
$rev->origtitle = $u->source;
|
||||
$rev->save();
|
||||
|
||||
|
||||
$ocr = new OCR();
|
||||
$ocr->revision = $rev->id;
|
||||
$ocr->body = $u->body;
|
||||
$ocr->save();
|
||||
|
||||
$out = new File($rev->path() . "/doc.pdf");
|
||||
$out->parent()->mkdir();
|
||||
|
||||
$pdf = $u->getPDF();
|
||||
$pdf->rename($out->path());
|
||||
|
||||
$db = DB::getInstance();
|
||||
$db->query("DELETE FROM job WHERE source=:source", ["source" => "upload:" . $u->id]);
|
||||
$u->delete();
|
||||
|
||||
$rev->info = $rev->getPDF()->info();
|
||||
$rev->save();
|
||||
|
||||
$j = new IndexJob($rev->id);
|
||||
$j->queue();
|
||||
|
||||
|
||||
//return redirect("/uploads");
|
||||
return redirect("/document/" . $doc->id);
|
||||
|
||||
}
|
||||
|
||||
public static function delete_upload($_request, $id) {
|
||||
$u = new Upload($id);
|
||||
if ($u->owner != get_user()->id) {
|
||||
return [403, "Not yours, punk!"];
|
||||
}
|
||||
}
|
||||
|
||||
public static function upload_duplicate($id) {
|
||||
$r = new Revision($id);
|
||||
return blade("upload.duplicate", ["rev" => $r]);
|
||||
}
|
||||
|
||||
public static function view_upload($id) {
|
||||
$u = new Upload($id);
|
||||
return $u->getPDF();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user