Jump to content

Wikimedia commons-like images


JoshoB
 Share

Recommended Posts

Happy New Year everyone!

For a large website project, images are all separate pages that contain a bunch of data, similar to image pages on Wikimedia Commons. When you want to add an image to another page, you have to load them from the Wikimedia-like page. This all works as expected. I also enable "Link to larger version".

However, when someone clicks the image, instead of just showing a larger version of the same picture, I want the user to be shown the page with all the extra data, including the name of the creator and the licence under which the picture is available.

Now, I think this can be done using regular expressions, but I cannot seem to get it done. I have created a function to pass $page->body through that then searches for HREF-attributes for pictures (stored in assets). What I want is to have the "larger version"-link be replaced by a link to the picture page. I cannot wrap my head around it, however.

Is there a kind soul who can help me out? Simply put, I want the function to search through $page->body, when it finds something like:

'/href="\/cms\/site\/assets\/files\/(\w+)\/(\w+).(\w+)"/i'

I want it to replace that with a link to the picture page, for example 'href="example-page/target/"'. Any tips?

  • Like 1
Link to comment
Share on other sites

First question would be why not just link to the page rather than the image in the first place? But thinking on it more, I'm betting you are inserting these from TinyMCE/CKEditor? Something like this might work:

function replaceImagesWithPages($str) {
  $rx = '{href="' . wire('config')->urls->root . 'site/assets/files/(\d+)/.+?"}i';
  if(!preg_match_all($rx, $str, $matches)) return $str;
  foreach($matches[1] as $key => $id) {
    $page = wire('pages')->get((int) $id); 
    if($page->viewable()) {
      $str = str_replace($matches[0][$key], "href='$page->url'", $str); 
    }
  }
  return $str; 
}

echo replaceImagesWithPages($page->body); 
 

This type of thing could be bundled into your own Textformatter module for easy re-usability (let me know if I can elaborate). Note that this was written in the browser and not actually tested, so may likely need adjustments. 

  • Like 2
Link to comment
Share on other sites

Wow, Ryan, thanks a lot!

Yes, I may not have explained it very well at first. The object is to have all the pictures together (under /pictures/), so that they can be browsed and searched similar to Wikimedia Commons. Regular pages don't have an images field; instead, you select the picture page itself and then insert those images in the page. When you click on the image, it should take you to the description.

This really works excellently; thanks again.

I'd be interested to know more about writing your own Textformatter module. :-)

Link to comment
Share on other sites

Here is the same thing as a Textformatter module. To use, paste the following into /site/modules/TextformatterImagesToPages.module. Then, in your admin, to to Modules > Check for new modules. Click install on the new module. Then go to Setup > Fields and edit the field you want it to operate on ('body' for example). On the "details" tab, choose the "Images to Pages" text formatter, and save. The text formatter will be applied automatically when you access any $page->body field from the front-end of your site. 

/site/modules/TextformatterImagesToPages.module

<?php

class TextformatterImagesToPages extends Textformatter {

  public static function getModuleInfo() {
    return array(
      'title' => 'Images to Pages',
      'version' => 1,
      'summary' => "Takes image links in HTML and converts them to page links."
    );
  }

  public function format(&$str) {
    $rx = '{href="' . wire('config')->urls->root . 'site/assets/files/(\d+)/.+?"}i';
    if(!preg_match_all($rx, $str, $matches)) return;
    foreach($matches[1] as $key => $id) {
      $page = wire('pages')->get((int) $id); 
      if($page->viewable()) 
        $str = str_replace($matches[0][$key], "href='$page->url'", $str); 
    }
  }

} 
  • Like 4
Link to comment
Share on other sites

  • 2 weeks later...
  • 2 weeks later...

I am having some trouble finding a solution to render captions for the images that are linked in this way. I want to avoid using JavaScript, but all of the extant modules like ImageInterceptor seem either not to function correctly either or just plain overkill.

Is there a way to modify the code above to also output a caption for the figure, and/or perhaps wrap the whole thing in HTML5 figure and figcaption tags? I've been trying for days, but it has got me stumped. I thought the AutoSchema module would work well, but it generates an error and I don't understand why (claims there's a reference to a method that doesn't exist, but it does).

Link to comment
Share on other sites

Thanks for the link Adrian. I had used that thread before, but none of the solutions work for me, including yours. When I use your module, ProcessWire adds doctype-statements before the images (which is erroneous), but doesn't add a caption. Any idea how to solve that?

