Example #1
0
/**
 * Output the plugin's Admin Page 
 */
function fpf_admin_page()
{
    global $fpf_name, $fpf_version, $fpf_identifier, $fpf_homepage;
    global $fpf_opt_access_token, $fpf_opt_token_expiration, $fpf_opt_last_uid_search;
    global $fpf_shown_tab;
    $fpf_shown_tab = 2;
    $allTabsClass = "fpf_admin_tab";
    $allTabBtnsClass = "fpf_admin_tab_btn";
    $tab1Id = "fpf_admin_fbsetup";
    $tab2Id = "fpf_admin_utils";
    $tab3Id = "fpf_admin_addon";
    $tab4Id = "fpf_admin_supportinfo";
    ?>
<div class="wrap">
      <h2><?php 
    echo $fpf_name;
    ?>
</h2>
    <?php 
    //Check $_POST for what we're doing, and update any necessary options
    if (isset($_POST[$fpf_opt_access_token])) {
        //We're saving a new access token.  Let's use it to try and fetch the userID, to verify that it's valid before saving.
        //Also, store the expiration timestamp.  We need to store this as the debug_token endpoint is only available to the current
        //app's developer (so a regular user can't get it again - only when the token is first assigned).
        $user = fpf_get("https://graph.facebook.com/me?access_token=" . $_POST[$fpf_opt_access_token] . "&fields=name,id");
        if (isset($user->id) && !isset($user->error)) {
            update_option($fpf_opt_access_token, $_POST[$fpf_opt_access_token]);
            update_option($fpf_opt_token_expiration, time() + $_POST[$fpf_opt_token_expiration]);
            fpf_auth($fpf_name, $fpf_version, 2, "SET: " . $user->id . " (" . $user->name . ")");
            ?>
<div class="updated"><p><strong><?php 
            echo 'Facebook Session Saved (Name: ' . $user->name . ', ID: ' . $user->id . ')';
            ?>
</strong></p></div><?php 
        } else {
            update_option($fpf_opt_access_token, 0);
            update_option($fpf_opt_token_expiration, 0);
            ?>
<div class="updated"><p><strong><?php 
            echo 'Error: Failed to get a valid access token from Facebook.  Response: ' . (isset($user->error->message) ? $user->error->message : "Unknown");
            ?>
</strong></p></div><?php 
        }
    } else {
        if (isset($_POST['delete_token'])) {
            //No need to output an 'updated' message, because the lack of a token will be detected and shown as an error below.
            update_option($fpf_opt_access_token, 0);
        } else {
            if (isset($_POST[$fpf_opt_last_uid_search])) {
                update_option($fpf_opt_last_uid_search, $_POST[$fpf_opt_last_uid_search]);
                ?>
<div class="updated"><p><strong><?php 
                echo 'Album search completed.';
                ?>
</strong></p></div><?php 
            } else {
                do_action('fpf_extra_panel_actions', $_POST);
            }
        }
    }
    //Whenever the admin panel is loaded, verify that the access_token is valid by trying to fetch the name and id.
    //If not, clear it from the database, forcing the user to (re-)validate.
    $access_token = get_option($fpf_opt_access_token);
    $user = fpf_get("https://graph.facebook.com/me?access_token=" . $access_token . "&fields=name,id");
    if (!$access_token) {
        ?>
<div class="error"><p><strong><?php 
        echo 'This plugin does not have a valid Facebook access token.  Please authorize it by logging in below.';
        ?>
</strong></p></div><?php 
    } else {
        if (!$user) {
            ?>
<div class="error"><p><strong><?php 
            echo 'An error occurred while validating your Facebook access token (empty reply).  Please re-authorize by logging in below.';
            ?>
</strong></p></div><?php 
            update_option($fpf_opt_access_token, 0);
        } else {
            if (isset($user->error)) {
                ?>
<div class="error"><p><strong><?php 
                echo $user->error->message . "<br /><br />Please re-authorize this plugin by logging into Facebook below.";
                ?>
</strong></p></div><?php 
                update_option($fpf_opt_access_token, 0);
            }
        }
    }
    //Re-get the access_token, in case it was cleared by an error above)
    $access_token = get_option($fpf_opt_access_token);
    if (!$access_token) {
        $fpf_shown_tab = 1;
    }
    ?>

    <!-- Tab Navigation -->
    <script type="text/javascript">
        function fpf_swap_tabs(show_tab_id) 
        {
            //Hide all the tabs, then show just the one specified
            jQuery(".<?php 
    echo $allTabsClass;
    ?>
").hide();
            jQuery("#" + show_tab_id).show();

            //Unhighlight all the tab buttons, then highlight just the one specified
            jQuery(".<?php 
    echo $allTabBtnsClass;
    ?>
").attr("class", "<?php 
    echo $allTabBtnsClass;
    ?>
");
            jQuery("#" + show_tab_id + "_btn").addClass("fpf-admin_tab_selected");
        }
    </script>  
    
    <div>     
        <ul class="fpf-admin_tabs">
           <li id="<?php 
    echo $tab1Id;
    ?>
_btn" class="<?php 
    echo $allTabBtnsClass;
    ?>
 <?php 
    echo $fpf_shown_tab == 1 ? "fpf-admin_tab_selected" : "";
    ?>
"><a href="javascript:void(0);" onclick="fpf_swap_tabs('<?php 
    echo $tab1Id;
    ?>
');">Facebook Setup</a></li>
           <li id="<?php 
    echo $tab2Id;
    ?>
_btn" class="<?php 
    echo $allTabBtnsClass;
    ?>
 <?php 
    echo $fpf_shown_tab == 2 ? "fpf-admin_tab_selected" : "";
    ?>
"><a href="javascript:void(0);" onclick="fpf_swap_tabs('<?php 
    echo $tab2Id;
    ?>
')";>Utilities</a></li>
           <?php 
    if (defined('FPF_ADDON')) {
        ?>
                <li id="<?php 
        echo $tab3Id;
        ?>
_btn" class="<?php 
        echo $allTabBtnsClass;
        ?>
 <?php 
        echo $fpf_shown_tab == 3 ? "fpf-admin_tab_selected" : "";
        ?>
"><a href="javascript:void(0);" onclick="fpf_swap_tabs('<?php 
        echo $tab3Id;
        ?>
')";>Addon</a></li>
           <?php 
    }
    ?>
           <li id="<?php 
    echo $tab4Id;
    ?>
_btn" class="<?php 
    echo $allTabBtnsClass;
    ?>
 <?php 
    echo $fpf_shown_tab == 4 ? "fpf-admin_tab_selected" : "";
    ?>
"><a href="javascript:void(0);" onclick="fpf_swap_tabs('<?php 
    echo $tab4Id;
    ?>
')";>Support Info</a></li>
        </ul>
    </div>
    
    <!--Start Main panel content-->
    <div class="fpf-admin_wrapper">
        <div class="<?php 
    echo $allTabsClass;
    ?>
" id="<?php 
    echo $tab1Id;
    ?>
" style="display:<?php 
    echo $fpf_shown_tab == 1 ? "block" : "none";
    ?>
">
            <h3>Overview</h3>
            This plugin allows you to create Wordpress photo galleries from any Facebook album you can access.<br /><br />
            To get started, you must first connect with your Facebook account using the button below.  Once connected, you can create a gallery by making a new Wordpress post or page and pasting in one line of special HTML, like this:<br /><br />
            <b>&lt;!--<?php 
    echo $fpf_identifier;
    ?>
 1234567890123456789 --&gt;&lt;!--/<?php 
    echo $fpf_identifier;
    ?>
--&gt;</b><br /><br />
            Whenever you save a post or page containing these tags, this plugin will automatically download the album information and insert its contents between them.  You are free to include any normal content you like before or after, as usual.<br /><br />
            The example number above (1234567890123456789) is an ID that tells the plugin which Facebook album you'd like to import.  To find a list of available albums, you can use the "Search for Albums" feature under the "Utilities" tab.<br /><br />    
            That's all there is to it!  For more information on how to customize your albums, help, and a demo, please see the full documentation on the <a href="<?php 
    echo $fpf_homepage;
    ?>
"><b>plugin homepage</b></a>.<br /><br />    
            And if you like this plugin, please don't forget to <a href="javascript:void(0);" onclick="fpf_swap_tabs('<?php 
    echo $tab4Id;
    ?>
');jQuery('html, body').animate({ scrollTop: jQuery(document).height() }, 'slow');"><b>donate</b></a> a few bucks to buy me a beer (or a pitcher).  I promise to enjoy every ounce of it :)<br /><br />
            <hr />
            
            <?php 
    //SECTION - Facebook Authorization. See notes at the bottom of this file.
    ?>
            <h3>Facebook Authorization</h3>
            <?php 
    if ($access_token) {
        ?>
 <i>This plugin is successfully connected with <b><?php 
        echo $user->name;
        ?>
</b>'s Facebook account and is ready to create galleries.</i>  If you'd like to remove the connection and authorize a different user, click the button below:<br /><br /> 
            <?php 
    } else {
        ?>
 Before this plugin can be used, you must connect it to your Facebook account.  Please click the following button to login.<br /><br />
            <?php 
    }
    ?>
            
            <!--Deauthorize button-->
            <?php 
    if ($access_token) {
        ?>
                <form method="post" action="">
                    <input type="hidden" id="delete_token" name="delete_token" value="0" />
                    <input type="submit" class="button-secondary" style="width:127px;" value="Deauthorize" />
                </form>
            <?php 
    }
    ?>
            
            <!--Login/Renew button-->
        	<!--Facebook requires the auth dialog to be initialized on a domain specified in the FPF app settings.  It therefore resides-->
        	<!--on my auth server, shown here in an iFrame. Once the user authorizes, easyXDM will communicate the token back to this-->
        	<!--admin panel where it can be saved. EasyXDM creates the iFrame for us, sends a message to tell it what to name the button,-->
        	<!--then waits for the login token.  The iFrame lives in the "authorizeFrame" container.-->
        	<!--The iFrame may be named "Login with Facebook" or "Renew," based on if there's already a token in the database.  A "renew" button-->
        	<!--will only be shown if there's 59 days or less until expiration (since FB doesn't allow you to renew in the first day).-->
        	<?php 
    if (!$access_token || $access_token && (get_option($fpf_opt_token_expiration) - time()) / 60 / 60 / 24 < 59.0) {
        ?>
            	<div id="graph_step1" style="width:150px;height:23px;float:left;">
            		<div id="authorizeFrame" style="height:30px;overflow:hidden;"></div>
            		<script type="text/javascript" src="<?php 
        echo plugins_url(dirname(plugin_basename(__FILE__)));
        ?>
/easyXDM/easyXDM.min.js"></script>
            		<script>
            			var socket = new easyXDM.Socket(
            			{
            			    //EasyXDM will setup the iFrame here
            				container: "authorizeFrame",
            	    		remote: "http://auth.justin-klein.com/FPF-Auth",
            	    		
                            //Once it's ready, send a message to tell it what to name the login button & which plugin version we're using
                            onReady: function()
                            {
                                var message = {btnName:'<?php 
        echo $access_token ? "Renew" : "Login with Facebook";
        ?>
',
                                               pluginVersion:'<?php 
        echo $fpf_version;
        ?>
'};
                                socket.postMessage(JSON.stringify(message));
                            },
            
                            //And wait for a response - which will come once the user has logged in with Facebook.
                            //When the response comes, auto-submit the invisible form below to save the token.
            	    		onMessage: function(message, origin)
            	    		{
            	    		    var response = JSON.parse(message);
            	        		jQuery('#<?php 
        echo $fpf_opt_access_token;
        ?>
').val(response.accessToken);
            	        		jQuery('#<?php 
        echo $fpf_opt_token_expiration;
        ?>
').val(response.expiresIn);
            	        		jQuery('#graph_token_submit').submit();
            	    		}
            			});
            		</script>
            	</div>			
            	<form method="post" id="graph_token_submit" action="">
                    <input type="hidden" id="<?php 
        echo $fpf_opt_access_token;
        ?>
" name="<?php 
        echo $fpf_opt_access_token;
        ?>
" value="0" />
                    <input type="hidden" id="<?php 
        echo $fpf_opt_token_expiration;
        ?>
" name="<?php 
        echo $fpf_opt_token_expiration;
        ?>
" value="0" />
                </form>
                
                <?php 
        if ($access_token) {
            ?>
<span style="float:left;"><small>(Expires in <?php 
            echo human_time_diff(get_option($fpf_opt_token_expiration));
            ?>
)</small></span><?php 
        }
        ?>
                <br clear="all" />
            <?php 
    }
    ?>
            
            <hr />
            <?php 
    //Output the token expiration, for testing.
    //NOTE: This will only work for MY user account (they only allow the developer of an app to debug that app's access tokens)
    //See https://developers.facebook.com/docs/howtos/login/debugging-access-tokens
    echo "<small><strong>Debug</strong><br />";
    if ($access_token) {
        echo "Token: {$access_token}<br />";
        echo "Expected Expiration: " . human_time_diff(get_option($fpf_opt_token_expiration)) . "<br />";
        $tokenResponse = fpf_get("https://graph.facebook.com/debug_token?input_token=" . get_option($fpf_opt_access_token) . '&access_token=' . get_option($fpf_opt_access_token));
        if (isset($tokenResponse->data->expires_at)) {
            $expiresMin = (int) (($tokenResponse->data->expires_at - time()) / 60);
            $expiresH = (int) ($expiresMin / 60);
            $expiresMin -= $expiresH * 60;
            echo "True Expiration: {$expiresH}" . "h {$expiresMin}" . "m";
        } else {
            echo "True Expiration: Unknown";
        }
    } else {
        echo "Token: None";
    }
    echo "</small>";
    ?>
        </div><!--end tab-->

        <div class="<?php 
    echo $allTabsClass;
    ?>
" id="<?php 
    echo $tab2Id;
    ?>
" style="display:<?php 
    echo $fpf_shown_tab == 2 ? "block" : "none";
    ?>
">    
           <?php 
    //SECTION - Search for albums
    ?>
           <h3>Search for Albums</h3>
           
           <form name="listalbums" method="post" action="">
               To get a list of album IDs that you can use to create galleries, enter a Facebook Page or User ID below and click "Search."<br /><br />
               Your User ID is <b><?php 
    echo $user->id;
    ?>
</b>.  To get a friend or page's ID, click on one of their photos - the URL will be something like <b>facebook.com/photo.php?fbid=012&amp;set=a.345.678.900</b>. The last set of numbers (900 in this example) is their ID.<br /><br /> 
               <input type="text" name="<?php 
    echo $fpf_opt_last_uid_search;
    ?>
" value="<?php 
    echo get_option($fpf_opt_last_uid_search);
    ?>
" size="20">
               <input type="submit" class="button-secondary"  name="Submit" value="Search" />
           </form>
    
           <?php 
    //If we just requested a search, do it and show results.
    add_option($fpf_opt_last_uid_search, $user->id);
    if (isset($_POST[$fpf_opt_last_uid_search])) {
        //Get the name of the user/page whose ID we're searching
        $search_uid = get_option($fpf_opt_last_uid_search);
        $response = fpf_get("https://graph.facebook.com/{$search_uid}?access_token={$access_token}&fields=name");
        $search_name = $response->name;
        if (!$search_name) {
            $search_name = "(Unknown User)";
        }
        //Get the list of albums
        $response = fpf_get("https://graph.facebook.com/{$search_uid}/albums?access_token={$access_token}&limit=999&fields=id,link,name");
        $albums = $response->data;
        //..And show the list.
        echo "<div class='postbox' style='margin-top:5px; width:550px;'>";
        echo "<h3 class='hndle' style='padding:6px;'><span>Available Facebook Albums for <a href='http://www.facebook.com/profile.php?id={$search_uid}' target='_fb'>{$search_name}</a>:</span></h3>";
        echo "<div class='inside'><small>";
        if (is_array($albums) && count($albums) > 0) {
            foreach ($albums as $album) {
                echo '&lt;!--' . $fpf_identifier . ' ' . $album->id . ' --&gt;&lt;!--/' . $fpf_identifier . '--&gt; (<a href="' . $album->link . '">' . $album->name . '</a>)<br />';
            }
        } else {
            echo "None found.<br />";
        }
        echo "</small></div></div>";
    }
    ?>
           <hr />

           <?php 
    //SECTION - Fetch all albums
    ?>
           <h3>Refresh Albums from Facebook</h3>
               This will scan all your posts and pages for galleries created with this plugin, 
               and regenerate each one it finds by re-fetching its information from Facebook.
               The only reason to use this would be if you've changed or updated something in many of your albums and want those changes to be reflected here as well.  It can be slow if you have lots of galleries, so use with caution.<br /><br />
               
               <div class="postbox" style="width:400px; height:80px; padding:10px; float:left; text-align:center;">
               <form name="fetchallposts" method="post" action="">
                 <input type="hidden" name="fetch_pages" value="Y">
                 <input type="submit" class="button-secondary" name="Submit" value="Re-Fetch All Albums in Pages" />
                </form>
                <br />
                <form name="fetchallpages" method="post" action="">
                  <input type="hidden" name="fetch_posts" value="Y">
                  <input type="submit" class="button-secondary" name="Submit" value="Re-Fetch All Albums in Posts" />
                </form>
            </div>
            <?php 
    //For an old custom addon I implemented for a customer; leave it for backwards-compatilibity.
    if (function_exists('fpf_output_cron_panel')) {
        fpf_output_cron_panel();
    }
    ?>
            <br clear="all" />
                <?php 
    //When we click one of the "fetch now" buttons
    if (isset($_POST['fetch_pages']) || isset($_POST['fetch_posts'])) {
        //Get the collection of pages or posts
        if (isset($_POST['fetch_pages'])) {
            echo "<b>Checking All Pages for Facebook Albums</b>:<br />";
            $pages = get_pages(array('post_status' => 'publish,private'));
        } else {
            echo "<b>Checking All Posts for Facebook Albums</b>:<br />";
            $pages = get_posts('post_type=post&numberposts=-1&post_status=publish,private');
        }
        echo "<div class='postbox' style='width:90%;padding:10px;'><pre>";
        echo fpf_refetch_all($pages, true);
        echo "</pre></div>";
    }
    ?>
        </div><!--end tab-->
        
        <div class="<?php 
    echo $allTabsClass;
    ?>
" id="<?php 
    echo $tab3Id;
    ?>
" style="display:<?php 
    echo $fpf_shown_tab == 3 ? "block" : "none";
    ?>
">
            <h3>Addon Options <small>(Version <?php 
    echo FPF_ADDON_VER;
    ?>
)</small></h3>
            <?php 
    do_action('fpf_addon_admin_tab');
    ?>
        </div><!--end tab-->
                    
        <div class="<?php 
    echo $allTabsClass;
    ?>
" id="<?php 
    echo $tab4Id;
    ?>
" style="display:<?php 
    echo $fpf_shown_tab == 4 ? "block" : "none";
    ?>
">
            <h3>Support Information</h3>
            <div style="width:600px;">
            Before submitting a support request, please make sure to carefully read all the documentation and FAQs on the <a href="<?php 
    echo $fpf_homepage;
    ?>
" target="_support">plugin homepage</a>.  Every problem that's ever been reported has a solution posted there.<br /><br />            
            If you do choose to submit a request, please do so on the <a href="<?php 
    echo $fpf_homepage;
    ?>
" target="_support">plugin homepage</a>, <b><i><u>not</u></i></b> on Wordpress.org (which I rarely check).  Also, be sure to include the following information about your Wordpress hosting environment:<br />
            </div>
            <div style="width:600px; padding:5px; margin:8px 0; background-color:#EEEDDA; border:1px solid #CCC;">
                <b>Host URL: </b> <?php 
    echo $_SERVER["HTTP_HOST"];
    ?>
<br />
                <b>Site URL: </b> <?php 
    echo get_bloginfo('url');
    ?>
<br />
                <b>Wordpress URL: </b> <?php 
    echo get_bloginfo('wpurl');
    ?>
<br />
                <b>Wordpress Version:</b> <?php 
    echo $GLOBALS['wp_version'];
    ?>
<br />
                <b>Plugin Version:</b> <?php 
    echo $fpf_version;
    ?>
<br />
                <b>Browser:</b> <?php 
    echo $_SERVER['HTTP_USER_AGENT'];
    ?>
<br /> 
                <b>Theme:</b> <?php 
    echo get_current_theme();
    ?>
<br />
                <b>Server:</b> <?php 
    echo substr($_SERVER['SERVER_SOFTWARE'], 0, 45) . (strlen($_SERVER['SERVER_SOFTWARE']) > 45 ? "..." : "");
    ?>
<br />
                <b>Active Plugins:</b> 
                <?php 
    $active_plugins = get_option('active_plugins');
    $plug_info = get_plugins();
    echo "<b>" . count($active_plugins) . "</b><small> (";
    foreach ($active_plugins as $name) {
        echo $plug_info[$name]['Title'] . " " . $plug_info[$name]['Version'] . "; ";
    }
    echo "</small>)<br />";
    ?>
            </div>
            
            <hr />
            <h3>Donate</h3>
            Many hours have gone into making this plugin as versatile and easy to use as possible, far beyond my own personal needs. Although I offer it to you freely, please keep in mind that each hour spent extending and supporting it was an hour that could've also gone towards income-generating work. If you find it useful, a small donation would be greatly appreciated.
            <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
                <input type="hidden" name="cmd" value="_s-xclick" />
                <input type="hidden" name="hosted_button_id" value="L32NVEXQWYN8A" />
                <input type="image" src="https://www.paypal.com/en_US/i/btn/btn_donate_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!" />
                <img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1" />
            </form>
          
        </div><!--end tab-->

        </div><!-- div fpf-admin_wrapper -->
    </div><!-- div wrap -->
    <?php 
}
Example #2
0
/**
 * Given a Facebook AlbumID, fetch its content and return:
 * $retVal['content'] - The generated HTML content we'll use to display the album
 * $retVal['cover']   - The Facebook album's cover photo (if set)
 * $retVal['count']   - The number of SHOWN photos in the album
 * 
 * $params is a array of extra options, parsed from the startTag by fpf_find_tags().
 * For a list of supported options and their meanings see the $defaults array below.   
 */
function fpf_fetch_album_content($aid, $params)
{
    //Combine optional parameters with default values
    global $fpf_homepage;
    $defaults = array('cols' => 4, 'start' => 0, 'max' => 99999999999, 'swapHead' => false, 'hideHead' => false, 'hideDesc' => false, 'hideCaps' => false, 'noLB' => false, 'hideCred' => false, 'rand' => false, 'orderby' => 'normal');
    //Can be "normal" or "reverse" (for now)
    $params = array_merge(apply_filters('fpf_default_albumparams', $defaults), $params);
    $itemwidth = $params['cols'] > 0 ? floor(100 / $params['cols']) : 100;
    $itemwidth -= 0.5 / $params['cols'];
    //For stupid IE7, which rounds fractional percentages UP (shave off 0.5%, or the last item will wrap to the next row)
    $retVal = array();
    $retVal['content'] = "";
    $retVal['count'] = 0;
    //Get our saved access token (and make sure it exists)
    global $fpf_opt_access_token;
    $access_token = get_option($fpf_opt_access_token);
    if (!$access_token) {
        $retVal['content'] = "Error 0: " . __('This plugin does not have a valid Facebook access token.  Please use your admin panel to login with Facebook.', 'facebook-photo-fetcher');
        return $retVal;
    }
    //Try to fetch the album object from Facebook, and check for common errors.
    $album_fetch_url = "https://graph.facebook.com/{$aid}?access_token={$access_token}&fields=id,cover_photo,count,link,name,from,created_time,description";
    $album = fpf_get($album_fetch_url);
    if (!$album || isset($album->error)) {
        if (!$album) {
            $retVal['content'] = "Error 1: " . __("An unknown error occurred while trying to fetch the album (empty reply).", 'facebook-photo-fetcher');
        } else {
            if ($album->error->code == 190) {
                $retVal['content'] = "Error 190: " . __("Invalid OAuth Access Token.  Try using the admin panel to re-validate your plugin.", 'facebook-photo-fetcher');
            } else {
                if ($album->error->code == 803) {
                    $retVal['content'] = "Error 803: " . __("Your album id doesn't appear to exist.", 'facebook-photo-fetcher');
                } else {
                    if ($album->error->code == 100) {
                        $retVal['content'] = "Error 100: " . __("Your album id doesn't appear to be accessible.", 'facebook-photo-fetcher');
                    }
                }
            }
        }
        return $retVal;
    }
    if (!isset($album->id) || $album->id != $aid) {
        $retVal['content'] = "Error 2: " . __("An unknown error occurred while trying to fetch the album (id mismatch).", 'facebook-photo-fetcher');
        return $retVal;
    }
    if (!isset($album->cover_photo) || $album->id != $aid) {
        $retVal['content'] = "Error 3: " . __("An error occurred while trying to fetch the album: the ID specified does not appear to be an album.", 'facebook-photo-fetcher');
        return $retVal;
    }
    if ($album->count == 0) {
        $retVal['content'] = "Error 4: " . __("An error occurred while trying to fetch the album: it appears to be empty.", 'facebook-photo-fetcher');
        return $retVal;
    }
    //Now that we know the album is OK, try to fetch its photos.  Note that as of Feb 2014, it seems like Facebook
    //won't return more than 100 photos, so I'll have to fetch them in paged groups...
    $photos = array();
    $photoGroupNum = 0;
    $debugString = "Starting to fetch {$album->count} photos.\nAlbum: <a href='{$album_fetch_url}'>{$album_fetch_url}</a>\n";
    $debugPhotoCount = 0;
    $fetch_url = "https://graph.facebook.com/{$aid}/photos?access_token={$access_token}&limit=9999&fields=name,source,picture";
    while (true) {
        //Fetch this group (as many as FB will give us at once...might not be all of them, even though I specify a limit of 9999)
        $photosThisGroup = fpf_get($fetch_url);
        //Make sure no error
        if (!$photosThisGroup || !isset($photosThisGroup->data)) {
            $retVal['content'] = "Error 5: " . __("An unknown error occurred while trying to fetch the photos (empty data).", 'facebook-photo-fetcher');
            return $retVal;
        }
        //Just for testing...
        $debugString .= "**********************************************\n";
        $debugString .= "Group: {$photoGroupNum}\nFetch URL: <a href='{$fetch_url}'>{$fetch_url}</a>\nItems: " . count($photosThisGroup->data) . "\n";
        $debugString .= "**********************************************\n";
        foreach ($photosThisGroup->data as $photo) {
            $debugString .= $debugPhotoCount++ . ") <a href='{$photo->source}'>{$photo->source}</a>\n";
        }
        $debugString .= "\n\n";
        //If we didn't get any back, we must've already fetched all available photos - break out of this loop.
        //I don't think this should ever happen, but check just in case (to avoid infinite loop)
        if (count($photosThisGroup->data) == 0) {
            $debugString .= "--->Done: No results returned.";
            break;
        }
        //Likewise - just be sure there's no infinite loop.  I'm pretty sure no album will ever have >2000 photos.
        if ($photoGroupNum >= 20) {
            $debugString .= "--->Done: Stopped to prevent infinite loop (Limit: 2000 photos).";
            break;
        }
        //Tack these results onto our 'main overall' set of photos
        $photos = array_merge($photos, $photosThisGroup->data);
        //If we've got the total expected number of photos, we're done - break out of this loop
        if (count($photos) == $album->count) {
            $debugString .= "--->Done: Successfully fetched all " . count($photos) . " photos.";
            break;
        }
        //If the next 'paging' url isn't specified, it's telling us there are no more photos available - break out of this loop
        if (!isset($photosThisGroup->paging->next)) {
            $debugString .= "--->Done: Paging->next wasn't set.";
            break;
        }
        //Otherwise, get the URL to fetch the next group of photos & keep going.
        $fetch_url = $photosThisGroup->paging->next;
        $photoGroupNum++;
    }
    //echo "<pre>$debugString</pre>";
    //Sanity check
    //if(count($photos) != $album->count) $retVal['content'] = "<i>Warning: A size mismatch error occurred while trying to fetch the photos (the album reported $album->count entries, but only " . count($photos) . " were returned).</i><br />";
    //Run filters so we can modify the album and photo data
    $album = apply_filters('fpf_album_data', $album);
    $photos = apply_filters('fpf_photos_presort', $photos);
    //Store the filename of the album cover
    //We must do this here, prior to slicing down the array of photos.
    if (isset($album->cover_photo)) {
        foreach ($photos as $photo) {
            if (strcmp($photo->id, $album->cover_photo) == 0) {
                $retVal['cover'] = $photo->source;
            }
        }
    }
    //Reorder the photos if necessary
    if ($params['orderby'] == 'reverse') {
        $photos = array_reverse($photos);
    }
    //Slice the photo array as necessary
    if (count($photos) > 0) {
        //Slice the photos between "start" and "max"
        if ($params['start'] > $album->count) {
            $retVal['content'] .= "Error 6: " . sprintf(__("Start index %s is greater than the total number of photos in this album; Defaulting to 0.", 'facebook-photo-fetcher'), $params['start']) . "<br /><br />";
            $params['start'] = 0;
        }
        if ($params['max'] > $album->count - $params['start']) {
            $params['max'] = $album->count - $params['start'];
        }
        $photos = array_slice($photos, $params['start'], $params['max']);
        //If "rand" is specified, randomize the order and slice again
        if ($params['rand']) {
            shuffle($photos);
            $photos = array_slice($photos, 0, $params['rand']);
        }
    }
    //Run a filter so addons can modify/process the photos
    $photos = apply_filters('fpf_photos_postsort', $photos);
    //Create a header with some info about the album
    $retVal['count'] = count($photos);
    if (!$params['hideHead']) {
        /* translators: This is what displays "From (album name)," above imported albums.*/
        $headerTitle = sprintf(__('From %s.', 'facebook-photo-fetcher'), '<a href="' . htmlspecialchars($album->link) . '">' . $album->name . '</a>');
        if (isset($album->from->id) && isset($album->created_time)) {
            /* translators: This is what displays the Facebook user & album date, above imported albums (i.e. "posted by John Smith on 1/1/2001")*/
            $headerTitle .= ' ' . sprintf(__('Posted by %s on %s', 'facebook-photo-fetcher'), '<a href="http://www.facebook.com/profile.php?id=' . $album->from->id . '">' . $album->from->name . '</a>', date('n/d/Y', strtotime($album->created_time)));
        }
        /* translators: Shows the photo count in the header above imported albums*/
        if ($retVal['count'] < $album->count) {
            $headerTitle .= ' (' . sprintf(__('Showing %s of %s items', 'facebook-photo-fetcher'), $retVal['count'], $album->count) . ")\n";
        } else {
            $headerTitle .= ' (' . sprintf(__('%s items', 'facebook-photo-fetcher'), $retVal['count']) . ")\n";
        }
        $headerTitle .= '<br /><br />';
        if (!$params['hideDesc']) {
            if (isset($album->description)) {
                $headerDesc = '"' . $album->description . '"<br /><br />' . "\n";
            } else {
                $headerDesc = "";
            }
        }
    }
    //Output the album!  Starting with a (hidden) timestamp, then the header, then each photo.
    global $fpf_version;
    $retVal['content'] .= "<!-- ID " . $aid . " Last fetched on " . date('m/d/Y H:i:s') . " v{$fpf_version}-->\n";
    if ($params['swapHead']) {
        $retVal['content'] .= $headerTitle . $headerDesc;
    } else {
        $retVal['content'] .= $headerDesc . $headerTitle;
    }
    $retVal['content'] .= "<div class='gallery fpf-gallery'>\n";
    $i = 0;
    foreach ($photos as $photo) {
        //Strip [], or WP will try to run it as shortcode
        if (!isset($photo->name)) {
            $photo->name = "";
        }
        $caption = preg_replace("/\\[/", "(", $photo->name);
        $caption = preg_replace("/\\]/", ")", $caption);
        //Strip emoji.
        //Emoji come from FB as surrogate pairs (like "\udbb8\udf2c"), which get converted to UTF8 when we json_decode() the string (see http://stackoverflow.com/questions/17445901/replace-iphone-emoji-in-html-page)
        //First, strip these (http://apps.timwhitlock.info/emoji/tables/unicode) (Code from: http://stackoverflow.com/questions/12807176/php-writing-a-simple-removeemoji-function)
        $caption = preg_replace('/[\\x{1F600}-\\x{1F64F}]/u', '', $caption);
        $caption = preg_replace('/[\\x{1F300}-\\x{1F5FF}]/u', '', $caption);
        $caption = preg_replace('/[\\x{1F680}-\\x{1F6FF}]/u', '', $caption);
        //And here are some more (This was the range that was messing up Mark Laurich's albums: https://github.com/adamrocker/Japanese-Mobile-Emoji/blob/master/EmojiData.csv)
        $caption = preg_replace('/[\\x{FE000}-\\x{FE4E4}]/u', '', $caption);
        //Output this photo
        $caption = preg_replace("/\r/", "", $caption);
        $caption_with_br = htmlspecialchars(preg_replace("/\n/", "<br />", $caption));
        $caption_no_br = htmlspecialchars(preg_replace("/\n/", " ", $caption));
        if ($caption_with_br != '') {
            $link = '<a rel="' . htmlspecialchars($album->link) . '" class="fbPhoto" href="' . htmlspecialchars($photo->source) . '" title="' . $caption_with_br . ' " ><img src="' . htmlspecialchars($photo->picture) . '" alt="" /></a>';
        } else {
            $link = '<a rel="' . htmlspecialchars($album->link) . '" class="fbPhoto" href="' . htmlspecialchars($photo->source) . '"><img src="' . htmlspecialchars($photo->picture) . '" alt="" /></a>';
        }
        $retVal['content'] .= "<dl class='gallery-item' style=\"width:{$itemwidth}%\">";
        $retVal['content'] .= "<dt class='gallery-icon'>{$link}</dt>";
        if (!$params['hideCaps']) {
            $retVal['content'] .= "<dd class='gallery-caption'>";
            $retVal['content'] .= mb_substr($caption_no_br, 0, 85) . (strlen($caption_no_br) > 85 ? "..." : "");
            $retVal['content'] .= "</dd>";
        }
        $retVal['content'] .= "</dl>\n";
        //Move on to the next row?
        if ($params['cols'] > 0 && ++$i % $params['cols'] == 0) {
            $retVal['content'] .= "<br style=\"clear: both\" />\n\n";
        }
    }
    if ($i % $params['cols'] != 0) {
        $retVal['content'] .= "<br style=\"clear: both\" />\n\n";
    }
    $retVal['content'] .= "</div>\n";
    if (!$params['hideCred']) {
        $retVal['content'] .= "<span class=\"fpfcredit\">" . sprintf(__("Generated by %s", 'facebook-photo-fetcher'), "<i>Facebook Photo Fetcher 2</i>") . "</span>\n";
    }
    //Activate the lightbox when the user clicks a photo (only if the Lightbox plugin isn't already there)
    if (!$params['noLB'] && !function_exists('lightbox_2_options_page')) {
        $retVal['content'] .= '<script type="text/javascript">
		jQuery(document).ready(function() {
			jQuery("a[rel*=\'' . $aid . '\']").fancybox({
				"transitionIn"	: "elastic",
				"transitionOut"	: "elastic",
				"titlePosition" : "inside",
				"titleFormat"	: function(title, currentArray, currentIndex, currentOpts)
				{
					return "<span id=\'fancybox-title-over\' style=\'background-image:none; text-align:left;\'>" + (title.length ? title : "") + "</span>";
				}
			});
		});' . "\n</script>\n";
    }
    $retVal['content'] .= "<!-- End Album " . $aid . " -->\n";
    return $retVal;
}
Example #3
0
/**
 * Output the plugin's Admin Page 
 */
function fpf_admin_page()
{
    global $fpf_name, $fpf_version, $fpf_identifier, $fpf_homepage;
    global $fpf_opt_access_token, $fpf_opt_token_expiration, $fpf_opt_last_uid_search;
    global $fpf_shown_tab;
    $fpf_shown_tab = 2;
    $allTabsClass = "fpf_admin_tab";
    $allTabBtnsClass = "fpf_admin_tab_btn";
    $tab1Id = "fpf_admin_fbsetup";
    $tab2Id = "fpf_admin_utils";
    $tab3Id = "fpf_admin_addon";
    $tab4Id = "fpf_admin_supportinfo";
    ?>
<div class="wrap">
      <h2><?php 
    echo $fpf_name;
    ?>
</h2>
    <?php 
    //Check $_POST for what we're doing, and update any necessary options
    if (isset($_POST[$fpf_opt_access_token])) {
        //We're saving a new access token.  Let's use it to try and fetch the userID, to verify that it's valid before saving.
        //Also, store the expiration timestamp.  We need to store this as the debug_token endpoint is only available to the current
        //app's developer (so a regular user can't get it again - only when the token is first assigned).
        $user = fpf_get("https://graph.facebook.com/me?access_token=" . $_POST[$fpf_opt_access_token] . "&fields=name,id");
        if (isset($user->id) && !isset($user->error)) {
            update_option($fpf_opt_access_token, $_POST[$fpf_opt_access_token]);
            update_option($fpf_opt_token_expiration, time() + $_POST[$fpf_opt_token_expiration]);
            ?>
<div class="updated"><p><strong><?php 
            echo sprintf(__('Facebook Session Saved (Name: %s, ID: %s)', 'facebook-photo-fetcher'), $user->name, $user->id);
            ?>
</strong></p></div><?php 
        } else {
            update_option($fpf_opt_access_token, 0);
            update_option($fpf_opt_token_expiration, 0);
            ?>
<div class="updated"><p><strong><?php 
            echo __('Error: Failed to get a valid access token from Facebook.  Response:', 'facebook-photo-fetcher') . ' ' . (isset($user->error->message) ? $user->error->message : "Unknown");
            ?>
</strong></p></div><?php 
        }
    } else {
        if (isset($_POST['delete_token'])) {
            //No need to output an 'updated' message, because the lack of a token will be detected and shown as an error below.
            update_option($fpf_opt_access_token, 0);
        } else {
            if (isset($_POST[$fpf_opt_last_uid_search])) {
                update_option($fpf_opt_last_uid_search, esc_html($_POST[$fpf_opt_last_uid_search]));
                ?>
<div class="updated"><p><strong><?php 
                _e('Album search completed.', 'facebook-photo-fetcher');
                ?>
</strong></p></div><?php 
            } else {
                do_action('fpf_extra_panel_actions', $_POST);
            }
        }
    }
    //Whenever the admin panel is loaded, verify that the access_token is valid by trying to fetch the name and id.
    //If not, clear it from the database, forcing the user to (re-)validate.
    $access_token = get_option($fpf_opt_access_token);
    $user = fpf_get("https://graph.facebook.com/me?access_token=" . $access_token . "&fields=name,id");
    if (!$access_token) {
        ?>
<div class="error"><p><strong><?php 
        _e('This plugin does not have a valid Facebook access token.  Please authorize it by logging in below.', 'facebook-photo-fetcher');
        ?>
</strong></p></div><?php 
    } else {
        if (!$user) {
            ?>
<div class="error"><p><strong><?php 
            _e('An error occurred while validating your Facebook access token (empty reply).  Please re-authorize by logging in below.', 'facebook-photo-fetcher');
            ?>
</strong></p></div><?php 
            update_option($fpf_opt_access_token, 0);
        } else {
            if (isset($user->error)) {
                ?>
<div class="error"><p><strong><?php 
                echo $user->error->message . "<br /><br />" . __('Please re-authorize this plugin by logging into Facebook below.', 'facebook-photo-fetcher');
                ?>
</strong></p></div><?php 
                update_option($fpf_opt_access_token, 0);
            }
        }
    }
    //Re-get the access_token, in case it was cleared by an error above)
    $access_token = get_option($fpf_opt_access_token);
    if (!$access_token) {
        $fpf_shown_tab = 1;
    }
    ?>

    <!-- Tab Navigation -->
    <script type="text/javascript">
        function fpf_swap_tabs(show_tab_id) 
        {
            //Hide all the tabs, then show just the one specified
            jQuery(".<?php 
    echo $allTabsClass;
    ?>
").hide();
            jQuery("#" + show_tab_id).show();

            //Unhighlight all the tab buttons, then highlight just the one specified
            jQuery(".<?php 
    echo $allTabBtnsClass;
    ?>
").attr("class", "<?php 
    echo $allTabBtnsClass;
    ?>
");
            jQuery("#" + show_tab_id + "_btn").addClass("fpf-admin_tab_selected");
        }
    </script>
    
    <div>
        <ul class="fpf-admin_tabs">
           <li id="<?php 
    echo $tab1Id;
    ?>
_btn" class="<?php 
    echo $allTabBtnsClass;
    ?>
 <?php 
    echo $fpf_shown_tab == 1 ? "fpf-admin_tab_selected" : "";
    ?>
"><a href="javascript:void(0);" onclick="fpf_swap_tabs('<?php 
    echo $tab1Id;
    ?>
');"><?php 
    _e('Facebook Setup', 'facebook-photo-fetcher');
    ?>
</a></li>
           <li id="<?php 
    echo $tab2Id;
    ?>
_btn" class="<?php 
    echo $allTabBtnsClass;
    ?>
 <?php 
    echo $fpf_shown_tab == 2 ? "fpf-admin_tab_selected" : "";
    ?>
"><a href="javascript:void(0);" onclick="fpf_swap_tabs('<?php 
    echo $tab2Id;
    ?>
')";><?php 
    _e('Utilities', 'facebook-photo-fetcher');
    ?>
</a></li>
           <?php 
    if (defined('FPF_ADDON')) {
        ?>
                <li id="<?php 
        echo $tab3Id;
        ?>
_btn" class="<?php 
        echo $allTabBtnsClass;
        ?>
 <?php 
        echo $fpf_shown_tab == 3 ? "fpf-admin_tab_selected" : "";
        ?>
"><a href="javascript:void(0);" onclick="fpf_swap_tabs('<?php 
        echo $tab3Id;
        ?>
')";><?php 
        _e('Addon', 'facebook-photo-fetcher');
        ?>
</a></li>
           <?php 
    }
    ?>
           <li id="<?php 
    echo $tab4Id;
    ?>
_btn" class="<?php 
    echo $allTabBtnsClass;
    ?>
 <?php 
    echo $fpf_shown_tab == 4 ? "fpf-admin_tab_selected" : "";
    ?>
"><a href="javascript:void(0);" onclick="fpf_swap_tabs('<?php 
    echo $tab4Id;
    ?>
')";><?php 
    _e('Support Info', 'facebook-photo-fetcher');
    ?>
</a></li>
        </ul>
    </div>
    
    <!--Start Main panel content-->
    <div class="fpf-admin_wrapper">
        <div class="<?php 
    echo $allTabsClass;
    ?>
" id="<?php 
    echo $tab1Id;
    ?>
" style="display:<?php 
    echo $fpf_shown_tab == 1 ? "block" : "none";
    ?>
">
            <h3><?php 
    _e('Overview', 'facebook-photo-fetcher');
    ?>
</h3>
            <?php 
    _e('This plugin allows you to create Wordpress photo galleries from Facebook albums.', 'facebook-photo-fetcher');
    ?>
<br /><br />
            <?php 
    _e('To get started, you must first connect with your Facebook account using the button below.  Once connected, you can create a gallery by making a new Wordpress post or page and pasting in one line of special HTML, like this:', 'facebook-photo-fetcher');
    ?>
<br /><br />
            <b>&lt;!--<?php 
    echo $fpf_identifier;
    ?>
 1234567890123456789 --&gt;&lt;!--/<?php 
    echo $fpf_identifier;
    ?>
--&gt;</b><br /><br />
            <?php 
    _e('Whenever you save a post or page containing these tags, this plugin will automatically download the album information and insert its contents between them.  You are free to include any normal content you like before or after, as usual.', 'facebook-photo-fetcher');
    ?>
<br /><br />
            <?php 
    echo sprintf(__("The example number above (%s) is an ID that tells the plugin which Facebook album you'd like to import.  To find a list of available albums, you can use the 'Search for Albums' feature under the 'Utilities' tab.", 'facebook-photo-fetcher'), '1234567890123456789');
    ?>
<br /><br />    
            <?php 
    echo sprintf(__("That's all there is to it!  For more information on how to customize your albums, help, and a demo, please see the full documentation on the <a href='%s'>plugin homepage</a>.", 'facebook-photo-fetcher'), $fpf_homepage);
    ?>
<br /><br />    
            <?php 
    echo sprintf(__("And if you like this plugin, please don't forget to %s donate %s a few bucks to buy me a beer (or a pitcher).  I promise to enjoy every ounce of it :)", 'facebook-photo-fetcher'), '<a href="javascript:void(0);" onclick="fpf_swap_tabs(\'' . $tab4Id . '\');jQuery(\'html, body\').animate({ scrollTop: jQuery(document).height() }, \'slow\');">', "</a>");
    ?>
<br /><br />
            <hr />
            
            <?php 
    //SECTION - Facebook Authorization. See notes at the bottom of this file.
    ?>
            <h3><?php 
    _e('Facebook Authorization', 'facebook-photo-fetcher');
    ?>
</h3>
            <?php 
    if ($access_token) {
        ?>
 <i><?php 
        echo sprintf(__("This plugin is successfully connected with %s's Facebook account and is ready to create galleries.", 'facebook-photo-fetcher'), "<b>{$user->name}</b>");
        ?>
</i>  <?php 
        _e("If you'd like to remove the connection and authorize a different user, click the button below:", 'facebook-photo-fetcher');
        ?>
<br /><br /> 
            <?php 
    } else {
        ?>
 <?php 
        _e('Before this plugin can be used, you must connect it to your Facebook account.  Please click the following button to login:'******'facebook-photo-fetcher');
        ?>
<br /><br />
            <?php 
    }
    ?>
            
            <!--Deauthorize button-->
            <?php 
    if ($access_token) {
        ?>
                <form method="post" action="">
                    <input type="hidden" id="delete_token" name="delete_token" value="0" />
                    <input type="submit" class="button-secondary" style="width:127px;" value="<?php 
        _e('Deauthorize', 'facebook-photo-fetcher');
        ?>
" />
                </form>
            <?php 
    }
    ?>
            
            <!--Login/Renew button-->
        	<!--Facebook requires the auth dialog to be initialized on a domain specified in the FPF app settings.  It therefore resides-->
        	<!--on my auth server, shown here in an iFrame. Once the user authorizes, easyXDM will communicate the token back to this-->
        	<!--admin panel where it can be saved. EasyXDM creates the iFrame for us, sends a message to tell it what to name the button,-->
        	<!--then waits for the login token.  The iFrame lives in the "authorizeFrame" container.-->
        	<!--The iFrame may be named "Login with Facebook" or "Renew," based on if there's already a token in the database.  A "renew" button-->
        	<!--will only be shown if there's 59 days or less until expiration (since FB doesn't allow you to renew in the first day).-->
        	<?php 
    if (!$access_token || $access_token && (get_option($fpf_opt_token_expiration) - time()) / 60 / 60 / 24 < 59.0) {
        ?>
            	<div id="graph_step1" style="width:150px;height:23px;float:left;">
            		<div id="authorizeFrame" style="height:30px;overflow:hidden;"></div>
            		<script type="text/javascript" src="<?php 
        echo plugins_url(dirname(plugin_basename(__FILE__)));
        ?>
/easyXDM/easyXDM.min.js"></script>
            		<script>
            			var socket = new easyXDM.Socket(
            			{
            			    //EasyXDM will setup the iFrame here
            				container: "authorizeFrame",
            	    		remote: "http://auth.justin-klein.com/FPF-Auth",
            	    		
                            //Once it's ready, send a message to tell it what to name the login button & which plugin version we're using
                            onReady: function()
                            {
                                var message = {btnName:'<?php 
        echo $access_token ? __("Renew", 'facebook-photo-fetcher') : __("Login with Facebook", 'facebook-photo-fetcher');
        ?>
',
                                               pluginVersion:'<?php 
        echo $fpf_version;
        ?>
'};
                                socket.postMessage(JSON.stringify(message));
                            },
            
                            //And wait for a response - which will come once the user has logged in with Facebook.
                            //When the response comes, auto-submit the invisible form below to save the token.
            	    		onMessage: function(message, origin)
            	    		{
            	    		    var response = JSON.parse(message);
            	        		jQuery('#<?php 
        echo $fpf_opt_access_token;
        ?>
').val(response.accessToken);
            	        		jQuery('#<?php 
        echo $fpf_opt_token_expiration;
        ?>
').val(response.expiresIn);
            	        		jQuery('#graph_token_submit').submit();
            	    		}
            			});
            		</script>
            	</div>			
            	<form method="post" id="graph_token_submit" action="">
                    <input type="hidden" id="<?php 
        echo $fpf_opt_access_token;
        ?>
" name="<?php 
        echo $fpf_opt_access_token;
        ?>
" value="0" />
                    <input type="hidden" id="<?php 
        echo $fpf_opt_token_expiration;
        ?>
" name="<?php 
        echo $fpf_opt_token_expiration;
        ?>
" value="0" />
                </form>
                
                <?php 
        if (is_ssl() && !$access_token) {
            ?>
                    <br clear="all" />
                    <div class="fpf-admin_warning" style="width:70%;">
                        <?php 
            _e("NOTE: Your Wordpress admin appears to be running over SSL.  Unfortunately, in order to comply with Facebook's security rules, the FPF authorization may only be performed from my server (since I'm the owner of the app) - thus the button is loaded in an iFrame.  Normally this would appear above, but some browsers have begun to silently block 'mixed content' pages from loading.  If you don't see a login button, you'll need temporarily enable mixed content (just on this page).  Not to worry, all transactions with Facebook are still encrypted and secure - it's only my simple 'wrapper' script that will be sent over http:", 'facebook-photo-fetcher');
            ?>
<br/>
                        <ul style="list-style-type:disc;list-style-position:inside;">
                            <li><?php 
            _e('In IE, it will prompt you to \'Show all content\' at the bottom of the window when you first load this page.  All you need to do is click that button.', 'facebook-photo-fetcher');
            ?>
</li>
                            <li><?php 
            _e('In Firefox, click the shield to the left of the URL and select \'disable protection on this page\' from the drop-down.', 'facebook-photo-fetcher');
            ?>
</li>
                            <li><?php 
            _e("In Chrome, there's a similar shield to the right of the URL that lets you 'load unsafe content.'", 'facebook-photo-fetcher');
            ?>
</li>
                        </ul>
                        <small>(<?php 
            echo sprintf(__("If you're reluctant to enable these options, please keep in mind that the vast majority of Wordpress installations do not run over SSL - and thus never see this warning.  All you're doing is giving the browser permission load an iFrame over http, while the rest of the page is https. This was the default behavior for all major browsers until mid-2013 (i.e. see %s and %s).  Also note that the Facebook logins themselves still run entirely over SSL.  For more information on mixed content, please see %s.", 'facebook-photo-fetcher'), '<a target="link1" href="http://stackoverflow.com/questions/18251128/why-am-i-suddenly-getting-a-blocked-loading-mixed-active-content-issue-in-fire">here</a>', '<a target="link2" href="http://productforums.google.com/forum/#!topic/chrome/OrwppKWbKnc">here</a>', '<a target="link3" href="https://developer.mozilla.org/en-US/docs/Security/MixedContent">here</a>');
            ?>
)</small>
                    </div>
                <?php 
        }
        ?>
                
                <?php 
        if ($access_token) {
            ?>
                    <span style="float:left;"><small>(<?php 
            echo sprintf(__("Expires in %s", 'facebook-photo-fetcher'), human_time_diff(get_option($fpf_opt_token_expiration)));
            ?>
)</small></span>
                <?php 
        } else {
            ?>
                    <br clear="all"/><br/><small><i><?php 
            _e("Note: When you click the login button, a Facebook dialog will be shown via my own authentication server.  Authorizing from my server is required to comply with Facebook's security rules, which only allow apps to authorize from one specific, known location.  During the authorization process, no personal information will be transferred; Facebook handles the entire process, and only supplies me with the resulting token, which I then hand back to your site to be stored.  This is what the plugin uses in order to fetch the photos.  For more information about how the Facebook authorization process works, please see their documentation:", 'facebook-photo-fetcher');
            ?>
 <a href="https://developers.facebook.com/docs/reference/dialogs/oauth/" target="fpf">here</a>.)</i></small>
                <?php 
        }
        ?>
                <br clear="all" />
            <?php 
    }
    ?>
            
            <hr />
            <?php 
    //Output the token expiration, for testing.
    //NOTE: This will only work for MY user account (they only allow the developer of an app to debug that app's access tokens)
    //See https://developers.facebook.com/docs/howtos/login/debugging-access-tokens
    echo "<small><strong>Debug</strong><br />";
    if ($access_token) {
        echo "Token: {$access_token}<br />";
        echo "Expected Expiration: " . human_time_diff(get_option($fpf_opt_token_expiration)) . "<br />";
        $tokenResponse = fpf_get("https://graph.facebook.com/debug_token?input_token=" . get_option($fpf_opt_access_token) . '&access_token=' . get_option($fpf_opt_access_token));
        if (isset($tokenResponse->data->expires_at)) {
            $expiresMin = (int) (($tokenResponse->data->expires_at - time()) / 60);
            $expiresH = (int) ($expiresMin / 60);
            $expiresMin -= $expiresH * 60;
            echo "True Expiration: {$expiresH}" . "h {$expiresMin}" . "m";
        } else {
            echo "True Expiration: Unknown";
        }
    } else {
        echo "Token: None";
    }
    echo "</small>";
    ?>
        </div><!--end tab-->

        <div class="<?php 
    echo $allTabsClass;
    ?>
" id="<?php 
    echo $tab2Id;
    ?>
" style="display:<?php 
    echo $fpf_shown_tab == 2 ? "block" : "none";
    ?>
">    
           <?php 
    //SECTION - Search for albums
    ?>
           
           <?php 
    if (!get_option($fpf_opt_access_token)) {
        ?>
                    <h3><?php 
        _e('Utilities', 'facebook-photo-fetcher');
        ?>
</h3>
                    <?php 
        _e("Please use the 'Facebook Setup' tab to authorize your Facebook account.", 'facebook-photo-fetcher');
        ?>
<br /><br/>
                 <?php 
    } else {
        ?>
           <h3><?php 
        _e('Search for Albums', 'facebook-photo-fetcher');
        ?>
</h3>
           
           <form name="listalbums" method="post" action="">
               <?php 
        _e('To get a list of album IDs that you can use to create galleries, enter a Facebook Page or User ID below and click "Search."', 'facebook-photo-fetcher');
        ?>
<br /><br />
               <?php 
        echo sprintf(__("Your User ID is %s.  To get a page's ID, view any of its photos on Facebook - the URL will be something like %s. The last set of numbers (%s in this example) is the ID.", 'facebook-photo-fetcher'), "<b>{$user->id}</b>", "<b>facebook.com/photos/a.123.456.789</b>", "789");
        ?>
<br /><br /> 
               <input type="text" name="<?php 
        echo $fpf_opt_last_uid_search;
        ?>
" value="<?php 
        echo get_option($fpf_opt_last_uid_search);
        ?>
" size="20">
               <input type="submit" class="button-secondary"  name="Submit" value="<?php 
        _e("Search", 'facebook-photo-fetcher');
        ?>
" />
           </form>
    
           <?php 
        //If we just requested a search, do it and show results.
        add_option($fpf_opt_last_uid_search, $user->id);
        if (isset($_POST[$fpf_opt_last_uid_search])) {
            //Get the name of the user/page whose ID we're searching
            $search_uid = get_option($fpf_opt_last_uid_search);
            $response = fpf_get("https://graph.facebook.com/{$search_uid}?access_token={$access_token}&fields=name");
            if (!isset($response->name) || !$response->name) {
                $search_name = "(" . __("Unknown User", 'facebook-photo-fetcher') . ")";
            } else {
                $search_name = $response->name;
            }
            //Get the list of albums
            $response = fpf_get("https://graph.facebook.com/{$search_uid}/albums?access_token={$access_token}&limit=999&fields=id,link,name,count");
            if (isset($response->data)) {
                $albums = $response->data;
            } else {
                $albums = array();
            }
            //..And show the list.
            ?>
<div class='postbox' style='margin-top:5px; width:550px;'>
               <h3 class='hndle' style='padding:6px;'>
                   <span><?php 
            echo sprintf(__("Available Facebook Albums for %s:", 'facebook-photo-fetcher'), "<a href='http://www.facebook.com/profile.php?id={$search_uid}' target='_fb'>{$search_name}</a>");
            ?>
</span>
               </h3><?php 
            echo "<div class='inside'><small>";
            if (is_array($albums) && count($albums) > 0) {
                foreach ($albums as $album) {
                    echo '&lt;!--' . $fpf_identifier . ' ' . $album->id . ' --&gt;&lt;!--/' . $fpf_identifier . '--&gt; (<a href="' . $album->link . '">' . $album->name . '</a>; ' . sprintf(__('%s photos', 'facebook-photo-fetcher'), $album->count) . ')<br />';
                }
            } else {
                echo __("None found.", 'facebook-photo-fetcher') . "<br />";
            }
            echo "</small></div></div>";
        }
        ?>
           <hr />

           <?php 
        //SECTION - Fetch all albums
        ?>
           <h3><?php 
        _e('Refresh Albums from Facebook', 'facebook-photo-fetcher');
        ?>
</h3>
               <?php 
        _e("This will scan all your posts and pages for galleries created with this plugin, and regenerate each one it finds by re-fetching its information from Facebook.  " . "The only reason to use this would be if you've changed or updated something in many of your albums and want those changes to be reflected here as well.  It can be slow if you have lots of galleries, so use with caution.", 'facebook-photo-fetcher');
        ?>
<br /><br />
               
               <div class="postbox" style="width:400px; height:80px; padding:10px; float:left; text-align:center;">
               <form name="fetchallposts" method="post" action="">
                 <input type="hidden" name="fetch_pages" value="Y">
                 <input type="submit" class="button-secondary" name="Submit" value="<?php 
        _e('Re-Fetch All Albums in Pages', 'facebook-photo-fetcher');
        ?>
" />
                </form>
                <br />
                <form name="fetchallpages" method="post" action="">
                  <input type="hidden" name="fetch_posts" value="Y">
                  <input type="submit" class="button-secondary" name="Submit" value="<?php 
        _e('Re-Fetch All Albums in Posts', 'facebook-photo-fetcher');
        ?>
" />
                </form>
            </div>
            <?php 
        //For an old custom addon I implemented for a customer; leave it for backwards-compatilibity.
        if (function_exists('fpf_output_cron_panel')) {
            fpf_output_cron_panel();
        }
        ?>
            <br clear="all" />
                <?php 
        //When we click one of the "fetch now" buttons
        if (isset($_POST['fetch_pages']) || isset($_POST['fetch_posts'])) {
            //Get the collection of pages or posts
            if (isset($_POST['fetch_pages'])) {
                echo "<b>" . __("Checking All Pages for Facebook Albums:", 'facebook-photo-fetcher') . "</b><br />";
                $pages = get_pages(array('post_status' => 'publish,private'));
            } else {
                echo "<b>" . __("Checking All Posts for Facebook Albums:", 'facebook-photo-fetcher') . "</b><br />";
                $pages = get_posts('post_type=post&numberposts=-1&post_status=publish,private');
            }
            echo "<div class='postbox' style='width:90%;padding:10px;'><pre>";
            echo fpf_refetch_all($pages, true);
            echo "</pre></div>";
        }
        ?>
            
            <?php 
    }
    //If not authorized
    ?>
        </div><!--end tab-->
        
        <div class="<?php 
    echo $allTabsClass;
    ?>
" id="<?php 
    echo $tab3Id;
    ?>
" style="display:<?php 
    echo $fpf_shown_tab == 3 ? "block" : "none";
    ?>
">
            <h3><?php 
    _e("Addon Options", 'facebook-photo-fetcher');
    ?>
 <small>(Version <?php 
    echo defined('FPF_ADDON_VER') ? FPF_ADDON_VER : "?";
    ?>
)</small></h3>
            <?php 
    do_action('fpf_addon_admin_tab');
    ?>
        </div><!--end tab-->
                    
        <div class="<?php 
    echo $allTabsClass;
    ?>
" id="<?php 
    echo $tab4Id;
    ?>
" style="display:<?php 
    echo $fpf_shown_tab == 4 ? "block" : "none";
    ?>
">
            <h3><?php 
    _e('Support Information', 'facebook-photo-fetcher');
    ?>
</h3>
            <div style="width:600px;">
            <?php 
    echo sprintf(__('Before submitting a support request, please make sure to carefully read all the documentation and FAQs on the <a href="%s">plugin homepage</a>.  Every problem that\'s ever been reported has a solution posted there.', 'facebook-photo-fetcher'), $fpf_homepage);
    ?>
<br /><br />
            <?php 
    echo sprintf(__('If you do choose to submit a request, please do so on the <a href="%s">plugin homepage</a>, not on Wordpress.org (which I rarely check).  Also, be sure to include the following information about your Wordpress hosting environment:', 'facebook-photo-fetcher'), $fpf_homepage);
    ?>
<br />
            </div>
            <div style="width:600px; padding:5px; margin:8px 0; background-color:#EEEDDA; border:1px solid #CCC;">
                <b>Host URL: </b> <?php 
    echo $_SERVER["HTTP_HOST"];
    ?>
<br />
                <b>Site URL: </b> <?php 
    echo get_bloginfo('url');
    ?>
<br />
                <b>Wordpress URL: </b> <?php 
    echo get_bloginfo('wpurl');
    ?>
<br />
                <b>Wordpress Version:</b> <?php 
    echo $GLOBALS['wp_version'];
    ?>
<br />
                <b>Plugin Version:</b> <?php 
    echo $fpf_version;
    ?>
<br />
                <b>Browser:</b> <?php 
    echo $_SERVER['HTTP_USER_AGENT'];
    ?>
<br /> 
                <b>Theme:</b> <?php 
    echo wp_get_theme();
    ?>
<br />
                <b>Server:</b> <?php 
    echo substr($_SERVER['SERVER_SOFTWARE'], 0, 45) . (strlen($_SERVER['SERVER_SOFTWARE']) > 45 ? "..." : "");
    ?>
<br />
                <b>Active Plugins:</b> 
                <?php 
    $active_plugins = get_option('active_plugins');
    $plug_info = get_plugins();
    echo "<b>" . count($active_plugins) . "</b><small> (";
    foreach ($active_plugins as $name) {
        echo $plug_info[$name]['Title'] . " " . $plug_info[$name]['Version'] . "; ";
    }
    echo "</small>)<br />";
    ?>
            </div>
            
            <hr />
            <h3><?php 
    _e('Donate', 'facebook-photo-fetcher');
    ?>
</h3>
            <?php 
    _e("Many hours have gone into making this plugin as versatile and easy to use as possible, far beyond my own personal needs. Although I offer it to you freely, please keep in mind that each hour spent extending and supporting it was an hour that could've also gone towards income-generating work. If you find it useful, a small donation would be greatly appreciated.", 'facebook-photo-fetcher');
    ?>
            <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
                <input type="hidden" name="cmd" value="_s-xclick" />
                <input type="hidden" name="hosted_button_id" value="L32NVEXQWYN8A" />
                <input type="image" src="https://www.paypal.com/en_US/i/btn/btn_donate_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!" />
                <img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1" />
            </form>
          
        </div><!--end tab-->

        </div><!-- div fpf-admin_wrapper -->
    </div><!-- div wrap -->
    <?php 
}
Example #4
0
/**
 * Given a Facebook AlbumID, fetch its content and return:
 * $retVal['content'] - The generated HTML content we'll use to display the album
 * $retVal['cover']   - The Facebook album's cover photo (if set)
 * $retVal['count']   - The number of SHOWN photos in the album
 * 
 * $params is a array of extra options, parsed from the startTag by fpf_find_tags().
 * For a list of supported options and their meanings see the $defaults array below.   
 */
function fpf_fetch_album_content($aid, $params)
{
    //Combine optional parameters with default values
    global $fpf_homepage;
    $defaults = array('cols' => 4, 'start' => 0, 'max' => 99999999999.0, 'swapHead' => false, 'hideHead' => false, 'hideCaps' => false, 'noLB' => false, 'hideCred' => false, 'rand' => false, 'orderby' => 'normal');
    //Can be "normal" or "reverse" (for now)
    $params = array_merge($defaults, $params);
    $itemwidth = $params['cols'] > 0 ? floor(100 / $params['cols']) : 100;
    $itemwidth -= 0.5 / $params['cols'];
    //For stupid IE7, which rounds fractional percentages UP (shave off 0.5%, or the last item will wrap to the next row)
    $retVal = array();
    //Get our saved access token (and make sure it exists)
    global $fpf_opt_access_token;
    $access_token = get_option($fpf_opt_access_token);
    if (!$access_token) {
        $retVal['content'] = 'This plugin does not have a valid Facebook access token.  Please use your admin panel to login with Facebook.';
        return $retVal;
    }
    //Try to fetch the album object from Facebook, and check for common errors.
    $album = fpf_get("https://graph.facebook.com/{$aid}?access_token={$access_token}&fields=id,cover_photo,count,link,name,from,created_time,description");
    if (!$album || isset($album->error)) {
        if (!$album) {
            $retVal['content'] = "An unknown error occurred while trying to fetch the album (empty reply).";
        } else {
            if ($album->error->code == 190) {
                $retVal['content'] = "Error 190: Invalid OAuth Access Token.  Try using the admin panel to re-validate your plugin.";
            } else {
                if ($album->error->code == 803) {
                    $retVal['content'] = "Error 803: Your album id doesn't appear to exist.";
                } else {
                    if ($album->error->code == 100) {
                        $retVal['content'] = "Error 100: Your album id doesn't appear to be accessible.";
                    }
                }
            }
        }
        return $retVal;
    }
    if (!isset($album->id) || $album->id != $aid) {
        $retVal['content'] = "An unknown error occurred while trying to fetch the album (id mismatch).";
        return $retVal;
    }
    if (!isset($album->cover_photo) || $album->id != $aid) {
        $retVal['content'] = "An error occurred while trying to fetch the album: the ID specified does not appear to be an album.";
        return $retVal;
    }
    if ($album->count == 0) {
        $retVal['content'] = "An error occurred while trying to fetch the album: it appears to be empty.";
        return $retVal;
    }
    //Now that we know the album is OK, try to fetch its photos and run some checks on them.
    $photos = fpf_get("https://graph.facebook.com/{$aid}/photos?access_token={$access_token}&limit=999&fields=name,source,picture");
    if (!$photos || !isset($photos->data)) {
        $retVal['content'] = "An unknown error occurred while trying to fetch the photos (empty data).";
        return $retVal;
    }
    if (count($photos->data) != $album->count) {
        $retVal['content'] = "<i>Warning: A size mismatch error occurred while trying to fetch the photos (the album reported {$album->count} entries, but only " . count($photos->data) . " were returned).</i><br />";
        //$retVal['content'] .= "Album:\n\nhttps://graph.facebook.com/$aid?access_token=$access_token&fields=id,cover_photo,count,link,name,from,created_time,description\n\n";
        //$retVal['content'] .= "Photos:\n\nhttps://graph.facebook.com/$aid/photos?access_token=$access_token&limit=999&fields=name,source,picture\n\n";
    }
    $photos = $photos->data;
    //Run filters so we can modify the album and photo data
    $album = apply_filters('fpf_album_data', $album);
    $photos = apply_filters('fpf_photos_presort', $photos);
    //Store the filename of the album cover
    //We must do this here, prior to slicing down the array of photos.
    if (isset($album->cover_photo)) {
        foreach ($photos as $photo) {
            if (strcmp($photo->id, $album->cover_photo) == 0) {
                $retVal['cover'] = $photo->source;
            }
        }
    }
    //Reorder the photos if necessary
    if ($params['orderby'] == 'reverse') {
        $photos = array_reverse($photos);
    }
    //Slice the photo array as necessary
    if (count($photos) > 0) {
        //Slice the photos between "start" and "max"
        if ($params['start'] > $album->count) {
            $retVal['content'] .= "<b>Error: Start index " . $params['start'] . " is greater than the total number of photos in this album; Defaulting to 0.</b><br /><br />";
            $params['start'] = 0;
        }
        if ($params['max'] > $album->count - $params['start']) {
            $params['max'] = $album->count - $params['start'];
        }
        $photos = array_slice($photos, $params['start'], $params['max']);
        //If "rand" is specified, randomize the order and slice again
        if ($params['rand']) {
            shuffle($photos);
            $photos = array_slice($photos, 0, $params['rand']);
        }
    }
    //Run a filter so addons can modify/process the photos
    $photos = apply_filters('fpf_photos_postsort', $photos);
    //Create a header with some info about the album
    $retVal['count'] = count($photos);
    if (!$params['hideHead']) {
        $headerTitle = 'From <a href="' . htmlspecialchars($album->link) . '">' . $album->name . '</a>';
        if (isset($album->from->id) && isset($album->created_time)) {
            $headerTitle .= ', posted by <a href="http://www.facebook.com/profile.php?id=' . $album->from->id . '">' . $album->from->name . '</a>';
            $headerTitle .= ' on ' . date('n/d/Y', strtotime($album->created_time));
        }
        if ($retVal['count'] < $album->count) {
            $headerTitle .= ' (Showing ' . $retVal['count'] . ' of ' . $album->count . " items)\n";
        } else {
            $headerTitle .= ' (' . $retVal['count'] . " items)\n";
        }
        $headerTitle .= '<br /><br />';
        if ($album->description) {
            $headerDesc = '"' . $album->description . '"<br /><br />' . "\n";
        } else {
            $headerDesc = "";
        }
    }
    //Output the album!  Starting with a (hidden) timestamp, then the header, then each photo.
    global $fpf_version;
    $retVal['content'] .= "<!-- ID " . $aid . " Last fetched on " . date('m/d/Y H:i:s') . " v{$fpf_version}-->\n";
    if ($params['swapHead']) {
        $retVal['content'] .= $headerTitle . $headerDesc;
    } else {
        $retVal['content'] .= $headerDesc . $headerTitle;
    }
    $retVal['content'] .= "<div class='gallery'>\n";
    foreach ($photos as $photo) {
        //Output this photo (must get rid of [], or WP will try to run it as shortcode)
        $caption = preg_replace("/\\[/", "(", $photo->name);
        $caption = preg_replace("/\\]/", ")", $caption);
        $caption = preg_replace("/\r/", "", $caption);
        $caption_with_br = htmlspecialchars(preg_replace("/\n/", "<br />", $caption));
        $caption_no_br = htmlspecialchars(preg_replace("/\n/", " ", $caption));
        $link = '<a rel="' . htmlspecialchars($album->link) . '" class="fbPhoto" href="' . $photo->source . '" title="' . $caption_with_br . ' " ><img src="' . $photo->picture . '" alt="" /></a>';
        $retVal['content'] .= "<dl class='gallery-item' style=\"width:{$itemwidth}%\">";
        $retVal['content'] .= "<dt class='gallery-icon'>{$link}</dt>";
        if (!$params['hideCaps']) {
            $retVal['content'] .= "<dd class='gallery-caption'>";
            $retVal['content'] .= mb_substr($caption_no_br, 0, 85) . (strlen($caption_no_br) > 85 ? "..." : "");
            $retVal['content'] .= "</dd>";
        }
        $retVal['content'] .= "</dl>\n";
        //Move on to the next row?
        if ($params['cols'] > 0 && ++$i % $params['cols'] == 0) {
            $retVal['content'] .= "<br style=\"clear: both\" />\n\n";
        }
    }
    if ($i % $params['cols'] != 0) {
        $retVal['content'] .= "<br style=\"clear: both\" />\n\n";
    }
    $retVal['content'] .= "</div>\n";
    if (!$params['hideCred']) {
        $retVal['content'] .= "<span class=\"fpfcredit\">Generated by <i>Facebook Photo Fetcher 2</i></span>\n";
    }
    //Activate the lightbox when the user clicks a photo (only if the Lightbox plugin isn't already there)
    if (!$params['noLB'] && !function_exists('lightbox_2_options_page')) {
        $retVal['content'] .= '<script type="text/javascript">//<!--
		jQuery(document).ready(function() {
			jQuery("a[rel*=\'' . $aid . '\']").fancybox({
				"transitionIn"	: "elastic",
				"transitionOut"	: "elastic",
				"titlePosition" : "inside",
				"titleFormat"	: function(title, currentArray, currentIndex, currentOpts)
				{
					return "<span id=\'fancybox-title-over\' style=\'background-image:none; text-align:left;\'>" + (title.length ? title : "") + "</span>";
				}
			});
		});' . "\n//--></script>\n";
    }
    $retVal['content'] .= "<!-- End Album " . $aid . " -->\n";
    return $retVal;
}