Recent Topics

[2.x] First linked image in sidebar

Started by on Aug 15, 2008 – Contents updated: Aug 15, 2008

Aug 15, 2008 20:37    

My b2evolution Version: 2.x

I'm starting to tinker with a plugin that will search a blog for items with linked images then display the first linked image in the sidebar. The problem is, as I should have known, that this stuff is way over my head.

So if anyone is motivated, here are some details about where I want to go: think of it like partially the "posts" widget, only all it shows is items with at least one linked image, and all it shows is the first linked image. Probably the title of the post as well. Oh and of course link both the title and the image to the post's permalink.

The category part is where I'm going blind again. Like, each entry in foo_links tells me a "link_itm_ID" value, and that via foo_items__item can tell me a "post_main_cat_ID" and foo_categories can tell me "cat_blog_ID" but holy smokes I've no idea how to build a query that starts with the blog_ID and works itself backwards through the categories table. I'm thinking adding a zillion queries would be a mistake eh?

hmmm... maybe I should add an extra checkbox field when posting that says "add this to the FLIISB list?" and build a table on posting that contains all the groovy details required to make a sidebar list? That way the SkinTag would say "okay check out the extra table and spit out what it's got". Seems to me though that the database already contains what it needs so shouldn't I be able to query it directly with minimum overhead?

Anyway it is an idea that I don't think we have available and would like to either create OR see someone else create with style.

Aug 15, 2008 22:32

Here's a working hack.

All you need is edit the loop in inc/widgets/model/widget.class.php lines 485-495 to

PHP

while( $Item = & $ItemList->get_item() )
{
    $File = & get_File_by_Item_ID$Item->ID );
 
    if( !is_object($File) )
        continue;
    
    $imgSize $File->get_image_size'widthheight' );
    
    // Option 1: Pop-up image
    $image '<a href="'.$Item->get_permanent_url().'" title="'.$Item->title.'" onclick="return pop_up_window( \''.
                    $File->get_url().'\', \'popup_image\', '.($imgSize[0]+25).', '.($imgSize[1]+25).' )"><img src="'.
                    $File->get_thumb_url().'" alt="" /></a>';
    
    // Option 2: Link to post
    $image '<a href="'.$Item->get_permanent_url().'" title="'.$Item->title.'"><img src="'.
                    $File->get_thumb_url().'" alt="" /></a>';
            
    echo $this->disp_params['item_start'];
    $Item->titlearray(
            'link_type' => 'permalink',
        ) );
    if( $this->disp_params'disp_excerpt' ] )
        echo '<p>'.$Item->dget'excerpt''htmlbody' ).'</p>';// no formatting in excerpts
    
    echo $image;
 
    echo $this->disp_params['item_end'];
}

And use the function I posted before to get a File object by Item ID
Here it is again

PHP

// Get File by Item ID
function get_File_by_Item_ID$Item_ID$position )
{
    $FileCache = & get_Cache'FileCache' );
    
    $SQL = & new SQL();
    
    $SQL->SELECT'link_ID, link_ltype_ID, file_ID, file_title, file_root_type, file_root_ID, file_path, file_alt, file_desc' );
    $SQL->FROM'T_links LEFT JOIN T_files ON link_file_ID = file_ID' );
    $SQL->WHERE'link_itm_ID = '.$Item_ID );
    $SQL->ORDER_BY'link_ID' );
    
    $Results = & new Results$SQL->get(), 'link_' );
    $Results->queryfalsefalsefalse );
 
    if( $Results->total_rows != )
        return false;
    
    $File = & $FileCache->get_by_ID$Results->rows[$position]->file_IDfalsefalse );
    
    if( !is_object($File) && !$File->is_image() )
        return false;
    
    return $File;
}

Aug 16, 2008 01:27

Well I'd rather avoid more hacks, but this'll do as a starting point I guess. THANKS!

Aug 16, 2008 12:12

Hey this is getting fun!

So far I've managed to add it to the widget list without bothering to make it be a plugin. Seems to me that means a little less server power required eh? I've also incorporated a modified version of your "custom size" hack so that my image fits the sidebar in evopress nicely (160 wide by the way). But I run into a problem I thought I'd show before I try to hack through it.

So I'm trying to present the first linked image in a post in the sidebar. The problem happens when posts do not have a linked image, and one must assume that not all posts in any given blog will have a linked image. I get 2 notices and a fatal error from inc/files/model/_file.funcs.php, which happens to be where I put your get_file_by_item_ID function. The specific lines in question are as follows:

Code

$File = & $FileCache->get_by_ID( $Results->rows[$file_number]->file_ID, false, false );
 
if( !is_object($File) && !$File->is_image() )

View source on the errors and death reveal the following:

<b>Notice</b>: Undefined offset: 0 in <b>/path_to/inc/files/model/_file.funcs.php</b> on line <b>735</b><br>
<br>
<b>Notice</b>: Trying to get property of non-object in <b>/path_to/inc/files/model/_file.funcs.php</b> on line <b>735</b><br>

<br>
<b>Fatal error</b>: Call to a member function is_image() on a non-object in <b>/path_to/inc/files/model/_file.funcs.php</b> on line <b>737</b><br>

I *think* I need to do something with the "$File = & $FileCache->get_by_ID" bit to stop it from throwing the notice. Kinda like maybe "if( ! $File = & $FileCache->get_by_ID ..... ) continue" or maybe return false, but yeah I figured if I let you know the problem you'd find a solution a heck of a lot quicker and better than I could.

Aug 16, 2008 12:29

PHP

if ( $results->rows($file_number)->file_ID )
{
   $File = & $FileCache->get_by_ID$Results->rows[$file_number]->file_IDfalsefalse ); 
}

Good luck

Aug 16, 2008 12:34

SEE WHAT I MEAN!!!

I'd have never gotten there.

Thanks. You rock!

EDIT: oops - spoke too soon. using $results throws an notice for $results and a fatal error for "Call to a member function rows() on a non-object". In fact it kills the one image that happened (the most recent post has a linked image). Changing it to $Results removes the notice but retains the fatal error.

Aug 16, 2008 12:48

Changing that line to

Code

if( ! $File = & $FileCache->get_by_ID( $Results->rows[$file_number]->file_ID, false, false ) ) {
  return false;
  }
fixed the fatal error, but I still get a pair of notices thrown for each post that doesn't have a linked image.

<b>Notice</b>: Undefined offset: 0 in <b>/path_to/inc/files/model/_file.funcs.php</b> on line <b>740</b><br>
<br>
<b>Notice</b>: Trying to get property of non-object in <b>/path_to/inc/files/model/_file.funcs.php</b> on line <b>740</b><br>

It's kinda late. I'll try again tomorrow I guess. It'll be kinda fun to finish this and share the bit about how to add a widget directly instead of building a plugin. I think it saves on server power, and it definitely saves on the code you need to write and the steps you need to go through to use a new widget is the big deal there. To me anyway.

EDIT: I'll add my favorite "pre print_r( $thing ) /pre" later. That usually helps me find what I gotta do, though "usually" includes way back to the dawn of time more than in the latest and greatest releases. I'm pretty much an obsolete release kinda guy is why.

Aug 16, 2008 12:57

PHP

if ( $file_number )
{
    $File = & $FileCache->get_by_ID$Results->rows[$file_number]->file_IDfalsefalse )
}

&file_number == 0 can be legal I presume, then do

PHP

if ( $file_number > -)

--F

Aug 16, 2008 14:57

It's interesting, I use this function on 2 b2evo-2.4 and one b2evo-2.5 and never get any errors, it just returns false.

EDIT: You are right about the error, so I'll wait for your ideas ;)

Aug 16, 2008 18:05

I can't help but think yer over complicating this ... but for the life of me I can't remember which code snippet I saw that makes me think this .... it's in one of the files

.... or it could just be the mix of drugs and booze :D

¥

Aug 16, 2008 22:19

Okay I got lots of things that don't work, and one thing that does. ¥åßßå you are probably right - there is probably a much easier way. But what I found works and I think it is not too resource-heavy. I could be way wrong on that ...

Anyway the trick is to play with $Results from the "$Results->query( false, false, false );" line before trying to create $File. So I did a "print_r( $Results )" and saw 'result_num_rows' in there and recognized it. Unfortunately you can't really use it because it is part of an object, so I figured if I could make the object be an array I could ask it what the value of result_num_rows was. What I came up with was the following, including a wee bit of what there was both leading and trailing:

Code

$Results = & new Results( $SQL->get(), 'link_' );
    $Results->query( false, false, false );
 
    $Results_as_array = get_object_vars( $Results );
    if( $Results_as_array['result_num_rows'] > 0 ) {
      $File = & $FileCache->get_by_ID( $Results->rows[$file_number]->file_ID, false, false );
      } else {
      return false;
       }
 
    if( !is_object($File) && !$File->is_image() ) {
      return false;
       }
 
    return $File;

BTW in my test situation I simply added a post with a linked image to the linkblog. Thus I had posts without linked images. My real-world future application for this thing won't have situations like that, but clearly others might want to use it to pull images from a "mixed source" blog. So yeah this is a cool hack to a great hack.

Something else that dawned on me. Similar to the "hot topics" plugin, the value of $limit is a maximum with no promise that you will actually get that many. So what I'll do before I release this culmination of awesome hackage is have a "search limit" and "display limit" parameter so that I can say, for example, "search the last 10 posts but display no more than 5 images".

Soon!


Form is loading...

Advanced CMS – This forum is powered by b2evolution CMS, a complete engine for your website.