Edit: one problem for the JS solutions is the fact that because the images are linked, the DIVs are placed inside the A-tags, which causes problems. What I need something that checks if the image is linked yes/no and then applies the DIVs around the A-tag for the picture (but not the caption). It's a little complex at the moment.

Link to comment
Share on other sites

If you are using my module, remember that it takes the description field from the images field, rather than the one that you get when inserting the image into the RTE, Do you have those descriptions filled out?

I just pushed an update to the module. I have been using it on a few sites, but apparently forgot to push some recent fixes. Can you see if these changes make any difference?

  • Like 1
Link to comment
Share on other sites

Hi Adrian!

Thanks for the update. Unfortunately, the problem remains: the module adds a doctype-statement to every image. Not sure why. Like I said, I guess it just doesn't play nice with the ImagesToPages module. I will have a closer look at your code and see if I can find anything...

Edit: by the way, all images have a properly filled-in description field.

Link to comment
Share on other sites

Oh right now I understand - sorry I didn't read through the posts above properly to see what Ryan's module does and that you were using it. That might well be the issue. I'd be curious if you could disable it for a moment to see if the image caption module works.

  • Like 1
Link to comment
Share on other sites

No luck; sorry, Adrian.

Disabling the ImagesToPages module doesn't resolve the error that your module gives me. It also has the downside of apparently attempting to add a caption to every image, and I only need captions in the body field.

I've been trying to regex my way to hacking a module together to: (a) wrap the image (and a possible a-tag) into an HTML5 "figure" tag, and; (b) to extract the alt-text and wrap that inside a "figcaption" tag beneath the image and inside the "figure" tag. I got quite far, but matching one with the other (alt text to image) and having it all play nice is turning out to be impossible for me. I finally managed to get an ugly hack together to wrap the image and a-tag in a figure-tag, but that caused problems with the p-tag that the image is in, for some reason (in Firefox).

I've been going over and over this for some time now and it's getting a little frustrating. Anyway, I'll leave it for now. If someone has any idea to solve this...

Link to comment
Share on other sites

No need to apologize.

That module wasn't officially released because it hasn't really been tested in different scenarios, but it has been working just fine for me on a few sites, so I am curious why it's not working for you. 

Perhaps you will do better with Martijn's Image Interceptor. I know it might seem like overkill, but I have also used it and it works great, so long as you are happy using the image ALT field, rather than the images field description field, if that makes sense.

Good luck.

  • Like 1
Link to comment
Share on other sites

Martijn's module would be nice, but it doesn't function on my site, either.

Do you have any idea what kind of regular expression would work? I tried a DOM-like method, and while it extracted the alt texts just fine, there was no way -- that I could see -- to insert them properly back into the page.

Link to comment
Share on other sites

Well if neither my module nor Martijn's are working, it makes me wonder what is going on with your server / configuration. There are lots of ways to do this with a regex. Here is an example from teppo: https://github.com/teppokoivula/TextformatterImageWrapper/blob/master/TextformatterImageWrapper.module that should get you going.

  • Like 1
Link to comment
Share on other sites

I finally solved it, thanks to the module you linked to. This worked for me:

class TextformatterImageCaptionWrapper extends Textformatter 
{
	// Module information
	public static function getModuleInfo() 
	{
		return array(
			'title' => 'Image Caption Wrapper',
			'version' => 1,
			'summary' => "Adds a wrapper to images to support the use of captions drawn from alt-texts."
		);
	}
    
	// Formatting function use by TextFormatter
    public function format(&$str) 
	{
        if (!preg_match_all('#<a*[^>]*><img.*? alt="(.*?)".*?></a>#si', $str, $matches)) return;

        // iterate over found matches
        foreach($matches[0] as $key => $value) 
		{
            $caption = "";
            if ($matches[1][$key]) $caption = "<div class='caption'>{$matches[1][$key]}</div>";
            $class = "image_wrap";
            if ($caption) $class .= " with_caption";
            if (preg_match('# class="(.*?)"#si', $value, $match)) 
			{
                $class .= " {$match[1]}";
            }

            $image = '<div class="image">' . $value . '</div>';

            $out = "<div class='{$class}'>{$image}{$caption}</div>";

            // replace original tag ($line) with wrapped one ($out)
            $str = str_replace($value, $out, $str);
		}
	}
}

I'd like the A-tag to be optional, but I'll deal with that problem later.

Thanks for all the help and your patience!

  • Like 1
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...