├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── DependencyInjection ├── Configuration.php ├── FOSTwitterExtension.php └── Security │ └── Factory │ └── TwitterFactory.php ├── FOSTwitterBundle.php ├── README.md ├── Resources ├── config │ ├── schema │ │ └── twitter-1.0.xsd │ ├── security.xml │ └── twitter.xml ├── meta │ └── LICENSE └── views │ ├── initialize.html.php │ ├── initialize.html.twig │ ├── setup.html.php │ └── setup.html.twig ├── Security ├── Authentication │ ├── Provider │ │ ├── TwitterAnywhereProvider.php │ │ └── TwitterProvider.php │ └── Token │ │ ├── TwitterAnywhereToken.php │ │ └── TwitterUserToken.php ├── EntryPoint │ └── TwitterAuthenticationEntryPoint.php ├── Exception │ └── ConnectionException.php ├── Firewall │ └── TwitterListener.php └── User │ └── UserManagerInterface.php ├── Services └── Twitter.php ├── Templating └── Helper │ └── TwitterAnywhereHelper.php ├── Tests ├── DependencyInjection │ └── FOSTwitterExtensionTest.php ├── autoload.php.dist └── bootstrap.php ├── Twig └── Extension │ └── TwitterAnywhereExtension.php ├── composer.json ├── phpunit.xml.dist └── vendor └── vendors.php /.gitignore: -------------------------------------------------------------------------------- 1 | phpunit.xml 2 | coverage 3 | vendor/symfony 4 | vendor/twig 5 | vendor/twitteroauth -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.3 5 | - 5.4 6 | 7 | env: 8 | - SYMFONY_VERSION=v2.0.7 9 | - SYMFONY_VERSION=origin/2.0 10 | 11 | before_script: php vendor/vendors.php 12 | 13 | notifications: 14 | email: 15 | - friendsofsymfony-dev@googlegroups.com 16 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | This document details all changes between different versions of FOSTwitterBundle: 2 | 3 | 1.1 4 | --- 5 | 6 | - made user creation explicit by introducing a UserManagerInterface (this allows 7 | to create a user object if someone logs in through Twitter for the first time) 8 | 9 | 1.0 10 | --- 11 | 12 | Initial release 13 | -------------------------------------------------------------------------------- /DependencyInjection/Configuration.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\TwitterBundle\DependencyInjection; 13 | 14 | use Symfony\Component\Config\Definition\Builder\TreeBuilder, 15 | Symfony\Component\Config\Definition\ConfigurationInterface; 16 | 17 | /** 18 | * Configuration for the bundle 19 | */ 20 | class Configuration implements ConfigurationInterface 21 | { 22 | /** 23 | * Generates the configuration tree. 24 | * 25 | * @return TreeBuilder 26 | */ 27 | public function getConfigTreeBuilder() 28 | { 29 | $treeBuilder = new TreeBuilder(); 30 | $rootNode = $treeBuilder->root('fos_twitter'); 31 | 32 | $rootNode 33 | ->validate() 34 | ->always(function($v) { 35 | if (!empty($v['callback_url']) && !empty($v['callback_route'])) { 36 | throw new \Exception('You cannot configure a "callback_url", and a "callback_route" at the same time.'); 37 | } 38 | 39 | return $v; 40 | }) 41 | ->end() 42 | ->children() 43 | ->scalarNode('file')->defaultValue('%kernel.root_dir%/../vendor/twitteroauth/twitteroauth/twitteroauth.php')->end() 44 | ->scalarNode('consumer_key')->isRequired()->cannotBeEmpty()->end() 45 | ->scalarNode('consumer_secret')->isRequired()->cannotBeEmpty()->end() 46 | ->scalarNode('access_token')->defaultNull()->end() 47 | ->scalarNode('access_token_secret')->defaultNull()->end() 48 | ->scalarNode('callback_url')->defaultNull()->end() 49 | ->scalarNode('callback_route')->defaultNull()->end() 50 | ->scalarNode('anywhere_version')->defaultValue('1')->end() 51 | ->scalarNode('alias')->defaultNull()->end() 52 | ->end() 53 | ; 54 | 55 | return $treeBuilder; 56 | } 57 | 58 | } 59 | 60 | -------------------------------------------------------------------------------- /DependencyInjection/FOSTwitterExtension.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\TwitterBundle\DependencyInjection; 13 | 14 | use Symfony\Component\DependencyInjection\Reference; 15 | 16 | use Symfony\Component\Config\Definition\Processor; 17 | use Symfony\Component\HttpKernel\DependencyInjection\Extension; 18 | use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; 19 | use Symfony\Component\DependencyInjection\ContainerBuilder; 20 | use Symfony\Component\Config\FileLocator; 21 | 22 | class FOSTwitterExtension extends Extension 23 | { 24 | protected $resources = array( 25 | 'twitter' => 'twitter.xml', 26 | 'security' => 'security.xml', 27 | ); 28 | 29 | public function load(array $configs, ContainerBuilder $container) 30 | { 31 | $processor = new Processor(); 32 | $configuration = new Configuration(); 33 | $config = $processor->processConfiguration($configuration, $configs); 34 | 35 | $this->loadDefaults($container); 36 | 37 | if (isset($config['alias'])) { 38 | $container->setAlias($config['alias'], 'fos_twitter.service'); 39 | } 40 | 41 | foreach (array('file', 'consumer_key', 'consumer_secret', 'callback_url', 'access_token', 'access_token_secret', 'anywhere_version') as $attribute) { 42 | if (isset($config[$attribute])) { 43 | $container->setParameter('fos_twitter.'.$attribute, $config[$attribute]); 44 | } 45 | } 46 | 47 | if (!empty($config['callback_route'])) { 48 | $container 49 | ->getDefinition('fos_twitter.service') 50 | ->addMethodCall('setCallbackRoute', array( 51 | new Reference('router'), 52 | $config['callback_route'], 53 | )) 54 | ; 55 | } 56 | } 57 | 58 | /** 59 | * @codeCoverageIgnore 60 | */ 61 | public function getXsdValidationBasePath() 62 | { 63 | return __DIR__.'/../Resources/config/schema'; 64 | } 65 | 66 | /** 67 | * @codeCoverageIgnore 68 | */ 69 | public function getNamespace() 70 | { 71 | return 'http://friendsofsymfony.github.com/schema/dic/twitter'; 72 | } 73 | 74 | /** 75 | * @codeCoverageIgnore 76 | */ 77 | protected function loadDefaults($container) 78 | { 79 | $loader = new XmlFileLoader($container, new FileLocator(array(__DIR__.'/../Resources/config', __DIR__.'/Resources/config'))); 80 | 81 | foreach ($this->resources as $resource) { 82 | $loader->load($resource); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /DependencyInjection/Security/Factory/TwitterFactory.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\TwitterBundle\DependencyInjection\Security\Factory; 13 | 14 | use Symfony\Component\DependencyInjection\ContainerBuilder; 15 | use Symfony\Component\DependencyInjection\Reference; 16 | use Symfony\Component\DependencyInjection\DefinitionDecorator; 17 | use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\AbstractFactory; 18 | 19 | class TwitterFactory extends AbstractFactory 20 | { 21 | public function __construct() 22 | { 23 | $this->addOption('use_twitter_anywhere', false); 24 | $this->addOption('create_user_if_not_exists', false); 25 | } 26 | 27 | public function getPosition() 28 | { 29 | return 'pre_auth'; 30 | } 31 | 32 | public function getKey() 33 | { 34 | return 'fos_twitter'; 35 | } 36 | 37 | protected function getListenerId() 38 | { 39 | return 'fos_twitter.security.authentication.listener'; 40 | } 41 | 42 | protected function createAuthProvider(ContainerBuilder $container, $id, $config, $userProviderId) 43 | { 44 | // configure auth with Twitter Anywhere 45 | if (true === $config['use_twitter_anywhere']) { 46 | if (isset($config['provider'])) { 47 | $authProviderId = 'fos_twitter.anywhere_auth.'.$id; 48 | 49 | $container 50 | ->setDefinition($authProviderId, new DefinitionDecorator('fos_twitter.anywhere_auth')) 51 | ->addArgument(new Reference($userProviderId)) 52 | ->addArgument(new Reference('security.user_checker')) 53 | ->addArgument($config['create_user_if_not_exists']) 54 | ; 55 | 56 | return $authProviderId; 57 | } 58 | 59 | // no user provider 60 | return 'fos_twitter.anywhere_auth'; 61 | } 62 | 63 | // configure auth for standard Twitter API 64 | // with user provider 65 | if (isset($config['provider'])) { 66 | $authProviderId = 'fos_twitter.auth.'.$id; 67 | 68 | $container 69 | ->setDefinition($authProviderId, new DefinitionDecorator('fos_twitter.auth')) 70 | ->addArgument(new Reference($userProviderId)) 71 | ->addArgument(new Reference('security.user_checker')) 72 | ->addArgument($config['create_user_if_not_exists']) 73 | ; 74 | 75 | return $authProviderId; 76 | } 77 | 78 | // without user provider 79 | return 'fos_twitter.auth'; 80 | } 81 | 82 | protected function createListener($container, $id, $config, $userProvider) 83 | { 84 | $listenerId = parent::createListener($container, $id, $config, $userProvider); 85 | 86 | if ($config['use_twitter_anywhere']) { 87 | $container 88 | ->getDefinition($listenerId) 89 | ->addMethodCall('setUseTwitterAnywhere', array(true)) 90 | ; 91 | } 92 | 93 | return $listenerId; 94 | } 95 | 96 | protected function createEntryPoint($container, $id, $config, $defaultEntryPointId) 97 | { 98 | $entryPointId = 'fos_twitter.security.authentication.entry_point.'.$id; 99 | $container 100 | ->setDefinition($entryPointId, new DefinitionDecorator('fos_twitter.security.authentication.entry_point')) 101 | ; 102 | 103 | return $entryPointId; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /FOSTwitterBundle.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\TwitterBundle; 13 | 14 | use FOS\TwitterBundle\DependencyInjection\Security\Factory\TwitterFactory; 15 | use Symfony\Component\DependencyInjection\ContainerBuilder; 16 | use Symfony\Component\HttpKernel\Bundle\Bundle; 17 | 18 | class FOSTwitterBundle extends Bundle 19 | { 20 | public function build(ContainerBuilder $container) 21 | { 22 | parent::build($container); 23 | 24 | $extension = $container->getExtension('security'); 25 | $extension->addSecurityListenerFactory(new TwitterFactory()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DEPRECATED 2 | ========== 3 | 4 | See [HWIOAuthBundle](https://github.com/hwi/HWIOAuthBundle) instead 5 | ------------------------------------------------------------------- 6 | 7 | Introduction 8 | ============ 9 | 10 | This Bundle enables integration with Twitter PHP. Furthermore it 11 | also provides a Symfony2 authentication provider so that users can login to a 12 | Symfony2 application via Twitter. Furthermore via custom user provider support 13 | the Twitter login can also be integrated with other data sources like the 14 | database based solution provided by FOSUserBundle. 15 | 16 | ``If you are using Symfony 2.0 switch to the branch v1.0 of TwitterBundle or use the tag 1.0.0`` 17 | 18 | [![Build Status](https://secure.travis-ci.org/FriendsOfSymfony/FOSTwitterBundle.png)](http://travis-ci.org/FriendsOfSymfony/FOSTwitterBundle) 19 | 20 | Installation 21 | ============ 22 | 23 | 1. Add this bundle and Abraham Williams' Twitter library to your project as Git submodules: 24 | 25 | $ git submodule add git://github.com/FriendsOfSymfony/FOSTwitterBundle.git vendor/bundles/FOS/TwitterBundle 26 | $ git submodule add git://github.com/kertz/twitteroauth.git vendor/twitteroauth 27 | 28 | >**Note:** The kertz/twitteroauth is patched to be compatible with FOSTwitterBundle 29 | 30 | 2. Register the namespace `FOS` to your project's autoloader bootstrap script: 31 | 32 | //app/autoload.php 33 | $loader->registerNamespaces(array( 34 | // ... 35 | 'FOS' => __DIR__.'/../vendor/bundles', 36 | // ... 37 | )); 38 | 39 | 3. Add this bundle to your application's kernel: 40 | 41 | //app/AppKernel.php 42 | public function registerBundles() 43 | { 44 | return array( 45 | // ... 46 | new FOS\TwitterBundle\FOSTwitterBundle(), 47 | // ... 48 | ); 49 | } 50 | 51 | 4. Configure the `twitter` service in your YAML configuration: 52 | 53 | #app/config/config.yml 54 | fos_twitter: 55 | file: %kernel.root_dir%/../vendor/twitteroauth/twitteroauth/twitteroauth.php 56 | consumer_key: xxxxxx 57 | consumer_secret: xxxxxx 58 | callback_url: http://www.example.com/login_check 59 | 60 | 5. Add the following configuration to use the security component: 61 | 62 | #app/config/security.yml 63 | security: 64 | providers: 65 | fos_twitter: 66 | id: fos_twitter.auth 67 | firewalls: 68 | secured: 69 | pattern: /secured/.* 70 | fos_twitter: true 71 | public: 72 | pattern: /.* 73 | anonymous: true 74 | fos_twitter: true 75 | logout: true 76 | access_control: 77 | - { path: /.*, role: [IS_AUTHENTICATED_ANONYMOUSLY] } 78 | 79 | Using Twitter @Anywhere 80 | ----------------------- 81 | 82 | >**Note:** If you want the Security Component to work with Twitter @Anywhere, you need to send a request to the configured check path upon successful client authentication (see https://gist.github.com/1021384 for a sample configuration). 83 | 84 | A templating helper is included for using Twitter @Anywhere. To use it, first 85 | call the `->setup()` method toward the top of your DOM: 86 | 87 | 88 | setup() ?> 89 | 90 | 91 | 92 | {{ twitter_anywhere_setup() }} 93 | 94 | 95 | Once that's done, you can queue up JavaScript to be run once the library is 96 | actually loaded: 97 | 98 | 99 | 100 | setConfig('callbackURL', 'http://www.example.com/login_check') ?> 101 | queue('T("#twitter_connect").connectButton()') ?> 102 | 103 | 104 | 105 | {{ twitter_anywhere_setConfig('callbackURL', 'http://www.example.com/login_check') }} 106 | {{ twitter_anywhere_queue('T("#twitter_connect").connectButton()') }} 107 | 108 | Finally, call the `->initialize()` method toward the bottom of the DOM: 109 | 110 | 111 | initialize() ?> 112 | 113 | 114 | 115 | {{ twitter_anywhere_initialize() }} 116 | 117 | 118 | ### Configuring Twitter @Anywhere 119 | 120 | You can set configuration using the templating helper. with the setConfig() method. 121 | 122 | 123 | Example Custom User Provider using the FOSUserBundle 124 | ------------------------------------------------------- 125 | 126 | 127 | To use this provider you will need to add a new service in your config.yml 128 | 129 | ``` yaml 130 | # app/config/config.yml 131 | services: 132 | my.twitter.user: 133 | class: Acme\YourBundle\Security\User\Provider\TwitterUserProvider 134 | arguments: 135 | twitter_oauth: "@fos_twitter.api" 136 | userManager: "@fos_user.user_manager" 137 | validator: "@validator" 138 | session: "@session" 139 | ``` 140 | 141 | Also you would need some new properties and methods in your User model class. 142 | 143 | ``` php 144 | 145 | twitterID = $twitterID; 167 | $this->setUsername($twitterID); 168 | $this->salt = ''; 169 | } 170 | 171 | /** 172 | * Get twitterID 173 | * 174 | * @return string 175 | */ 176 | public function getTwitterID() 177 | { 178 | return $this->twitterID; 179 | } 180 | 181 | /** 182 | * Set twitter_username 183 | * 184 | * @param string $twitterUsername 185 | */ 186 | public function setTwitterUsername($twitterUsername) 187 | { 188 | $this->twitter_username = $twitterUsername; 189 | } 190 | 191 | /** 192 | * Get twitter_username 193 | * 194 | * @return string 195 | */ 196 | public function getTwitterUsername() 197 | { 198 | return $this->twitter_username; 199 | } 200 | ``` 201 | 202 | And this is the TwitterUserProvider class 203 | 204 | ``` php 205 | twitter_oauth = $twitter_oauth; 233 | $this->userManager = $userManager; 234 | $this->validator = $validator; 235 | $this->session = $session; 236 | } 237 | 238 | public function supportsClass($class) 239 | { 240 | return $this->userManager->supportsClass($class); 241 | } 242 | 243 | public function findUserByTwitterId($twitterID) 244 | { 245 | return $this->userManager->findUserBy(array('twitterID' => $twitterID)); 246 | } 247 | 248 | public function loadUserByUsername($username) 249 | { 250 | $user = $this->findUserByTwitterId($username); 251 | 252 | $this->twitter_oauth->setOAuthToken($this->session->get('access_token'), $this->session->get('access_token_secret')); 253 | 254 | try { 255 | $info = $this->twitter_oauth->get('account/verify_credentials'); 256 | } catch (Exception $e) { 257 | $info = null; 258 | } 259 | 260 | if (!empty($info)) { 261 | if (empty($user)) { 262 | $user = $this->userManager->createUser(); 263 | $user->setEnabled(true); 264 | $user->setPassword(''); 265 | $user->setAlgorithm(''); 266 | } 267 | 268 | $username = $info->screen_name; 269 | 270 | $user->setTwitterID($info->id); 271 | $user->setTwitterUsername($username); 272 | $user->setEmail(''); 273 | $user->setFirstname($info->name); 274 | 275 | $this->userManager->updateUser($user); 276 | } 277 | 278 | if (empty($user)) { 279 | throw new UsernameNotFoundException('The user is not authenticated on twitter'); 280 | } 281 | 282 | return $user; 283 | } 284 | 285 | public function refreshUser(UserInterface $user) 286 | { 287 | if (!$this->supportsClass(get_class($user)) || !$user->getTwitterID()) { 288 | throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user))); 289 | } 290 | 291 | return $this->loadUserByUsername($user->getTwitterID()); 292 | } 293 | } 294 | ``` 295 | 296 | 297 | Finally, to get the authentication tokens from Twitter you would need to create an action in your controller like this one. 298 | 299 | ``` php 300 | 301 | get('request'); 312 | $twitter = $this->get('fos_twitter.service'); 313 | 314 | $authURL = $twitter->getLoginUrl($request); 315 | 316 | $response = new RedirectResponse($authURL); 317 | 318 | return $response; 319 | 320 | } 321 | 322 | ``` 323 | 324 | You can create a button in your Twig template that will send the user to authenticate with Twitter. 325 | 326 | ``` 327 | 328 | 329 | ``` 330 | 331 | * Note: Your callback URL in your config.yml must point to your configured check_path 332 | 333 | ``` yaml 334 | # app/config/config.yml 335 | 336 | fos_twitter: 337 | ... 338 | callback_url: http://www.yoursite.com/twitter/login_check 339 | ``` 340 | 341 | Remember to edit your security.yml to use this provider 342 | 343 | 344 | ``` yaml 345 | # app/config/security.yml 346 | 347 | security: 348 | encoders: 349 | Symfony\Component\Security\Core\User\User: plaintext 350 | 351 | role_hierarchy: 352 | ROLE_ADMIN: ROLE_USER 353 | ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH] 354 | 355 | providers: 356 | 357 | my_fos_twitter_provider: 358 | id: my.twitter.user 359 | 360 | firewalls: 361 | dev: 362 | pattern: ^/(_(profiler|wdt)|css|images|js)/ 363 | security: false 364 | 365 | public: 366 | pattern: / 367 | fos_twitter: 368 | login_path: /twitter/login 369 | check_path: /twitter/login_check 370 | default_target_path: / 371 | provider: my_fos_twitter_provider 372 | 373 | anonymous: ~ 374 | 375 | ``` 376 | -------------------------------------------------------------------------------- /Resources/config/schema/twitter-1.0.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Resources/config/security.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | %fos_twitter.consumer_secret% 14 | 15 | 16 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Resources/config/twitter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | null 9 | null 10 | null 11 | null 12 | null 13 | null 14 | 1 15 | 16 | FOS\TwitterBundle\Templating\Helper\TwitterAnywhereHelper 17 | FOS\TwitterBundle\Twig\Extension\TwitterAnywhereExtension 18 | 19 | TwitterOAuth 20 | FOS\TwitterBundle\Services\Twitter 21 | 22 | 23 | 24 | 25 | 26 | 27 | %fos_twitter.callback_url% 28 | 29 | 30 | 31 | 32 | %fos_twitter.file% 33 | %fos_twitter.consumer_key% 34 | %fos_twitter.consumer_secret% 35 | %fos_twitter.access_token% 36 | %fos_twitter.access_token_secret% 37 | 38 | 39 | 40 | 41 | 42 | %fos_twitter.consumer_key% 43 | %fos_twitter.anywhere_version% 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /Resources/meta/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) Kris Wallsmith 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /Resources/views/initialize.html.php: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /Resources/views/initialize.html.twig: -------------------------------------------------------------------------------- 1 | {% autoescape false %} 2 | 11 | {% endautoescape %} 12 | -------------------------------------------------------------------------------- /Resources/views/setup.html.php: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Resources/views/setup.html.twig: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Security/Authentication/Provider/TwitterAnywhereProvider.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\TwitterBundle\Security\Authentication\Provider; 13 | 14 | use Symfony\Component\Security\Core\User\UserInterface; 15 | use Symfony\Component\Security\Core\User\UserCheckerInterface; 16 | use Symfony\Component\Security\Core\User\UserProviderInterface; 17 | use Symfony\Component\Security\Core\Exception\AuthenticationException; 18 | use FOS\TwitterBundle\Security\Authentication\Token\TwitterAnywhereToken; 19 | use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; 20 | use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface; 21 | 22 | class TwitterAnywhereProvider implements AuthenticationProviderInterface 23 | { 24 | private $consumerSecret; 25 | private $provider; 26 | private $checker; 27 | 28 | public function __construct($consumerSecret, UserProviderInterface $provider = null, UserCheckerInterface $checker = null) 29 | { 30 | $this->consumerSecret = $consumerSecret; 31 | $this->provider = $provider; 32 | $this->checker = $checker; 33 | } 34 | 35 | public function authenticate(TokenInterface $token) 36 | { 37 | if (!$this->supports($token)) { 38 | return null; 39 | } 40 | 41 | // previously authenticated user 42 | $user = $token->getUser(); 43 | if ($user instanceof UserInterface) { 44 | if (null !== $this->checker) { 45 | $this->checker->checkPostAuth($user); 46 | } 47 | 48 | $authenticated = TwitterAnywhereToken::createAuthenticated($user, $user->getRoles()); 49 | $authenticated->setAttributes($token->getAttributes()); 50 | 51 | return $authenticated; 52 | } 53 | 54 | if (!$this->isSignatureValid($token->getSignature(), sha1($token->getUser().$this->consumerSecret))) { 55 | throw new AuthenticationException(sprintf('The presented signature was invalid.')); 56 | } 57 | 58 | if (null === $this->provider) { 59 | $authenticated = TwitterAnywhereToken::createAuthenticated($token->getUser(), array()); 60 | $authenticated->setAttributes($token->getAttributes()); 61 | 62 | return $authenticated; 63 | } 64 | 65 | try { 66 | $user = $this->provider->loadUserByUsername($token->getUser()); 67 | $this->checker->checkPostAuth($user); 68 | 69 | $authenticated = TwitterAnywhereToken::createAuthenticated($user, $user->getRoles()); 70 | $authenticated->setAttributes($token->getAttributes()); 71 | 72 | return $authenticated; 73 | } catch (AuthenticationException $passthroughEx) { 74 | throw $passthroughEx; 75 | } catch (\Exception $ex) { 76 | throw new AuthenticationException($ex->getMessage(), null, 0, $ex); 77 | } 78 | } 79 | 80 | public function supports(TokenInterface $token) 81 | { 82 | return $token instanceof TwitterAnywhereToken; 83 | } 84 | 85 | private function isSignatureValid($actual, $expected) 86 | { 87 | if (strlen($actual) !== $c = strlen($expected)) { 88 | return false; 89 | } 90 | 91 | $result = 0; 92 | for ($i = 0; $i < $c; $i++) { 93 | $result |= ord($actual[$i]) ^ ord($expected[$i]); 94 | } 95 | 96 | return 0 === $result; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Security/Authentication/Provider/TwitterProvider.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\TwitterBundle\Security\Authentication\Provider; 13 | 14 | use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; 15 | use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; 16 | use FOS\TwitterBundle\Security\User\UserManagerInterface; 17 | use Symfony\Component\Security\Core\User\UserInterface; 18 | use Symfony\Component\Security\Core\User\UserCheckerInterface; 19 | use Symfony\Component\Security\Core\User\UserProviderInterface; 20 | use Symfony\Component\Security\Core\Exception\AuthenticationException; 21 | use Symfony\Component\Security\Core\Exception\UnsupportedUserException; 22 | use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; 23 | use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface; 24 | use Symfony\Component\DependencyInjection\Container; 25 | 26 | use FOS\TwitterBundle\Security\Authentication\Token\TwitterUserToken; 27 | use FOS\TwitterBundle\Services\Twitter; 28 | 29 | class TwitterProvider implements AuthenticationProviderInterface 30 | { 31 | private $twitter; 32 | private $userProvider; 33 | private $userChecker; 34 | private $createUserIfNotExists; 35 | 36 | public function __construct(Twitter $twitter, UserProviderInterface $userProvider = null, UserCheckerInterface $userChecker = null, $createUserIfNotExists = false) 37 | { 38 | if (null !== $userProvider && null === $userChecker) { 39 | throw new \InvalidArgumentException('$userChecker cannot be null, if $userProvider is not null.'); 40 | } 41 | 42 | if ($createUserIfNotExists && !$userProvider instanceof UserManagerInterface) { 43 | throw new \InvalidArgumentException('$userProvider must be an instanceof UserManagerInterface if createUserIfNotExists is true.'); 44 | } 45 | 46 | $this->twitter = $twitter; 47 | $this->userProvider = $userProvider; 48 | $this->userChecker = $userChecker; 49 | $this->createUserIfNotExists = $createUserIfNotExists; 50 | } 51 | 52 | public function authenticate(TokenInterface $token) 53 | { 54 | if (!$this->supports($token)) { 55 | return null; 56 | } 57 | 58 | $user = $token->getUser(); 59 | if ($user instanceof UserInterface) { 60 | // FIXME: Should we make a call to Twitter for verification? 61 | $newToken = new TwitterUserToken($user, null, $user->getRoles()); 62 | $newToken->setAttributes($token->getAttributes()); 63 | 64 | return $newToken; 65 | } 66 | 67 | try { 68 | if ($accessToken = $this->twitter->getAccessToken($token->getUser(), $token->getOauthVerifier())) { 69 | $newToken = $this->createAuthenticatedToken($accessToken); 70 | $newToken->setAttributes($token->getAttributes()); 71 | 72 | return $newToken; 73 | } 74 | } catch (AuthenticationException $failed) { 75 | throw $failed; 76 | } catch (\Exception $failed) { 77 | throw new AuthenticationException($failed->getMessage(), null, $failed->getCode(), $failed); 78 | } 79 | 80 | throw new AuthenticationException('The Twitter user could not be retrieved from the session.'); 81 | } 82 | 83 | public function supports(TokenInterface $token) 84 | { 85 | return $token instanceof TwitterUserToken; 86 | } 87 | 88 | private function createAuthenticatedToken(array $accessToken) 89 | { 90 | if (null === $this->userProvider) { 91 | return new TwitterUserToken($accessToken['screen_name'], null, array('ROLE_TWITTER_USER')); 92 | } 93 | 94 | try { 95 | $user = $this->userProvider->loadUserByUsername($accessToken['screen_name']); 96 | $this->userChecker->checkPostAuth($user); 97 | } catch (UsernameNotFoundException $ex) { 98 | if (!$this->createUserIfNotExists) { 99 | throw $ex; 100 | } 101 | 102 | $user = $this->userProvider->createUserFromAccessToken($accessToken); 103 | } 104 | 105 | if (!$user instanceof UserInterface) { 106 | throw new \RuntimeException('User provider did not return an implementation of user interface.'); 107 | } 108 | 109 | return new TwitterUserToken($user, null, $user->getRoles()); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Security/Authentication/Token/TwitterAnywhereToken.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\TwitterBundle\Security\Authentication\Token; 13 | 14 | use Symfony\Component\Security\Core\Authentication\Token\AbstractToken; 15 | 16 | class TwitterAnywhereToken extends AbstractToken 17 | { 18 | private $signature; 19 | 20 | /** 21 | * Constructor. 22 | * 23 | * Do not call this directly, use the static methods instead. 24 | * 25 | * @param mixed $user 26 | * @param array $roles 27 | */ 28 | public function __construct($user, array $roles) 29 | { 30 | parent::__construct($roles); 31 | $this->setUser($user); 32 | } 33 | 34 | public static function createUnauthenticated($userId, $signature) 35 | { 36 | $token = new self($userId, array()); 37 | $token->signature = $signature; 38 | 39 | return $token; 40 | } 41 | 42 | public static function createAuthenticated($user, array $roles) 43 | { 44 | $token = new self($user, $roles); 45 | $token->setAuthenticated(true); 46 | 47 | return $token; 48 | } 49 | 50 | public function getSignature() 51 | { 52 | return $this->signature; 53 | } 54 | 55 | public function getCredentials() 56 | { 57 | return ''; 58 | } 59 | 60 | public function serialize() 61 | { 62 | return serialize(array($this->signature, parent::serialize())); 63 | } 64 | 65 | public function unserialize($str) 66 | { 67 | list($this->signature, $parentStr) = unserialize($str); 68 | parent::unserialize($parentStr); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Security/Authentication/Token/TwitterUserToken.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\TwitterBundle\Security\Authentication\Token; 13 | 14 | use Symfony\Component\Security\Core\Authentication\Token\AbstractToken; 15 | 16 | class TwitterUserToken extends AbstractToken 17 | { 18 | private $oauthVerifier; 19 | 20 | public function __construct($uid = '', $oauthVerifier, array $roles = array()) 21 | { 22 | parent::__construct($roles); 23 | 24 | $this->oauthVerifier = $oauthVerifier; 25 | $this->setUser($uid); 26 | 27 | if (!empty($roles)) { 28 | parent::setAuthenticated(true); 29 | } 30 | } 31 | 32 | public function setAuthenticated($bool) 33 | { 34 | if ($bool) { 35 | throw new \LogicException('TwitterUserToken may not be set to authenticated after creation.'); 36 | } 37 | 38 | parent::setAuthenticated(false); 39 | } 40 | 41 | public function getCredentials() 42 | { 43 | return ''; 44 | } 45 | 46 | public function getOauthVerifier() 47 | { 48 | return $this->oauthVerifier; 49 | } 50 | 51 | public function serialize() 52 | { 53 | return serialize(array( 54 | $this->oauthVerifier, 55 | parent::serialize(), 56 | )); 57 | } 58 | 59 | public function unserialize($str) 60 | { 61 | list($this->oauthVerifier, $parentStr) = unserialize($str); 62 | parent::unserialize($parentStr); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Security/EntryPoint/TwitterAuthenticationEntryPoint.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\TwitterBundle\Security\EntryPoint; 13 | 14 | use Symfony\Component\HttpFoundation\ParameterBag; 15 | use Symfony\Component\HttpFoundation\Request; 16 | use Symfony\Component\HttpFoundation\RedirectResponse; 17 | use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; 18 | use Symfony\Component\Security\Core\Exception\AuthenticationException; 19 | use Symfony\Component\Security\Core\SecurityContext; 20 | 21 | use FOS\TwitterBundle\Security\Exception\ConnectionException; 22 | use FOS\TwitterBundle\Services\Twitter; 23 | 24 | /** 25 | * TwitterAuthenticationEntryPoint starts an authentication via Twitter. 26 | */ 27 | class TwitterAuthenticationEntryPoint implements AuthenticationEntryPointInterface 28 | { 29 | protected $twitter; 30 | 31 | /** 32 | * Constructor 33 | * 34 | * @param Twitter $twitter 35 | */ 36 | public function __construct(Twitter $twitter) 37 | { 38 | $this->twitter = $twitter; 39 | } 40 | 41 | /** 42 | * {@inheritdoc} 43 | */ 44 | public function start(Request $request, AuthenticationException $authException = null) 45 | { 46 | $authURL = $this->twitter->getLoginUrl(); 47 | if (!$authURL) { 48 | throw new ConnectionException('Could not connect to Twitter!'); 49 | } 50 | 51 | return new RedirectResponse($authURL); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Security/Exception/ConnectionException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\TwitterBundle\Security\Exception; 13 | 14 | use Symfony\Component\Security\Core\Exception\AuthenticationException; 15 | 16 | class ConnectionException extends AuthenticationException 17 | { 18 | } 19 | -------------------------------------------------------------------------------- /Security/Firewall/TwitterListener.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\TwitterBundle\Security\Firewall; 13 | 14 | use FOS\TwitterBundle\Security\Authentication\Token\TwitterAnywhereToken; 15 | use Symfony\Component\Security\Core\Exception\AuthenticationException; 16 | use FOS\TwitterBundle\Security\Authentication\Token\TwitterUserToken; 17 | use Symfony\Component\Security\Http\Firewall\AbstractAuthenticationListener; 18 | use Symfony\Component\HttpFoundation\Request; 19 | 20 | /** 21 | * Twitter authentication listener. 22 | */ 23 | class TwitterListener extends AbstractAuthenticationListener 24 | { 25 | private $useTwitterAnywhere = false; 26 | 27 | public function setUseTwitterAnywhere($bool) 28 | { 29 | $this->useTwitterAnywhere = (Boolean) $bool; 30 | } 31 | 32 | protected function attemptAuthentication(Request $request) 33 | { 34 | if ($this->useTwitterAnywhere) { 35 | if (null === $identity = $request->cookies->get('twitter_anywhere_identity')) { 36 | throw new AuthenticationException(sprintf('Identity cookie "twitter_anywhere_identity" was not sent.')); 37 | } 38 | if (false === $pos = strpos($identity, ':')) { 39 | throw new AuthenticationException(sprintf('The submitted identity "%s" is invalid.', $identity)); 40 | } 41 | 42 | return $this->authenticationManager->authenticate(TwitterAnywhereToken::createUnauthenticated(substr($identity, 0, $pos), substr($identity, $pos + 1))); 43 | } 44 | 45 | return $this->authenticationManager->authenticate(new TwitterUserToken($request->query->get('oauth_token'), $request->query->get('oauth_verifier'))); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Security/User/UserManagerInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\TwitterBundle\Services; 13 | 14 | use Symfony\Component\Routing\RouterInterface; 15 | 16 | use Symfony\Component\HttpFoundation\Session\Session; 17 | use Symfony\Component\HttpFoundation\Request; 18 | use Symfony\Component\Security\Core\Exception\AuthenticationException; 19 | use TwitterOAuth; 20 | 21 | class Twitter 22 | { 23 | private $twitter; 24 | private $session; 25 | private $router; 26 | private $callbackRoute; 27 | private $callbackURL; 28 | 29 | public function __construct(TwitterOAuth $twitter, Session $session, $callbackURL = null) 30 | { 31 | $this->twitter = $twitter; 32 | $this->session = $session; 33 | $this->callbackURL = $callbackURL; 34 | } 35 | 36 | public function setCallbackRoute(RouterInterface $router, $routeName) 37 | { 38 | $this->router = $router; 39 | $this->callbackRoute = $routeName; 40 | } 41 | 42 | public function getLoginUrl() 43 | { 44 | /* Get temporary credentials. */ 45 | $requestToken = ($callbackUrl = $this->getCallbackUrl()) ? 46 | $this->twitter->getRequestToken($callbackUrl) 47 | : $this->twitter->getRequestToken(); 48 | 49 | if (!isset($requestToken['oauth_token']) || !isset($requestToken['oauth_token_secret'])) { 50 | throw new \RuntimeException('Failed to validate oauth signature and token.'); 51 | } 52 | 53 | /* Save temporary credentials to session. */ 54 | $this->session->set('oauth_token', $requestToken['oauth_token']); 55 | $this->session->set('oauth_token_secret', $requestToken['oauth_token_secret']); 56 | 57 | /* If last connection failed don't display authorization link. */ 58 | switch ($this->twitter->http_code) { 59 | case 200: 60 | /* Build authorize URL and redirect user to Twitter. */ 61 | $redirectURL = $this->twitter->getAuthorizeURL($requestToken); 62 | return $redirectURL; 63 | break; 64 | default: 65 | /* return null if something went wrong. */ 66 | return null; 67 | } 68 | } 69 | 70 | public function getAccessToken($oauthToken, $oauthVerifier) 71 | { 72 | //set OAuth token in the API 73 | $this->twitter->setOAuthToken($oauthToken, $this->session->get('oauth_token_secret')); 74 | 75 | /* Check if the oauth_token is old */ 76 | if ($this->session->has('oauth_token')) { 77 | if ($this->session->get('oauth_token') && ($this->session->get('oauth_token') !== $oauthToken)) { 78 | $this->session->remove('oauth_token'); 79 | return null; 80 | } 81 | } 82 | 83 | /* Request access tokens from twitter */ 84 | $accessToken = $this->twitter->getAccessToken($oauthVerifier); 85 | 86 | /* Save the access tokens. Normally these would be saved in a database for future use. */ 87 | $this->session->set('access_token', $accessToken['oauth_token']); 88 | $this->session->set('access_token_secret', $accessToken['oauth_token_secret']); 89 | 90 | /* Remove no longer needed request tokens */ 91 | !$this->session->has('oauth_token') ?: $this->session->remove('oauth_token', null); 92 | !$this->session->has('oauth_token_secret') ?: $this->session->remove('oauth_token_secret', null); 93 | 94 | /* If HTTP response is 200 continue otherwise send to connect page to retry */ 95 | if (200 == $this->twitter->http_code) { 96 | /* The user has been verified and the access tokens can be saved for future use */ 97 | return $accessToken; 98 | } 99 | 100 | /* Return null for failure */ 101 | return null; 102 | } 103 | 104 | private function getCallbackUrl() 105 | { 106 | if (!empty($this->callbackURL)) { 107 | return $this->callbackURL; 108 | } 109 | 110 | if (!empty($this->callbackRoute)) { 111 | return $this->router->generate($this->callbackRoute, array(), true); 112 | } 113 | 114 | return null; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /Templating/Helper/TwitterAnywhereHelper.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\TwitterBundle\Templating\Helper; 13 | 14 | use Symfony\Component\Templating\Helper\Helper; 15 | use Symfony\Component\Templating\EngineInterface; 16 | 17 | class TwitterAnywhereHelper extends Helper 18 | { 19 | protected $templating; 20 | protected $apiKey; 21 | protected $version; 22 | protected $callbackURL; 23 | 24 | protected $config = array(); 25 | protected $scripts = array(); 26 | 27 | public function __construct(EngineInterface $templating, $apiKey, $version = 1) 28 | { 29 | $this->templating = $templating; 30 | $this->apiKey = $apiKey; 31 | $this->version = $version; 32 | } 33 | 34 | /* 35 | * 36 | */ 37 | public function setup($parameters = array(), $name = null) 38 | { 39 | $name = $name ?: 'FOSTwitterBundle::setup.html.php'; 40 | return $this->templating->render($name, $parameters + array( 41 | 'apiKey' => $this->apiKey, 42 | 'version' => $this->version, 43 | )); 44 | } 45 | 46 | /* 47 | * 48 | */ 49 | public function initialize($parameters = array(), $name = null) 50 | { 51 | //convert scripts into lines 52 | $lines = ''; 53 | foreach ($this->scripts as $script) { 54 | $lines .= rtrim($script, ';').";\n"; 55 | } 56 | 57 | $name = $name ?: 'FOSTwitterBundle::initialize.html.php'; 58 | return $this->templating->render($name, $parameters + array( 59 | 'configMap' => $this->config, 60 | 'scripts' => $lines, 61 | )); 62 | } 63 | 64 | /* 65 | * 66 | */ 67 | public function queue($script) 68 | { 69 | $this->scripts[] = $script; 70 | } 71 | 72 | /* 73 | * 74 | */ 75 | public function setConfig($key, $value) 76 | { 77 | $this->config[$key] = $value; 78 | } 79 | 80 | /** 81 | * @codeCoverageIgnore 82 | */ 83 | public function getName() 84 | { 85 | return 'twitter_anywhere'; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Tests/DependencyInjection/FOSTwitterExtensionTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\TwitterBundle\Tests\DependencyInjection; 13 | 14 | use FOS\TwitterBundle\DependencyInjection\FOSTwitterExtension; 15 | 16 | class TwitterExtensionTest extends \PHPUnit_Framework_TestCase 17 | { 18 | /** 19 | * @covers Bundle\FOS\TwitterBundle\DependencyInjection\FOSTwitterExtension::load 20 | */ 21 | public function testLoadFailed() 22 | { 23 | $this->setExpectedException('\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException'); 24 | 25 | $container = $this->getMock('Symfony\\Component\\DependencyInjection\\ContainerBuilder'); 26 | 27 | $extension = new FOSTwitterExtension(); 28 | $extension->load(array(), $container); 29 | } 30 | 31 | /** 32 | * @covers Bundle\FOS\TwitterBundle\DependencyInjection\FOSTwitterExtension::load 33 | */ 34 | public function testLoadSuccess() 35 | { 36 | $configs = array( 37 | array( 38 | 'file' => 'foo', 39 | 'callback_url' => 'foo', 40 | 'consumer_key' => 'foo', 41 | 'consumer_secret' => 'foo', 42 | ), 43 | ); 44 | 45 | $container = $this->getMock('Symfony\\Component\\DependencyInjection\\ContainerBuilder'); 46 | $parameterbag = $this->getMock('Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface'); 47 | $container 48 | ->expects($this->once()) 49 | ->method('getParameterBag') 50 | ->with() 51 | ->will($this->returnValue($parameterbag)); 52 | 53 | $alias = 'bar'; 54 | 55 | $container 56 | ->expects($this->once()) 57 | ->method('setAlias') 58 | ->with($alias, 'fos_twitter'); 59 | 60 | $configs[] = array('alias' => $alias); 61 | 62 | $extension = new FOSTwitterExtension(); 63 | $extension->load($configs, $container); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Tests/autoload.php.dist: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | $vendorDir = __DIR__.'/../vendor'; 13 | require_once $vendorDir.'/symfony/src/Symfony/Component/ClassLoader/UniversalClassLoader.php'; 14 | 15 | use Symfony\Component\ClassLoader\UniversalClassLoader; 16 | 17 | $loader = new UniversalClassLoader(); 18 | $loader->registerNamespaces(array( 19 | 'Symfony' => array($vendorDir.'/symfony/src'), 20 | )); 21 | $loader->registerPrefixes(array( 22 | 'Twig_' => $vendorDir.'/twig/lib', 23 | )); 24 | $loader->register(); 25 | 26 | spl_autoload_register(function($class) { 27 | if (0 === strpos($class, 'FOS\\TwitterBundle\\')) { 28 | $path = __DIR__.'/../'.implode('/', array_slice(explode('\\', $class), 2)).'.php'; 29 | if (!stream_resolve_include_path($path)) { 30 | return false; 31 | } 32 | require_once $path; 33 | return true; 34 | } 35 | }); 36 | -------------------------------------------------------------------------------- /Tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | if (file_exists($file = __DIR__.'/autoload.php')) { 13 | require_once $file; 14 | } elseif (file_exists($file = __DIR__.'/autoload.php.dist')) { 15 | require_once $file; 16 | } 17 | -------------------------------------------------------------------------------- /Twig/Extension/TwitterAnywhereExtension.php: -------------------------------------------------------------------------------- 1 | 4 | * Date: 05/03/11 5 | */ 6 | 7 | namespace FOS\TwitterBundle\Twig\Extension; 8 | 9 | use Symfony\Component\DependencyInjection\ContainerInterface; 10 | 11 | class TwitterAnywhereExtension extends \Twig_Extension 12 | { 13 | protected $container; 14 | 15 | /** 16 | * @param \Symfony\Component\DependencyInjection\ContainerInterface $container 17 | */ 18 | public function __construct(ContainerInterface $container) 19 | { 20 | $this->container = $container; 21 | } 22 | 23 | public function getFunctions() 24 | { 25 | return array( 26 | 'twitter_anywhere_setup' => new \Twig_Function_Method($this, 'renderSetup', array('is_safe' => array('html'))), 27 | 'twitter_anywhere_initialize' => new \Twig_Function_Method($this, 'renderInitialize', array('is_safe' => array('html'))), 28 | 'twitter_anywhere_queue' => new \Twig_Function_Method($this, 'queue', array('is_safe' => array('html'))), 29 | 'twitter_anywhere_setConfig' => new \Twig_Function_Method($this, 'setConfig', array('is_safe' => array('html'))), 30 | ); 31 | } 32 | 33 | public function renderSetup($parameters = array(), $name = null) 34 | { 35 | return $this->container->get('fos_twitter.anywhere.helper')->setup($parameters, $name ?: 'FOSTwitterBundle::setup.html.twig'); 36 | } 37 | 38 | public function renderInitialize($parameters = array(), $name = null) 39 | { 40 | return $this->container->get('fos_twitter.anywhere.helper')->initialize($parameters, $name ?: 'FOSTwitterBundle::initialize.html.twig'); 41 | } 42 | 43 | /* 44 | * 45 | */ 46 | public function queue($script) 47 | { 48 | return $this->container->get('fos_twitter.anywhere.helper')->queue($script); 49 | } 50 | 51 | /* 52 | * 53 | */ 54 | public function setConfig($key, $value) 55 | { 56 | return $this->container->get('fos_twitter.anywhere.helper')->setConfig($key, $value); 57 | } 58 | 59 | /** 60 | * @return string 61 | */ 62 | public function getName() 63 | { 64 | return 'twitter_anywhere'; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "friendsofsymfony/twitter-bundle", 3 | "type": "symfony-bundle", 4 | "description": "Symfony FOSTwitterBundle", 5 | "keywords": ["Twitter authentication"], 6 | "homepage": "http://friendsofsymfony.github.com", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "FriendsOfSymfony Community", 11 | "homepage": "https://github.com/FriendsOfSymfony/FOSTwitterBundle/contributors" 12 | } 13 | ], 14 | "require": { 15 | "php": ">=5.3.2", 16 | "symfony/framework-bundle": "2.*", 17 | "symfony/security-bundle": "~2.1", 18 | "kertz/twitteroauth": "*" 19 | }, 20 | "autoload": { 21 | "psr-0": { "FOS\\TwitterBundle": "" } 22 | }, 23 | "target-dir": "FOS/TwitterBundle" 24 | } 25 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ./Tests 8 | 9 | 10 | 11 | 12 | 13 | ./ 14 | 15 | ./Resources 16 | ./Tests 17 | ./vendor 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /vendor/vendors.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | set_time_limit(0); 13 | 14 | $vendorDir = __DIR__; 15 | $deps = array( 16 | array('symfony', 'http://github.com/symfony/symfony', isset($_SERVER['SYMFONY_VERSION']) ? $_SERVER['SYMFONY_VERSION'] : 'origin/master'), 17 | array('twitteroauth', 'git://github.com/kertz/twitteroauth.git', 'origin/master'), 18 | array('twig', 'http://github.com/fabpot/Twig', 'origin/master'), 19 | ); 20 | 21 | foreach ($deps as $dep) { 22 | list($name, $url, $rev) = $dep; 23 | 24 | echo "> Installing/Updating $name\n"; 25 | 26 | $installDir = $vendorDir.'/'.$name; 27 | if (!is_dir($installDir)) { 28 | system(sprintf('git clone -q %s %s', escapeshellarg($url), escapeshellarg($installDir))); 29 | } 30 | 31 | system(sprintf('cd %s && git fetch -q origin && git reset --hard %s', escapeshellarg($installDir), escapeshellarg($rev))); 32 | } 33 | --------------------------------------------------------------------------------