Last active
March 4, 2019 20:54
-
-
Save dfelton/2216ccff546bf94d6427418888954a1b to your computer and use it in GitHub Desktop.
Instagram Feed for Magento
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Instructions on how to add an Instagram Feed to a Magento Site. | |
Includes: | |
Block Class w/ base template for rendering the feed | |
System -> Configuration options for connecting to the client's Instagram account | |
Default CSS Styles |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- | |
Adds the necessary System -> Configuration fields to store the client's | |
account information and configuration settings for the feed. | |
--> | |
<config> | |
<tabs> | |
<firstscribe translate="label" module="firstscribe_grizzly"> | |
<label>Client Name</label> | |
<sort_order>20</sort_order> | |
</firstscribe> | |
</tabs> | |
<sections> | |
<firstscribe_client translate="label" module="firstscribe_grizzly"> | |
<class>separator-top</class> | |
<label>Client Name</label> | |
<tab>firstscribe</tab> | |
<frontend_type>text</frontend_type> | |
<sort_order>100</sort_order> | |
<show_in_default>1</show_in_default> | |
<groups> | |
<instagram translate="label" module="firstscribe_grizzly"> | |
<label>Instagram Account</label> | |
<frontend_type>text</frontend_type> | |
<sort_order>10</sort_order> | |
<show_in_default>1</show_in_default> | |
<fields> | |
<user_id> | |
<label>User Id</label> | |
<comment>This is different from your login username.</comment> | |
<frontend_type>text</frontend_type> | |
<show_in_default>1</show_in_default> | |
<sort_order>0</sort_order> | |
<frontend_class>validate-digits</frontend_class> | |
</user_id> | |
<access_token translate="label"> | |
<label>Access Token</label> | |
<frontend_type>obscure</frontend_type> | |
<backend_model>adminhtml/system_config_backend_encrypted</backend_model> | |
<comment><![CDATA[<a href="https://www.instagram.com/developer/authentication/" target="_blank">Read Documentation</a>]]></comment> | |
<sort_order>10</sort_order> | |
<show_in_default>1</show_in_default> | |
</access_token> | |
<photo_count> | |
<label>Photo count</label> | |
<comment>Number of photos to display in the feed.</comment> | |
<frontend_type>text</frontend_type> | |
<show_in_default>1</show_in_default> | |
<frontend_class>validate-digits required-entry validate-greater-than-zero</frontend_class> | |
<sort_order>0</sort_order> | |
</photo_count> | |
</fields> | |
</instagram> | |
</groups> | |
</firstscribe_client> | |
</sections> | |
</config> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Instagram Helper | |
* | |
* @category FirstScribe | |
* @package FirstScribe_Client | |
* @author Darren D Felton <[email protected]> | |
*/ | |
class FirstScribe_Client_Helper_Instagram extends Mage_Core_Helper_Abstract | |
{ | |
const XML_PATH_ACCESS_TOKEN = 'firstscribe_client/instagram/access_token'; | |
const XML_PATH_USER_ID = 'firstscribe_client/instagram/user_id'; | |
const XML_PATH_PHOTO_COUNT = 'firstscribe_client/instagram/photo_count'; | |
/** | |
* Return the user id for the client's Instagram account | |
* @return string | |
*/ | |
public function getUserId() | |
{ | |
return Mage::getStoreConfig(self::XML_PATH_USER_ID); | |
} | |
/** | |
* Return the access token for the client's Instagram account | |
* | |
* @return string | |
*/ | |
public function getAccessToken() | |
{ | |
/* @var $core Mage_Core_Helper_Data */ | |
$core = Mage::helper('core'); | |
return $core->decrypt(Mage::getStoreConfig(self::XML_PATH_ACCESS_TOKEN)); | |
} | |
/** | |
* Return the number of items to fetch for the feed. | |
* | |
* @return string | |
*/ | |
public function getPhotoCount() | |
{ | |
return Mage::getStoreConfig(self::XML_PATH_PHOTO_COUNT); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Instagram Feed | |
* | |
* @category FirstScribe | |
* @package FirstScribe_Grizzly | |
* @author Darren D Felton <[email protected]> | |
*/ | |
/* @var $this FirstScribe_Grizzly_Block_Instagram_Feed */ | |
/* @var $item Varien_Object */ | |
$j = count($this->getFeed()); | |
$i = 0; | |
?> | |
<div class="instagram-feed-container" id="list_instagram"> | |
<div class="instagram-feed"> | |
<?php foreach ($this->getFeed() as $item): ?> | |
<a href="#instagram_feed_<?php echo $item->getId() ?>" data-fancybox-group="instagram" class="<?php echo $this->getListClass(++$i, $j, $item, 'item', 6, 'fancybox') ?>"> | |
<img src="<?php echo $item->getData('image_preview') ?>" alt="<?php echo $this->quoteEscape($item->getData('caption')) ?>" /> | |
<div class="absolute-cover inside"> | |
<div class="valign-wrap"> | |
<div class="valign-middle"> | |
<div class="animated mglass-white"></div> | |
</div> | |
</div> | |
</div> | |
</a> | |
<div class="overlay-container hidden"> | |
<div class="instagram-popup" id="instagram_feed_<?php echo $item->getId() ?>"> | |
<img src="<?php echo $item->getData('image_full') ?>" alt="<?php echo $this->quoteEscape($item->getData('caption')) ?>" /> | |
<div class="std"> | |
<p><?php echo $item->getData('caption') ?></p> | |
<p class="a-center"> | |
<a href="<?php echo $item->getData('link') ?>" target="_blank" class="button view"> | |
<?php echo $this->__('View on Instagram') ?></a> | |
</div> | |
</div> | |
</div> | |
<?php endforeach ?> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Animations */ | |
@keyframes bounceInDown{60%,75%,90%,from,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,-3000px,0);transform:translate3d(0,-3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,25px,0);transform:translate3d(0,25px,0)}75%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}90%{-webkit-transform:translate3d(0,5px,0);transform:translate3d(0,5px,0)}to{-webkit-transform:none;transform:none}} | |
.animated{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:both;animation-fill-mode:both} | |
/* Global: Helpers */ | |
.absolute-cover{bottom:0;left:0;padding:15px;position:absolute;right:0;top:0} | |
.valign-wrap{display:table;height:100%;width:100%} | |
.valign-middle{display:table-cell;vertical-align:middle} | |
/* Instagram Feed */ | |
.instagram-feed{border:5px solid #fff;margin:0 auto;max-width:100%;width:1920px} | |
.instagram-feed .item{border:5px solid #fff;display:block;float:left;overflow:hidden;position:relative;width:16%;width:calc(100%/6)} | |
.instagram-feed .item:hover{cursor:pointer} | |
.instagram-feed .item:hover .inside{background:#a60918;opacity:.6} | |
.instagram-feed .item:hover .mglass-white{animation-name:bounceInDown;opacity:1} | |
.instagram-feed img{max-width:100%} | |
.instagram-feed .mglass-white{opacity:0;height:30px;margin:0 auto;position:relative;transition:opacity 1000ms;width:30px} | |
.instagram-feed .inside{transition:background-color 500ms,opacity 500ms} | |
.instagram-popup{border-bottom-left-radius:10px;border-bottom-right-radius:10px;max-width:640px;overflow:hidden;width:100%} | |
.instagram-popup img{max-width:100%} | |
.instagram-popup .std{border-top:5px solid #a60918;padding:10px} | |
@media(max-width:1600px){ | |
.instagram-feed .item{width:20%}} | |
@media(max-width:1280px){ | |
.instagram-feed .item{width:25%}} | |
@media(max-width:960px){ | |
.instagram-feed .item{width:33%;width:calc(100%/3)}} | |
@media(max-width:640px){ | |
.instagram-feed .item{width:50%}} | |
@media(max-width:500px){ | |
.instagram-feed .item{float:none;margin:0 auto;width:320px}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Provides helper methods for HTML lists. | |
* | |
* @category FirstScribe | |
* @package FirstScribe_Trait | |
* @author Darren D Felton <[email protected]> | |
*/ | |
trait FirstScribe_Trait_Utilities_Html_List | |
{ | |
/** | |
* Return a string of CSS class names | |
* | |
* @param int $i REQUIRED; Current iteration | |
* @param int $j REQUIRED; Total iterations | |
* @param object|int|string $item OPTIONAL; Object model or id of the item | |
* @param string $name OPTIONAL; CSS class name to use for items | |
* @param int $cols OPTIONAL; Max column CSS class names | |
* @param array|string $additional OPTIONAL; Additional CSS class names desired for every item | |
* @return string | |
*/ | |
public function getListClass($i, $j, $item = null, $name = 'item', $cols = 0, $additional = array()) | |
{ | |
$class = array($name, $name.'-'.$i); | |
if (is_object($item) && method_exists($item, 'getId')) { | |
$class[] = $name.'-id-'.$item->getId(); | |
} elseif (is_string($item) || is_int($item)) { | |
$class[] = $name.'-id-'.$item; | |
} | |
$class[] = $i% 2 ? 'odd' : 'even'; | |
for ($k=3; $k <= $cols; $k++) { | |
if (0 == ($i-1) % $k || 1 == $i) { | |
$class[] = 'col'.$k.'-start'; | |
} elseif (0 == $i % $k) { | |
$class[] = 'col'.$k.'-end'; | |
} | |
} | |
if (1 == $i) $class[] = 'first'; | |
if ($j == $i) $class[] = 'last'; | |
if (is_string($additional)) { | |
$additional = array($additional); | |
} | |
$class = array_merge($class, $additional); | |
return implode(' ', $class); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Instagram Feed | |
* | |
* @category FirstScribe | |
* @package FirstScribe_Client | |
* @author Darren D Felton <[email protected]> | |
*/ | |
class FirstScribe_Client_Block_Instagram_Feed extends Mage_Core_Block_Template | |
{ | |
use FirstScribe_Trait_Utilities_Html_List; | |
// Response codes from Instagram | |
const META_CODE_INVALID_ACCESS_TOKEN = 400; | |
const META_CODE_OK = 200; | |
/** | |
* @var array | |
*/ | |
protected $_feed; | |
/** | |
* @var FirstScribe_Client_Helper_Instagram | |
*/ | |
protected $_helper; | |
public function getFeed() | |
{ | |
if (is_null($this->_feed)) { | |
$this->initFeed(); | |
} | |
return $this->_feed; | |
} | |
/** | |
* Initialize the instagram feed. | |
*/ | |
protected function initFeed() | |
{ | |
$json = file_get_contents($this->getFeedUrl()); | |
if (false === $json) { | |
$this->logException('Failed to load feed contents.'); | |
$this->_feed = array(); | |
return; | |
} | |
$object = json_decode($json); | |
switch ($object->meta->code) { | |
case self::META_CODE_OK: | |
$this->_feed = $this->parseFeed($object->data); | |
break; | |
case self::META_CODE_INVALID_ACCESS_TOKEN: | |
$this->logException('Invalid Instagram access_token.'); | |
$this->_feed = array(); | |
break; | |
default: | |
$this->logException('Unknown response meta code:'.$object->meta->code); | |
$this->_feed = array(); | |
break; | |
} | |
return $this; | |
} | |
/** | |
* Parse the Instagram feed into a friendly array | |
* | |
* @param array $items | |
* @return array | |
*/ | |
protected function parseFeed(array $items) | |
{ | |
/* @var $item stdClass */ | |
$feed = array(); | |
foreach ($items as $item) { | |
// Only images are handled at this point. | |
if ($item->type != 'image') { | |
continue; | |
} | |
$data = array( | |
'id' => $item->id, | |
'image_preview' => $item->images->low_resolution->url, | |
'image_full' => $item->images->standard_resolution->url, | |
'link' => $item->link, | |
'caption' => $item->caption->text | |
); | |
$feed[] = new Varien_Object($data); | |
} | |
return $feed; | |
} | |
/** | |
* Log an exception message | |
* | |
* @param string $message | |
* @return FirstScribe_Client_Block_Instagram_Feed | |
*/ | |
protected function logException($message) | |
{ | |
try { | |
Mage::throwException('Invalid Instagram access_token.'); | |
} catch (Exception $e) { | |
Mage::logException($e); | |
} | |
return $this; | |
} | |
/** | |
* Return the URL for the Instagram feed, including all parameters for it. | |
* | |
* @return string | |
*/ | |
public function getFeedUrl() | |
{ | |
return 'https://api.instagram.com/v1/users/'.$this->getUserId() | |
.'/media/recent/?access_token='.$this->getAccessToken() | |
.'&count='.$this->getPhotoCount(); | |
} | |
/** | |
* Return the client's access token. | |
* | |
* @return string | |
*/ | |
public function getAccessToken() | |
{ | |
return $this->getInstagramHelper()->getAccessToken(); | |
} | |
/** | |
* Return the client's user id. | |
* | |
* @return string | |
*/ | |
public function getUserId() | |
{ | |
return $this->getInstagramHelper()->getUserId(); | |
} | |
/** | |
* Return the photo count for the feed. | |
* | |
* @return string | |
*/ | |
public function getPhotoCount() | |
{ | |
return $this->getInstagramHelper()->getPhotoCount(); | |
} | |
/** | |
* @return FirstScribe_Client_Helper_Instagram | |
*/ | |
public function getInstagramHelper() | |
{ | |
if (!$this->_helper) { | |
$this->_helper = $this->helper('firstscribe_client/instagram'); | |
} | |
return $this->_helper; | |
} | |
protected function _prepareLayout() | |
{ | |
parent::_prepareLayout(); | |
$this->setData('cache_lifetime', '21600'); // 6 hours | |
return $this; | |
} | |
protected function _toHtml() | |
{ | |
return $this->getFeed() ? parent::_toHtml() : ''; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment