Source of file InstagramAccount.php
Size: 8,081 Bytes - Last Modified: 2021-12-23T10:37:52+00:00
/var/www/docs.ssmods.com/process/src/code/model/InstagramAccount.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 | <?php use Larabros\Elogram\Client; class InstagramAccount extends DataObject { /** * @config * @var string */ private static $client_id; /** * @config * @var string */ private static $client_secret; /** * @config * @var string */ private static $redirect_path; /** * @config */ private static $items_per_page = 9; /** * @var array */ private static $db = [ 'Title' => 'Varchar', 'AccessToken' => 'Text', ]; /** * @return FieldList */ public function getCMSFields() { $fields = parent::getCMSFields(); $fields->removeByName('AccessToken'); if ($this->AccessToken) { $token = json_decode($this->AccessToken); $usernameField = LiteralField::create( 'Title', '<div class="field">' . '<label class="left">' . _t('Instagram.FieldLabelTitle', 'Username') . '</label>' . '<div class="middleColumn" style="padding-top:8px;">' . '<a ' . "href='https://www.instagram.com/{$token->user->username}' " . 'title="View on Instagram" ' . 'target="_blank">' . $token->user->username . '</a>' . '</div>' . '</div>' ); } else { $usernameField = Textfield::create('Title', _t('Instagram.FieldLabelTitle', 'Username')); $usernameField->setDescription( _t( 'Instagram.FieldDescriptionTitle', 'The Instagram account you want to pull media from.' ) ); } $fields->addFieldToTab('Root.Main', $usernameField); $this->extend('updateCMSFields', $fields); return $fields; } /** * @return FieldList */ public function getCMSActions() { $actions = parent::getCMSActions(); if (!$this->ID || $this->AccessToken) { $this->extend('updateCMSActions', $actions); return $actions; } $client = self::getNewInstagramClient(); $loginURL = $client->getLoginUrl(); $this->setSessionOAuthState($this->getOAuthStateValueFromLoginURL($loginURL)); $actions->push( LiteralField::create( 'OAuthLink', '<a class="ss-ui-button" href="' . $loginURL . '">' . _t('Instagram.ButtonLabelAuthoriseAccount', 'Authorise account') . '</a>' ) ); $this->extend('updateCMSActions', $actions); return $actions; } /** * @return RequiredFields */ public function getCMSValidator() { return new RequiredFields('Title'); } /** * Ensures the person to authorising the account is logged into Instagram as the correct user * before setting the token. * * For example if the user is logged into Instagram as 'FooUser' and they attempt to set a token * for the InstagramAccount record 'InstagramAccount', the token will contain data relating to * the 'FooUser' account. So if this happen we display a message telling the user they need to * log out of Instagram before they can authorise another account. * * @param string $token */ public function updateAccessToken($token, $state) { $newToken = json_decode($token); if ($state !== $this->getSessionOAuthState() || $newToken->user->username !== $this->getField('Title')) { throw new Exception('Trying to set token on wrong InstagramAccount'); } if (!$currentToken = $this->getField('AccessToken')) { $this->setField('AccessToken', $token); return; } $currentToken = json_decode($currentToken); if ($newToken->user->id !== $currentToken->user->id) { throw new Exception('Trying to set token on wrong InstagramAccount'); } $this->setField('AccessToken', $token); } /** * Create a configured Instagram API interface. * * @param string $token * @return MetzWeb\Instagram\Instagram */ public static function getNewInstagramClient($token = null) { $client_id = Config::inst()->get('InstagramAccount', 'client_id'); $client_secret = Config::inst()->get('InstagramAccount', 'client_secret'); $redirect_path = Config::inst()->get('InstagramAccount', 'redirect_path'); if (!$client_id) { user_error( 'Add a client_id to config (InstagramAdmin::client_id)', E_USER_ERROR ); } if (!$client_secret) { user_error( 'Add a client_secret to config (InstagramAdmin::client_secret)', E_USER_ERROR ); } return new Client( $client_id, $client_secret, $token, Director::absoluteBaseURL() . $redirect_path ); } /** * Gets the 'state' value from an OAuth login URL. * * @param string $loginURL * @return string|null */ public function getOAuthStateValueFromLoginURL($loginURL = null) { if (!$loginURL) { return null; } $parts = parse_url($loginURL); parse_str($parts['query'], $query); return array_key_exists('state', $query) ? $query['state'] : null; } /** * Gets the InstsgramAccount's OAuth state from Session. * * @return string|null */ public function getSessionOAuthState() { $instagramAccounts = Session::get('InstagramAccounts'); if (!$this->ID || !$instagramAccounts || !array_key_exists($this->ID, $instagramAccounts)) { return null; } return $instagramAccounts[$this->ID]; } /** * Gets the authorised user's Instagram ID from the AccessToken. * * @return string|null */ public function getInstagramID() { if (!$token = $this->getField('AccessToken')) { return null; } return json_decode($token)->user->id; } /** * Checks if the passed ID is a valid pattern. * * @param string $mediaID * @return boolean */ public function isValidMediaID($mediaID = null) { if (!$mediaID || !$instagramID = $this->getInstagramID()) { return false; } $pattern = '/^(\d{18}|\d{19})_' . $instagramID . '$/'; return preg_match($pattern, $mediaID) === 1; } /** * Sets a Session variable which is used to keep track of * the InstagramAccount through the OAuth flow. * * @param string $state */ private function setSessionOAuthState($state = null) { if (!$this->ID || !$state) { return null; } $instagramAccounts = Session::get('InstagramAccounts'); $instagramAccounts = $instagramAccounts ? $instagramAccounts : []; $instagramAccounts[$this->ID] = $state; Session::set('InstagramAccounts', $instagramAccounts); } /** * Gets a list of media from the user's Instagram. * * @param string $maxID Return media earlier than this ID * @return Larabros\Elogram\Http\Response|null */ public function getMedia($maxID = null) { if ( !is_string($this->getField('AccessToken')) || ($maxID && !$this->isValidMediaID($maxID)) ) { return null; } $client = $this->getNewInstagramClient($this->getField('AccessToken')); $client->secureRequests(); return $client->users()->getMedia('self', $this->config()->items_per_page, null, $maxID); } } |