modifiedcontent

Change 'choose file' image source options to include external media gallery?

Recommended Posts

Is there a way to change the input options for the images field?

I am trying to figure out if it would make sense to use an external script like Zenphoto as a central media library/manager. How could I connect that with Processwire?

'Choose File' in the images field would have to be able to open that 3rd party media library or a directory on the server or some cloud service instead of (only) the client file manager.

Could justb3a's field type module Image Extra be part of the solution? I will try that and report back. Other field types/modules?

I know there is a pro module Media Manager that does look very slick, but would prefer to make this work with a mature, tested 3rd party script if a central media gallery is never going to be a core Processwire feature.

Share this post


Link to post
Share on other sites

Hello.

7 hours ago, modifiedcontent said:

'Choose File' in the images field would have to be able to open that 3rd party media library or a directory on the server or some cloud service instead of (only) the client file manager.

There are few possible problems with centralised concept. As example, what to store in that images field? To be more clear, if some image is part of PW page only as reference link, than how can we resize it (eg. "on the fly" in page rendering process)? What would happened when someone delete image on that external point - how would ProcessWire page know that? Etc...

Because of that, if I go to build that module/field type than probably it will copy image from that external central point to ProcessWire page. With that, we can have external Media manager where we can use all it's power (organise files to folders, search etc.). Also, because we have on PW side copy of that file we can use all PW API power to manipulate with it - on PW side.

Here was few discussions why PW by default doesn't have "Media manager" like many others CMS's (I was one with that question too) but very soon undrestand that maybe because of that some other popular CMS's still doesn't have simple solution to store and generate various dimensions intro images. If some CMS's had that option, need to look closely to see how and where they store eg. that intro images... Storing concept is very important (eg. in case when need to do some export or imports).

That what you ask is completly ok, but also it's important to think about possible consequences.
What I like in centralised Media manager idea is 1 central point for file organisations, all other with that idea bring us problems and complicate things.
Regards.

Share this post


Link to post
Share on other sites

OLSA, thanks for your feedback. I personally like how Processwire handles images, but I have a client who wants a central media library.

That is why I want to create an external media library - Zenphoto in my case - and have Processwire "upload" the images from there instead of from a client OS file manager.

How can I modify 'choose file' in the image field to use other source options? Is it possible to have that open a web-based file manager of another script on the server or on a cloud service, AWS, whatever?

 

Share this post


Link to post
Share on other sites

Thanks dragan, but those threads really focus on uploading to AWS. I am looking for a way to download from an external library, instead of the client machine. I don't mind if the images are then stored/uploaded in the regular PW way.

How can I modify 'choose file' in the image field to open a file manager on a URL, instead of a client machine OS file manager?

Share this post


Link to post
Share on other sites

It's a little bit more involved that just "opening a file manager on a URL", since you have to get the necessary information back to PW, tell it to download the image in question and add it to a page field. Here's a small module that can do that, but it's little more than a starting point (no checking of that image is already there, for example, no live updating the image fields in the page editor) and that requires a rest api plugin on Zenphoto's side.

Spoiler

<?php

/**
 * Download photos from your Zenphoto galleries into your PW image fields
 * from within PW's image picker in CKEditor
 *
 * Needs zen_json_rest_api installed in Zenphoto
 * from https://github.com/deanmoses/zenphoto-json-rest-api
 * and URL Rewrite active in Zenphoto.
 *
 * Note: if you run Zenphoto on Windows, you will have to add a fix
 * to zen_json_rest_api. Edit json_rest_api and modify the dateToTimestamp
 * function according to https://github.com/deanmoses/zenphoto-json-rest-api/issues/14
 *
 * Beware: I have no clue if Permissions are honored on Zenphoto's side,
 * and no idea if introducing access control there blows things up.
 *
 * License:
 * This module is released under the WTFPL.
 * Feel free to do with this code whatever you want.
 *
 */
 

class ZenPhoto extends WireData implements Module, ConfigurableModule {

	public static function getModuleInfo() {
		return array(
			'title' => 'Zen Photo',
			'summary' => 'Allow browsing a Zenphoto installation and importing media from there. Zenphoto must have zenphoto_json_rest_api plugin active.',
			'version' => "0.0.4",
			'autoload' => true
		);
	}
	
