Page 1 of 1

is this poss? links different for internal and external

Posted: Thu Feb 02, 2006 3:47 am
by carl_galloway
Hi all,

Is it possible to differentiate between internal and external links within posts or sidebar items so that I could theme them separately?

My expectation would be that a user simply includes the link in their post as per normal, but s9y then checks to see if the url is part of the blog or not and then appends a link_internal or link_external to the html style. I would then be able to add a different background image or change color. I most want this for posts if this is possible, but ultimately would love to see it within plugins as well.

Cheers
Carl

Posted: Thu Feb 02, 2006 5:27 am
by judebert
:shock:

Wow. Taller order than it seems.

An event plugin could go through the posts and modify the links with a style, kinda like a markup plugin does. It would probably check against the blog URL, and if it's not in the link, mark it with the appropriate class. Could get a bit complicated, since you'd have to account for any existing class, but not impossible.

Doing it for the plugins and sidebars is much more difficult. I don't think there's a hook that provides the Smarty-formatted output. On the other hand, maybe Smarty already thought of that...

Sure enough. Here's a plugin that should do what you want. It actually adds the class "external_link" to all links that don't include the blog URL. I haven't tested it, so use at your own risk.

Code: Select all

<?php
class serendipity_event_linkmarker extends serendipity_event {
    function introspect(&$propbag) {
        global $serendipity;

        $propbag->add('name',         'Link Marker');
        $propbag->add('version',      '0.1');
        $propbag->add('author',       'Jude Anthony');
        $propbag->add('stackable',     false);
        $propbag->add('event_hooks',   array(
                                            'genpage' => true
                                        )
        );
    }

    function event_hook($event, &$bag, &$eventData) {
        global $serendipity;

        $hooks = &$bag->get('event_hooks');

        if (isset($hooks[$event])) {
            switch($event) {
                case 'genpage':
                    if (!isset($serendipity['smarty'])) {
                        serendipity_smarty_init();
                    }
                    $serendipity['smarty']->register_outputfilter('marklinks');
                    break;
            }
        }

        return true;
    }

    function marklinks($tpl_output, &$smarty) {
      // Normalize class/href placement and some spacing
      $tpl_output = preg_replace('#<a([^>]*)href\s*=\s*"([^"])"([^>])class\s*=\s*"([^"]*)"([^>]*)>#',
          '<a $1 $3 $5 class="$4" href="$2">', $tpl_output);
      // Marking for links that already have a class
      $tpl_output = 
        preg_replace('#<a([^>]*)class\s*=\s*"([^"]*)"([^>]*)href\s*=\s*"((?<!' . $serendipity['baseURL'] . ')[^"]*)"([^>]*)>#', 
          '<a $1 $3 $5 class="$2 external_link" href="$4">', $tpl_output);
      // Marking for links without a class
      $tpl_output = 
        preg_replace('#<a([^>]*)href\s*=\s*"((?<!' . $serendipity['baseURL'] . ')[^"]*)"([^>]*)>#',
          '<a $1 $3 href="$2">', $tpl_output);

      return $tpl_output;   
    }
}
?> 
Well, the more I look at that, the less I like it. It only accounts for href and class with double-quotes, and I'm not so sure about those (?<! constructs. But give it a try and see how it works for you.

Posted: Thu Feb 02, 2006 4:22 pm
by carl_galloway
Jude,

Thank you very much, I tried using your code and got this error message
Parse error: parse error, unexpected '{' in C:\obfuscated\path\by\carl\for\security\plugins\serendipity_plugin_entrylinks\serendipity_event_linkmarker.php on line 24
I just threw it into the entrylinks folder for now, I haven't amended the code as provided in any way.

Cheers
Carl

Posted: Thu Feb 02, 2006 9:24 pm
by judebert
Weird. There is no { on line 24.

Of course, I did forget the ?> on the last line; you'll need to add it. I've edited it into the plugin above.

Maybe the problem is the directory name. It needs to be serendipity_event_linkmarker, not serendipity_plugin_entrylinks.

I'll give it a look on my server later today.

Posted: Thu Feb 02, 2006 10:39 pm
by judebert
Fixed the error (missing paren, edited in above), but everything else blows up afterward. Looks like you can't use a function in a class for a callback. I'll have to see what I can do with that.

Posted: Sat Feb 04, 2006 1:13 pm
by garvinhicking
You can use the array($this, 'func_Callback') method of specifying the callback, which will wrap your current object for the func. :)

Regards,
Garvin

Posted: Sat Feb 04, 2006 6:29 pm
by carl_galloway
I really think a lot of users would appreciate a plugin like this, so if that makes the plugin work it would be very worthwhile.

Thanks,

Carl

Posted: Sun Feb 05, 2006 5:19 pm
by judebert
Sorry I'm so slow this week, guys. Lots of family activities. I'm squeaking this out before I go to celebrate family birthdays.

I'm having trouble with the regular expressions, which is usually my strong point. These lookbehinds are killing me.

As I was reading the forum backlog, it occurred to me that the Content Rewriter plugin might do the job, at least for a bit. It does regular expression style replacements; if we put it below the other plugins, wouldn't it look at links when so configured?

Here's the most recent post, with links to better info: http://www.s9y.org/forums/viewtopic.php?t=4411

Meanwhile, I'll still be working on this. I find it interesting.

Posted: Sun Feb 05, 2006 6:29 pm
by carl_galloway
phew, glad to see you still like the idea, um, but as for the logic that you and Garvin are talking about, which dummy's guide do I need to buy to understand techtalk?

Doesn't lookbehind mean "watch out, look behind you!"

Posted: Tue Feb 07, 2006 9:03 pm
by judebert
Sorry, Carl. Lookbehinds are weird patterns that you use in searches; the plugin I made above is nothing more than a pattern-replacement tool. It should search for a pattern like <a href="<not my blog url><anything else>">whatever</a>. But the logic to match the <not my blog url> bit has to look at stuff that's already been matched. So it's called a lookbehind.

Mine aren't working. I've never used them before, so I'm still trying to understand them. I'm considering other options, too. Just gotta get a couple of days free. (I spent most of last night figuring out how to wire up a particular piece of my electric car so it wouldn't electrocute my brother.)

As to the Content Rewriter, I was throwing it out as a bone, maybe something that could tide you over. I've never used it myself. I think I will be using it as the basis of the external link rewriter. Maybe I'll even just extend it.