bulk_add_csv: bulk_add with metadata

Imports a CSV with:
path,tags,source,rating

It is basically bulk_add with an fgetcsv loop instead of a foreach glob.
I wanted an easy way to import tagged data from other sources.
This commit is contained in:
velocity37 2012-08-23 17:03:46 -07:00
parent 624468851e
commit 86402f681c
2 changed files with 176 additions and 0 deletions

132
ext/bulk_add_csv/main.php Normal file
View file

@ -0,0 +1,132 @@
<?php
/*
* Name: Bulk Add CSV
* Author: velocity37 <velocity37@gmail.com>
* License: GPLv2
* Description: Bulk add server-side images with metadata from CSV file
* Documentation:
* Modification of "Bulk Add" by Shish.<br><br>
* Adds images from a CSV with the four following values: <br>
* "/path/to/image.jpg","space separated tags","source","rating (s, q, or e)" <br>
* <b>e.g.</b> "/tmp/cat.png","shish oekaki","shimmie.shishnet.org/v2/post/view/3051","s" <br><br>
* Any value but the first may be omitted, but there must be four values per line.<br>
* <b>e.g.</b> "/why/not/try/bulk_add.jpg","","",""<br><br>
* Useful for importing tagged images without having to do database manipulation.<br>
* <p><b>Note:</b> requires "Admin Controls" and optionally "Image Ratings" to be enabled<br><br>
*
*/
class BulkAddCSV extends Extension {
public function onPageRequest(PageRequestEvent $event) {
global $page, $user;
if($event->page_matches("bulk_add_csv")) {
if($user->is_admin() && $user->check_auth_token() && isset($_POST['csv'])) {
set_time_limit(0);
$this->add_csv($_POST['csv']);
$this->theme->display_upload_results($page);
}
}
}
public function onCommand(CommandEvent $event) {
if($event->cmd == "help") {
print " bulk-add-csv [/path/to.csv]\n";
print " Import this .csv file (refer to documentation)\n\n";
}
if($event->cmd == "bulk-add-csv") {
global $user;
//Nag until CLI is admin by default
if (!$user->is_admin()) {
print "Not running as an admin, which can cause problems.\n";
print "Please add the parameter: -u admin_username";
} elseif(count($event->args) == 1) {
$this->add_csv($event->args[0]);
}
}
}
public function onAdminBuilding(AdminBuildingEvent $event) {
$this->theme->display_admin_block();
}
/**
* Generate the necessary DataUploadEvent for a given image and tags.
*/
private function add_image($tmpname, $filename, $tags, $source, $rating) {
assert(file_exists($tmpname));
$pathinfo = pathinfo($filename);
if(!array_key_exists('extension', $pathinfo)) {
throw new UploadException("File has no extension");
}
$metadata['filename'] = $pathinfo['basename'];
$metadata['extension'] = $pathinfo['extension'];
$metadata['tags'] = $tags;
$metadata['source'] = $source;
$event = new DataUploadEvent($tmpname, $metadata);
send_event($event);
if($event->image_id == -1) {
throw new UploadException("File type not recognised");
} elseif(class_exists("RatingSetEvent") && in_array($rating, array("s", "q", "e"))) {
$ratingevent = new RatingSetEvent(Image::by_id($event->image_id), $rating);
send_event($ratingevent);
}
}
private function add_csv(/*string*/ $csvfile) {
global $page;
if(!file_exists($csvfile)) {
$this->theme->add_status("Error", "$csvfile not found");
return;
}
if (!is_file($csvfile) || strtolower(substr($csvfile, -4)) != ".csv") {
$this->theme->add_status("Error", "$csvfile doesn't appear to be a csv file");
return;
}
$linenum = 1;
$list = "";
$csvhandle = fopen($csvfile, "r");
while (($csvdata = fgetcsv($csvhandle, 0, ",")) !== FALSE) {
if(count($csvdata) != 4) {
if(strlen($list) > 0) {
$this->theme->add_status("Error", "<b>Encountered malformed data. Line $linenum $csvfile</b><br>".$list);
fclose($csvhandle);
return;
} else {
$this->theme->add_status("Error", "<b>Encountered malformed data. Line $linenum $csvfile</b><br>Check <a href=\"" . make_link("ext_doc/bulk_add_csv") . "\">here</a> for the expected format");
fclose($csvhandle);
return;
}
}
$fullpath = $csvdata[0];
$tags = trim($csvdata[1]);
$source = $csvdata[2];
$rating = $csvdata[3];
$pathinfo = pathinfo($fullpath);
$shortpath = $pathinfo["basename"];
$list .= "<br>".html_escape("$shortpath (".str_replace(" ", ", ", $tags).")... ");
if (file_exists($csvdata[0]) && is_file($csvdata[0])) {
try{
$this->add_image($fullpath, $pathinfo["basename"], $tags, $source, $rating);
$list .= "ok\n";
}
catch(Exception $ex) {
$list .= "failed:<br>". $ex->getMessage();
}
} else {
$list .= "failed:<br> File doesn't exist ".html_escape($csvdata[0]);
}
$linenum += 1;
}
if(strlen($list) > 0) {
$this->theme->add_status("Adding $csvfile", $list);
}
fclose($csvhandle);
}
}
?>

View file

@ -0,0 +1,44 @@
<?php
class BulkAddCSVTheme extends Themelet {
var $messages = array();
/*
* Show a standard page for results to be put into
*/
public function display_upload_results(Page $page) {
$page->set_title("Adding images from csv");
$page->set_heading("Adding images from csv");
$page->add_block(new NavBlock());
foreach($this->messages as $block) {
$page->add_block($block);
}
}
/*
* Add a section to the admin page. This should contain a form which
* links to bulk_add_csv with POST[csv] set to the name of a server-side
* csv file
*/
public function display_admin_block() {
global $page, $user;
$html = "
Add images from a csv. Images will be tagged and have their
source and rating set (if \"Image Ratings\" is enabled)
<br>Specify the absolute or relative path to a local .csv file. Check <a href=\"" . make_link("ext_doc/bulk_add_csv") . "\">here</a> for the expected format.
<p>".make_form(make_link("bulk_add_csv"))."
<table class='form'>
<tr><th>CSV</th><td><input type='text' name='csv' size='40'></td></tr>
<tr><td colspan='2'><input type='submit' value='Add'></td></tr>
</table>
</form>
";
$page->add_block(new Block("Bulk Add CSV", $html));
}
public function add_status($title, $body) {
$this->messages[] = new Block($title, $body);
}
}
?>