	public function init() {
		$this->addHook("ProcessPageEditImageSelect::executeZenPicker", $this, "executeZenPicker");
		$this->addHook("ProcessPageEditImageSelect::executeZenDownload", $this, "executeZenDownload");
		$this->addHookAfter("ProcessPageEditImageSelect::execute", $this, "execute_addButton");
	}
	
	public function execute_addButton(HookEvent $event) {
		$this->initPages($event->object);

		$html = $event->return;
		
		$btn = $this->modules->get('InputfieldButton');
		$btn->href = $this->makeExecLink("picker");
		$btn->value = $this->_('Import ZenPhoto Image');
		$btn->addClass('upload pw-modal-button'); 
		$btn->icon = 'link';

		$out = $btn->render();
		
		$html = preg_replace('~</div>$~', "<p>" . $out . "</p>" . '$1', $html);
		$event->return = $html;
	}
	
	public function executeZenPicker(HookEvent $event) {
		$this->initPages($event->object);

		if(! $this->zenphotoURL) {
			$event->return = "<p><strong>" . $this->_("No Zenphoto URL configured. Go to Modules -> Configure -> Zen Photo and set a valid URL to your Zenphoto installation.");
			return;
		}

		$albumPath = $this->input->get->album;
		$url = $this->zenphotoURL;
		
		if($albumPath) {
			$url .= $albumPath;
		}
		
		$galery = "<div>";
		
		$zenGalery = $this->getJson($url);
		
		if($zenGalery !== FALSE) {
			$galery .= "<h3>" . sprintf($this->_("Albums in %s"), $albumPath ?: "/") . "</h3>" .
					"<div>";
			if($albumPath) {
				$parentAlbum = rtrim(preg_replace('~[^/]+$~', '', $albumPath), "/");
				$galery .= "<div style='width: 160px; height: 160px; display: inline-block; padding: 0.5em; vertical-align: top;'>" .
						"<a href='" . $this->makeExecLink("picker") . "&album={$parentAlbum}'>" .
						"..<br>" .
						$this->_("Return to parent album ") . "</a>" .
						"</div>";
				
			}
			foreach($zenGalery->album->albums as $album) {
				$galery .= "<div style='width: 160px; height: 160px; display: inline-block; padding: 0.5em; vertical-align: top;'>" .
						"<img style='max-width: 120px; max-height: 120px;' src='" . $album->url_thumb . "' alt='" . $album->title . "' title='" . $album->title . "'><br>" .
						"<a href='" . $this->makeExecLink("picker") . "&album={$album->path}'>" .
						$this->_("Browse album: ") . $album->title . "</a>" .
						"</div>";
			}
			if(! $zenGalery->album->albums) {
				$galery .= "<div style='width: 160px; height: 160px; display: inline-block; padding: 0.5em; vertical-align: top;'>" .
						$this->_("No child albums defined") .
						"</div>";
			}
			$galery .= "</div>" .
					"<h3>" . sprintf($this->_("Images in %s"), $albumPath ?: "/") . "</h3>" .
					"<div>";
			foreach($zenGalery->album->images as $image) {
				$galery .= "<div style='width: 160px; height: 180px; display: inline-block; padding: 0.5em; vertical-align: top;'>" .
						"<img style='max-width: 120px; max-height: 120px;' data-url='" . $image->path . "' src='" . $image->url_thumb . "' alt='" . $image->title . "' title='" . $image->title . "'><br>" .
						"<a href='" . $this->makeExecLink("download") . "&image={$image->url_full}&imagename=" . basename($image->path) . "'>" .
						$image->title . " (" . $image->width . "x" . $image->height . ") [" . strftime($this->_("%Y-%m-%d %H:%M"), $image->date) . "]</a>" .
						"</div>";
			}
		}
		$galery .= "</div>" .
				"</div>";
		
		$event->return = $galery;
	}

	private function makeExecLink($action) {
		return "./zen-" . $action . "?modal=1&id={$this->page->id}&edit_page_id={$this->editorPage->id}";
	}

