The idea is to grab a user's XML feed data and store the information locally in a file named for the user feed (identified by the URL rather than the user's name). Since this leads to extremely long file names, the MD5 function creates a shorter, more consistent naming pattern and also adds a bit of privacy. If you're wondering why I've named the file based on the URL instead of the user name, take a look at the fetchAvatar function. This data must also be cached. The only data that is common between the two functions is the user feed URL. This ensures that the cached feed and the cached avatar have the same naming pattern. If you recall, we added the strtolower() function call to the constructor when passing the user name value into the fetchUserInfo function. This ensures that the user name passed into this function is always in lower case form. The reason is the use of the MD5 function above. Take a look at the following two URLs. http://twitter.com/statuses/user_timeline/WindowsGuru.xml?count=1 http://twitter.com/statuses/user_timeline/windowsguru.xml?count=1 While both of these URLs appear to (and in fact do) point to the same user feed location, due to their difference in case they will produce two different MD5 values. This means that the same user data could be stored in two separate cache files, making it nearly impossible to load from a cache properly. By forcing the case of the user name before constructing the URL, the MD5 function will always return the same for any given user name, regardless of the case the end-user uses when supply the name. if (@filemtime($cache_file) + $this->cache_expires > time()) { $xml = @file_get_contents($cache_file); } else { $xml = $this->curlRequest($url); if ($xml !== false) { file_put_contents($cache_file, $xml); } } The next piece of logic performs the caching magic. If the creation time on the cache file plus the cache expiration time is greater than the current system time (meaning the cache file is not older than the expiration time), the file contents are retrieved using the file_get_contents() function. Otherwise, we make a request to the Twitter API using our curlRequest method and store the file contents to a local cache file. You may be looking at this logic and thinking to yourself that a piece is missing. The entire logic here relies on the ability to read the time stamp on the local cache file. But what if that file doesn't exist yet? Won't the logic fail? The short answer is yes, relying on that exclusively would create a problem. However, you'll notice that I've added the @ symbol in front of my call to the filemtime() function to suppress any errors that may occur of the time cannot be read. Since filemtime() simply returns false in the event of an error, this provides a shortcut that pushes the logic into the Else block anyway. The key here is that I've suppressed any error from being displayed in the browser. I have intentionally ignored a third scenario here in which a local file exists but cannot be read. Since the chances of this are pretty slim and this isn't a mission critical application, I didn't take the time to worry about it. You could add another If block based around the result of the file_get_contents() method that will make a call to curlRequest in the event that it returns false, which would force a new user feed to be downloaded if the local copy were ever unreadable. if ($xml === false && file_exists($cache_file)) { $xml = file_get_contents($cache_file); } if ($xml === false) { throw new SignatureImageException('User feed unavailable.'); } The final piece of logic checks to see if any user feed data exists at this point in the script. If not, and a local copy exists (assuming a CURL request failed for whatever reason), the file is loaded locally even if the cached version is outdated. This prevents the script from bombing out if the Twitter API should be down for any reason. If at this point a user feed still does not exists (meaning it could not be downloaded and there was no usable local copy), the second If block with throw an exception explaining that the user feed was not available.
blog comments powered by Disqus |
|
|
|
|
|
|
|