	public function executeZenDownload(HookEvent $event) {
		$this->initPages($event->object);
		
		if(! $this->zenphotoURL) {
			$event->return = "<p><strong>" . $this->_("No Zenphoto URL configured. Go to Modules -> Configure -> Zen Photo and input the URL of your Zenphoto installation.");
			return;
		}

		if(! $this->input->get->assignfile) {
			// Download selected image
			$url = $this->input->get->image;
			$name = $this->input->get->imagename;
			
			if(! strlen($url) || ! strlen($name)) {
				$event->return = "<p><strong>" . $this->_("Missing parameters for image.");
				return;
			}
			
			$tempName = $this->getImage($url, $name);
			
			$toPage = $this->page ?: $this->editPage;
			
			$this->log->message("toPage = " . $toPage->id);
			
			$imageFields = array();
			foreach($toPage->template->fields as $fld) {
				if($fld->type instanceof FieldtypeImage) {
					$imageFields[] = $fld;
				}
			}
			
			$form = $this->modules->get("InputfieldForm");
			$form->label = sprintf($this->_("Add image to page %s"), $toPage->title);
			$form->action = "./zen-download";
			$form->method = "get";
			
			$f = $this->modules->get("InputfieldHidden");
			$f->attr('name', "id");
			$f->attr('value', $this->page->id);
			$form->add($f);
			
			$f = $this->modules->get("InputfieldHidden");
			$f->attr('name', "edit_page_id");
			$f->attr('value', $this->editorPage->id);
			$form->add($f);
			
			$f = $this->modules->get("InputfieldHidden");
			$f->attr('name', "topage");
			$f->attr('value', $toPage->id);
			$form->add($f);
			
			$f = $this->modules->get("InputfieldHidden");
			$f->attr('name', "tempimage");
			$f->attr('value', $tempName);
			$form->add($f);
			
			if(count($imageFields) > 1) {
				// Show a select dropdown if there is more than one possible image field
				$f = $this->modules->get("InputfieldSelect");
				$f->attr('name', 'targetField');
				$f->label = $this->_("Select target image field on page");
				foreach($imageFields as $fld) {
					$f->addOption($fld->name, $fld->label);
				}
				$f->required = true;
			} else {
				$f = $this->modules->get("InputfieldHidden");
				$f->attr('name', 'targetField');
				$f->attr('value', $imageFields[0]->name);
			}
			$form->add($f);
			
			$urlCmp = parse_url($this->zenphotoURL);
			
			$fullUrl = $urlCmp["scheme"] . "://" . $urlCmp["host"] . ":" . $urlCmp["port"] . $url;

			$f = $this->modules->get("InputfieldMarkup");
			$f->attr('value', "<img src='$fullUrl' />");
			$form->add($f);
			
			$btn = $this->modules->get("InputfieldSubmit");
			$btn->attr('name', "assignfile");
			$btn->attr('value', $this->_("Import this image"));
			$form->add($btn);
			
			$event->return = $form->render();
		} else {

			$toPage = $this->pages->get((int)$this->input->get->topage);
			$tempimage = $this->input->get->tempimage;
			$targetField = $this->sanitizer->fieldName($this->input->get->targetField);

			$toPage->of($false);
			$img = new Pageimage($toPage->{$targetField}, $tempimage);
			$toPage->{$targetField}->add($img);
			$toPage->save($targetField);
			
			unlink($tempimage);
			
			$this->session->redirect($this->config->urls->admin . "page/image/edit?modal=1&file={$toPage->id},{$img->name}&id={$toPage->id}&edit_page_id={$this->editorPage->id}");
		}
	}

	private function initPages($imageSelect) {
		$id = (int) $this->input->get->id; 
		$editID = (int) $this->input->get->edit_page_id; 
		if(! $editID) {
			$editID = $this->session->get($imageSelect, 'edit_page_id');
		}
		if($editID) {
			$this->editorPage = $this->wire('pages')->get($editID); 
		}
		if($id) {
			$this->page = $this->wire('pages')->get($id);
		}
	}

	public function getModuleConfigInputfields(array $data) {
		$inputfields = $this->wire(new InputfieldWrapper());

		$f =  $this->wire('modules')->get('InputfieldText');
		$f->attr('name', 'zenphotoURL');
		$f->label = $this->_("Zenphoto URL");
		$f->description = $this->_("Base URL of the Zenphoto installation");
		$f->attr('value', isset($data['zenphotoURL']) ? $data['zenphotoURL'] : '' );
		$inputfields->add($f);
		
		return $inputfields;
	}
	
	public function getJson($url) {

		$url = rtrim($url, "/") . "/";

		$ch = curl_init();

		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_URL, $url . "?json");

		$result = curl_exec($ch);

		curl_close($ch);

		if($result === FALSE) return $result;
		
		$decoded = json_decode($result);
		if($decoded === NULL) {
			$this->log->error(sprintf($this->_("Invalid JSON return in ZenPhoto::getJSON from %s"), $url));
			return FALSE;
		}
		
		return $decoded;
	}
	
	public function getImage($url, $name) {
		$http = new WireHTTP();
		
		$tmpname = $this->config->uploadTmpDir . $name;
		
		$urlCmp = parse_url($this->zenphotoURL);
		
		$fullUrl = $urlCmp["scheme"] . "://" . $urlCmp["host"] . ":" . $urlCmp["port"] . $url;
		
		$http->download($fullUrl, $tmpname);
		
		return $tmpname;
	}
}

 

 

  • Like 6

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Roberts R
      Solution :
       
      Issue :
      Fresh install ProcessWire 3.0.39 + multilangual support
      In video it shows how it goes. And I can't figure it out.  It happens for few of my sites.
      td;tl : Upload 5 image in images field ->  Save -> 2 left.
      EDIT : Files are in "/assets/files/id"
      processwire-bug.mp4
    • By cosmicsafari
      Hi all,
      I am working on a site which involves a lot of image upload fields, 99% of the time it works perfectly but I have noticed that every so often image variations will be missing.
      Like the original uploaded image is fine but maybe 1 or 2 out of the variations is just blank.
      The variation files will appear within the assets folder but they will be just in name only without any actual image content.
      Since its quite a random thing I am finding it rather difficult to figure out why this happens?
      Any ideas?
    • By modifiedcontent
      It would be great if 'choose file' in the image field would be able to handle other input sources than only the client's OS file manager; Amazon S3/cloud storage, Dropbox, an image folder on an intranet, another folder on the same server where PW is installed, whatever.
      It would be super convenient if you could just upload images to a folder/directory in the templates folder or root, without any processing, and be able to access that as a source option in the image field. Any way to make that happen?
      I had started a thread about this here. BitPoet posted a very helpful partial solution specifically for Zenphoto, but it would be great if there was a more source agnostic solution built into Processwire.
      Letting Processwire download images from any external media gallery/repository would be a good alternative to having a full centralized Media Manager.
      Or am I missing something that would make this impossible/a bad idea?
      Edit: Robin S has a module that adds one alternative input option.
    • By David Koplin
      Hello dear community
      I have a problem with a front edit possibility inside a OWL gallery.
      The thing is, normally you do a double click to edit something directly on a page.
      In my case a single click opens up a picture inside a gallery, so I can't "hit" the editing.

         
                           <div class="demo-gallery">                             <ul id="lightgallery2" class="list-unstyled row">                                 <li class="img-md-12 mb-12 mb-sm-12 mb-md-12 mb-lg-12 mb-xl-12 col-12 col-md-12 img-fluid full-height" data-responsive="" data-src="<? echo $page->page_home_owl_00_img->url; ?>" data-sub-html="<h4><? echo $page->page_home_owl_00_h4; ?></h4><p><? echo $page->page_home_owl_00_p; ?></p>">                                     <a href="">                                         <img class="img-responsive" src="<? echo $page->page_home_owl_00_img->url; ?>">                                     </a>                                 </li>                                                                  <? foreach($page->children('template=9dk-owl-home') as $item): ?>                                 <li class="img-md-6 mb-3 mb-sm-3 mb-md-3 mb-lg-3 mb-xl-3 col-12 col-md-6 img-fluid" data-responsive="" data-src="<? echo $config->urls->templates ;?><? echo $item->page_home_owl_01_img; ?>" data-sub-html="<h4><? echo $item->page_home_owl_01_h4; ?></h4><p><? echo $item->page_home_owl_01_p; ?></p>">                                     <a href="">                                         <img class="img-responsive" src="<? echo $config->urls->templates ;?><? echo $item->page_home_owl_01_img; ?>">                                     </a>                                 </li>                                 <? endforeach; ?>                                                         </ul>                         </div>  
      I tried any variants of options C and D from this page:
      https://processwire.com/api/modules/front-end-editing/
      Are there any hints for me, what I can do?
      Any help is highly appreciated!

      Best from Munich in Germany