├── .gitignore ├── Command ├── ClearCommand.php └── CompilerCommand.php ├── DependencyInjection ├── Configuration.php └── RuianTwitterBootstrapExtension.php ├── Exception └── TwitterBootstrapVersionException.php ├── Features ├── Command.feature └── Context │ └── FeatureContext.php ├── README.md ├── Resources ├── config │ ├── routing.yml │ └── services.yml ├── public │ ├── css │ │ └── .keep │ ├── img │ │ └── .keep │ └── js │ │ └── .keep └── views │ ├── Alert │ ├── bootstrap_v1.html.twig │ └── bootstrap_v2.html.twig │ └── Form │ ├── bootstrap_v1.html.twig │ └── bootstrap_v2.html.twig ├── RuianTwitterBootstrapBundle.php └── composer.json /.gitignore: -------------------------------------------------------------------------------- 1 | Resources/public/js 2 | Resources/public/css 3 | Resources/public/img 4 | -------------------------------------------------------------------------------- /Command/ClearCommand.php: -------------------------------------------------------------------------------- 1 | versions = array( 20 | 'v1', 21 | 'v2' 22 | ); 23 | } 24 | 25 | protected function configure() 26 | { 27 | $this 28 | ->setName('twitter-bootstrap:clear') 29 | ->setDescription('Delete any css and js in RuianTwitterBootstrapBundle Resources') 30 | ; 31 | } 32 | 33 | protected function execute(InputInterface $input, OutputInterface $output) 34 | { 35 | $finder = new Finder(); 36 | $finder->files()->in(__DIR__ . '/../Resources/public/')->name('/(js$)|(css$)/')->sortByName(); 37 | 38 | foreach ($finder->files() as $file) { 39 | unlink($file->getRealPath()); 40 | $output->writeln('Delete '. $file->getFilename() .''); 41 | } 42 | $output->writeln('Success every files had been removed'); 43 | } 44 | } -------------------------------------------------------------------------------- /Command/CompilerCommand.php: -------------------------------------------------------------------------------- 1 | versions = array( 21 | 'v1', 22 | 'v2' 23 | ); 24 | } 25 | 26 | protected function configure() 27 | { 28 | $this 29 | ->setName('twitter-bootstrap:compile') 30 | ->setDescription('Compile a version of twitter-bootstrap and paste it into RuianTwitterBundle public folder') 31 | ->addArgument('version', InputArgument::OPTIONAL, 'Main version v1 or v2', 'v1') 32 | ; 33 | } 34 | 35 | protected function execute(InputInterface $input, OutputInterface $output) 36 | { 37 | $version = $input->getArgument('version'); 38 | 39 | if (false === in_array($version, $this->versions)) { 40 | throw new TwitterBootstrapVersionException("Version you have selected is not supported, or inexistant. Please choose one of these versions " . implode(' or ', $this->versions)); 41 | } 42 | 43 | if (true === $this->writeCss($version, $output)) { 44 | $output->writeln('Success, bootstrap'.$version.'.css has been written in /Ruian/TwitterBootstrapBundle/Resources/public/css/bootstrap'.$version.'.css'); 45 | } 46 | 47 | if (true === $this->writeJs($version, $output)) { 48 | $output->writeln('Success, bootstrap'.$version.'.js has been written in /Ruian/TwitterBootstrapBundle/Resources/public/js/bootstrap'.$version.'.js'); 49 | } 50 | 51 | if (true === $this->copyImages($version, $output)) { 52 | $output->writeln('Success, bootstrap'.$version.' images have been copied to /Ruian/TwitterBootstrapBundle/Resources/public/img'); 53 | } 54 | } 55 | 56 | protected function writeCss($version, $output) 57 | { 58 | if (!is_dir(__DIR__ . '/../Resources/public/css/')) { 59 | mkdir(__DIR__ . '/../Resources/public/css/', 0777, true); 60 | } 61 | 62 | if ('v1' === $version) { 63 | $in = __DIR__ . '/../../../../twitter/bootstrap/'.$version.'/lib/bootstrap.less'; 64 | $out = __DIR__ . '/../Resources/public/css/bootstrap' . $version . '.css'; 65 | 66 | lessc::ccompile($in, $out); 67 | 68 | $output->writeln('Writing bootstrap'.$version.'.css from bootstrap.less'); 69 | $output->writeln('You can add bundles/ruiantwitterbootstrap/css/bootstrap'.$version.'.css to your layout'); 70 | } 71 | 72 | if ('v2' === $version) { 73 | $in = __DIR__ . '/../../../../twitter/bootstrap/'.$version.'/less/bootstrap.less'; 74 | $out = __DIR__ . '/../Resources/public/css/bootstrap' . $version . '.css'; 75 | 76 | lessc::ccompile($in, $out); 77 | 78 | $output->writeln('Writing bootstrap'.$version.'.css from bootstrap.less'); 79 | $output->writeln('You can add bundles/ruiantwitterbootstrap/css/bootstrap'.$version.'.css to your layout'); 80 | 81 | $in = __DIR__ . '/../../../../twitter/bootstrap/'.$version.'/less/responsive.less'; 82 | $out = __DIR__ . '/../Resources/public/css/bootstrap' . $version . '-responsive.css'; 83 | 84 | lessc::ccompile($in, $out); 85 | 86 | $output->writeln('Writing bootstrap'.$version.'-responsive.css from responsive.less'); 87 | $output->writeln('You can add bundles/ruiantwitterbootstrap/css/bootstrap'.$version.'-responsive.css to your layout'); 88 | } 89 | 90 | return true; 91 | } 92 | 93 | protected function copyImages($version, $output) { 94 | //no images to copy for 1.x bootstrap 95 | 96 | if ('v2' === $version) { 97 | if (!is_dir(__DIR__ . '/../Resources/public/img/')) { 98 | mkdir(__DIR__ . '/../Resources/public/img/', 0777, true); 99 | } 100 | 101 | foreach (glob(__DIR__ . '/../../../../twitter/bootstrap/'.$version.'/img/*') as $image) { 102 | copy($image, __DIR__ . '/../Resources/public/img/' . basename($image)); 103 | } 104 | } 105 | 106 | return true; 107 | } 108 | 109 | protected function writeJs($version, $output) 110 | { 111 | $jsDir = __DIR__ . '/../../../../twitter/bootstrap/'.$version.'/js/'; 112 | 113 | if (!is_dir(__DIR__ . '/../Resources/public/js/')) { 114 | mkdir(__DIR__ . '/../Resources/public/js/', 0777, true); 115 | } 116 | 117 | //here we use finder only to add some new files if bootstrap adds them 118 | //default bootstrap files, order is important 119 | $files = array('bootstrap-transition.js', 120 | 'bootstrap-alert.js', 121 | 'bootstrap-button.js', 122 | 'bootstrap-carousel.js', 123 | 'bootstrap-collapse.js', 124 | 'bootstrap-dropdown.js', 125 | 'bootstrap-modal.js', 126 | 'bootstrap-tooltip.js', 127 | 'bootstrap-popover.js', 128 | 'bootstrap-scrollspy.js', 129 | 'bootstrap-tab.js', 130 | 'bootstrap-typeahead.js'); 131 | 132 | $finder = new Finder(); 133 | $finder->depth('== 0'); 134 | $finder->files()->in($jsDir)->name('*.js'); 135 | 136 | foreach ($finder as $file) { 137 | $baseFile = basename($file); 138 | if (!in_array($baseFile, $files)) { 139 | $output->writeln(sprintf('Found NEW file "%s", bootstrap has new javascripts?', $baseFile)); 140 | $files[] = $baseFile; 141 | } 142 | } 143 | 144 | $bootstrapjs = null; 145 | 146 | foreach ($files as $file) { 147 | $bootstrapjs .= file_get_contents(realpath($jsDir . $file)); 148 | $output->writeln('Adding '.$file.''); 149 | } 150 | 151 | file_put_contents(__DIR__ . '/../Resources/public/js/bootstrap'.$version.'.js', $bootstrapjs); 152 | 153 | $output->writeln('Writing bootstrap'.$version.'.js'); 154 | $output->writeln('You can add bundles/ruiantwitterbootstrap/js/bootstrap'.$version.'.js to your layout'); 155 | 156 | return true; 157 | } 158 | } -------------------------------------------------------------------------------- /DependencyInjection/Configuration.php: -------------------------------------------------------------------------------- 1 | root('ruian_twitter_bootstrap'); 22 | 23 | // Here you should define the parameters that are allowed to 24 | // configure your bundle. See the documentation linked above for 25 | // more information on that topic. 26 | 27 | return $treeBuilder; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /DependencyInjection/RuianTwitterBootstrapExtension.php: -------------------------------------------------------------------------------- 1 | processConfiguration($configuration, $configs); 24 | 25 | $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); 26 | $loader->load('services.yml'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Exception/TwitterBootstrapVersionException.php: -------------------------------------------------------------------------------- 1 | application = new Application($kernel); 39 | $this->application->add(new CompilerCommand()); 40 | $this->application->add(new ClearCommand()); 41 | // add other commands if needed 42 | } 43 | 44 | /** 45 | * @When /^I run "([^"]*)" command$/ 46 | */ 47 | public function iRunCommand($cmd_line) 48 | { 49 | $input = new StringInput($cmd_line); 50 | $command = $this->application->find($input->getFirstArgument('command')); 51 | $input = new StringInput($cmd_line, $command->getDefinition()); 52 | $this->output = new StreamOutput(fopen('php://memory', 'w', false)); 53 | $command->run($input, $this->output); 54 | } 55 | 56 | /** 57 | * @Then /^I should see$/ 58 | */ 59 | public function iShouldSee(PyStringNode $string) 60 | { 61 | rewind($this->output->getStream()); 62 | $display = stream_get_contents($this->output->getStream()); 63 | assertSame($string->getRaw(), $display); 64 | } 65 | 66 | /** 67 | * @Then /^I should get a file "([^"]*)"$/ 68 | */ 69 | public function iShouldGetAFile($filename) 70 | { 71 | $assert = false; 72 | $finder = new Finder(); 73 | $finder->files()->in(__DIR__ . '/../../Resources/public/')->name('/(css$)|(js$)/'); 74 | 75 | foreach ($finder->files() as $file) { 76 | if ($filename === $file->getFilename()) { 77 | $assert = true; 78 | } 79 | } 80 | 81 | assertTrue($assert); 82 | } 83 | 84 | /** 85 | * @Then /^I should get no file$/ 86 | */ 87 | public function iShouldGetNoFile() 88 | { 89 | $finder = new Finder(); 90 | $finder->files()->in(__DIR__ . '/../../Resources/public/')->name('/(css$)|(js$)/'); 91 | 92 | $assert = true; 93 | foreach ($finder->files() as $key => $value) { 94 | $assert = false; 95 | break; 96 | } 97 | 98 | assertTrue($assert); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TwitterBootstrapBundle 2 | ====================== 3 | 4 | #WARNING 5 | If you use a symfony 2.0.x version please use the correct branch of this bundle (2.0.x in that case) 6 | 7 | #How to install ? 8 | 9 | ##Add theses lines into your deps 10 | 11 | ``` 12 | [RuianTwitterBootstrapBundle] 13 | git=git://github.com/ruian/TwitterBootstrapBundle.git 14 | version=origin/master 15 | target=/bundles/Ruian/TwitterBootstrapBundle 16 | 17 | [TwitterBootstrap1] 18 | git=git://github.com/twitter/bootstrap.git 19 | target=/twitter/bootstrap/v1/ 20 | version=v1.4.0 21 | 22 | [TwitterBootstrap2] 23 | git=git://github.com/twitter/bootstrap.git 24 | target=/twitter/bootstrap/v2/ 25 | version=v2.0.0 26 | 27 | [lessphp] 28 | git=git://github.com/leafo/lessphp.git 29 | target=/lessphp/ 30 | version=origin/master 31 | ``` 32 | 33 | ##Add autoloading 34 | 35 | ```php 36 | #app/autoload.php 37 | registerNamespaces(array( 39 | #... 40 | 'Ruian' => __DIR__.'/../vendor/bundles', 41 | )); 42 | 43 | #some code... 44 | 45 | // Add support for lessc 46 | require __DIR__.'/../vendor/lessphp/lessc.inc.php'; 47 | 48 | ``` 49 | 50 | ##Register this bundle 51 | 52 | ```php 53 | #app/AppKernel.php 54 | 85 | 86 | 87 | Twitter Bootstrap 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | ``` 97 | 98 | ##Use bootstrap form style 99 | Replace VERSION by the supported version you want, v1 or v2 100 | 101 | ``` 102 | {% form_theme form_view 'RuianTwitterBootstrapBundle:Form:bootstrap_VERSION.html.twig' %} 103 | ``` 104 | 105 | 106 | ##Example 107 | 108 | ```html 109 | #Ruian/DemoBundle/Resources/view/new.html.twig 110 | 111 | 112 | 113 | New article 114 | 115 | 116 | 117 | 118 |
119 |
120 |
121 | 122 | {% include 'RuianTwitterBootstrapBundle:Alert:bootstrap_v2.html.twig' %} 123 | 124 | {% form_theme form_view 'RuianTwitterBootstrapBundle:Form:bootstrap_v2.html.twig' %} 125 |
126 | {{ form_widget(form_view) }} 127 |
128 | 129 |
130 |
131 |
132 |
133 |
134 | 135 | 136 | 137 | 138 | ``` 139 | 140 | ```php 141 | #Ruian/DemoBundle/Controller/ArticleController.php 142 | createForm(new ArticleType(), $entity); 156 | 157 | $request = $this->get('request'); 158 | if ('POST' === $request->getMethod()) { 159 | $form->bindRequest($request); 160 | if (true === $form->isValid()) { 161 | $em = $this->get('doctrine.orm.default_entity_manager'); 162 | $em->persist($entity); 163 | $em->flush(); 164 | 165 | $this->setFlashSuccess('Congratulation, your article has been saved.'); 166 | return $this->redirect($this->generateUrl('RuianDemoBundle_new')); 167 | } else { 168 | $this->setFlashError('Warning, your article can\'t be saved due to some errors.'); 169 | } 170 | } 171 | 172 | return $this->render('RuianDemoBundle:Article:new.html.twig', array( 173 | 'form_view' => $form->createView(), 174 | )); 175 | } 176 | 177 | protected function setFlashSuccess($message) 178 | { 179 | $this->get('session')->setFlash('alert-success', $message); 180 | } 181 | 182 | protected function setFlashError($message) 183 | { 184 | $this->get('session')->setFlash('alert-error', $message); 185 | } 186 | 187 | # some code ... 188 | } 189 | 190 | ``` -------------------------------------------------------------------------------- /Resources/config/routing.yml: -------------------------------------------------------------------------------- 1 | RuianTwitterBootstrapBundle_homepage: 2 | pattern: /hello/{name} 3 | defaults: { _controller: RuianTwitterBootstrapBundle:Default:index } 4 | -------------------------------------------------------------------------------- /Resources/config/services.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | # ruian_twitter_bootstrap.example.class: Ruian\TwitterBootstrapBundle\Example 3 | 4 | services: 5 | # ruian_twitter_bootstrap.example: 6 | # class: %ruian_twitter_bootstrap.example.class% 7 | # arguments: [@service_id, "plain_value", %parameter%] 8 | -------------------------------------------------------------------------------- /Resources/public/css/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruian/TwitterBootstrapBundle/1594b84da7450f5740eb225bf3bde0e6792a0800/Resources/public/css/.keep -------------------------------------------------------------------------------- /Resources/public/img/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruian/TwitterBootstrapBundle/1594b84da7450f5740eb225bf3bde0e6792a0800/Resources/public/img/.keep -------------------------------------------------------------------------------- /Resources/public/js/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruian/TwitterBootstrapBundle/1594b84da7450f5740eb225bf3bde0e6792a0800/Resources/public/js/.keep -------------------------------------------------------------------------------- /Resources/views/Alert/bootstrap_v1.html.twig: -------------------------------------------------------------------------------- 1 | {% if app.session.hasFlash('alert-success') %} 2 | {% set message = app.session.getFlash('alert-success') %} 3 | {% set type = 'success' %} 4 | {% endif %} 5 | 6 | {% if app.session.hasFlash('alert-error') %} 7 | {% set message = app.session.getFlash('alert-error') %} 8 | {% set type = 'error' %} 9 | {% endif %} 10 | 11 | {% if app.session.hasFlash('alert-warning') %} 12 | {% set message = app.session.getFlash('alert-warning') %} 13 | {% set type = 'warning' %} 14 | {% endif %} 15 | 16 | {% if app.session.hasFlash('alert-info') %} 17 | {% set message = app.session.getFlash('alert-info') %} 18 | {% set type = 'info' %} 19 | {% endif %} 20 | 21 | {% if type is defined %} 22 | {# --> Start bootstrap_alert block #} 23 | {% block bootstrap_alert %} 24 |
25 | × 26 | {{ message }} 27 |
28 | {% endblock bootstrap_alert %} 29 | {# <-- End bootstrap_alert block #} 30 | {% endif %} -------------------------------------------------------------------------------- /Resources/views/Alert/bootstrap_v2.html.twig: -------------------------------------------------------------------------------- 1 | {% if app.session.hasFlash('alert-success') %} 2 | {% set title = 'Success' %} 3 | {% set message = app.session.getFlash('alert-success') %} 4 | {% set type = 'success' %} 5 | {% endif %} 6 | 7 | {% if app.session.hasFlash('alert-error') %} 8 | {% set title = 'Error' %} 9 | {% set message = app.session.getFlash('alert-error') %} 10 | {% set type = 'error' %} 11 | {% endif %} 12 | 13 | {% if app.session.hasFlash('alert-warning') %} 14 | {% set title = 'Warning' %} 15 | {% set message = app.session.getFlash('alert-warning') %} 16 | {% set type = 'warning' %} 17 | {% endif %} 18 | 19 | {% if app.session.hasFlash('alert-info') %} 20 | {% set title = 'Info' %} 21 | {% set message = app.session.getFlash('alert-info') %} 22 | {% set type = 'info' %} 23 | {% endif %} 24 | 25 | {% if type is defined %} 26 | {# --> Start bootstrap_alert block #} 27 | {% block bootstrap_alert %} 28 |
29 | × 30 |

{{ title }}

31 | {{ message }} 32 |
33 | {% endblock bootstrap_alert %} 34 | {# <-- End bootstrap_alert block #} 35 | {% endif %} -------------------------------------------------------------------------------- /Resources/views/Form/bootstrap_v1.html.twig: -------------------------------------------------------------------------------- 1 | {% block field_row %} 2 | {% spaceless %} 3 |
4 | {{ form_label(form, label|default(null)) }} 5 |
6 | {{ form_widget(form) }} 7 |
8 |
9 | {{ form_errors(form)}} 10 | {% endspaceless %} 11 | {% endblock field_row %} 12 | 13 | {% block field_errors %} 14 | {% spaceless %} 15 | {% if errors|length > 0 %} 16 | 17 | {% for error in errors %} 18 |
19 | × 20 | {{ error.messageTemplate|trans(error.messageParameters, 'validators') }} 21 |
22 | {% endfor %} 23 | 24 | {% endif %} 25 | {% endspaceless %} 26 | {% endblock field_errors %} 27 | 28 | {% block generic_label %} 29 | {% set attr = attr|merge({'class': ''}) %} 30 | {% spaceless %} 31 | {% if required %} 32 | {% set attr = attr|merge({'class': 'required'}) %} 33 | {% endif %} 34 | {{ label|trans({}, translation_domain) }} 35 | {% endspaceless %} 36 | {% endblock %} -------------------------------------------------------------------------------- /Resources/views/Form/bootstrap_v2.html.twig: -------------------------------------------------------------------------------- 1 | {% block field_row %} 2 | {% spaceless %} 3 |
4 | {{ form_label(form, label|default(null)) }} 5 |
6 | {{ form_widget(form) }} 7 | {{ form_errors(form)}} 8 |
9 |
10 | {% endspaceless %} 11 | {% endblock field_row %} 12 | 13 | {% block field_errors %} 14 | {% spaceless %} 15 | {% if errors|length > 0 %} 16 | 17 | {% for error in errors %} 18 |
19 | {{ error.messageTemplate|trans(error.messageParameters, 'validators') }} 20 |
21 | {% endfor %} 22 | 23 | {% endif %} 24 | {% endspaceless %} 25 | {% endblock field_errors %} 26 | 27 | {% block generic_label %} 28 | {% set attr = attr|merge({'class': ''}) %} 29 | {% spaceless %} 30 | {% if required %} 31 | {% set attr = attr|merge({'class': 'required'}) %} 32 | {% endif %} 33 | {{ label|trans({}, translation_domain) }} 34 | {% endspaceless %} 35 | {% endblock %} -------------------------------------------------------------------------------- /RuianTwitterBootstrapBundle.php: -------------------------------------------------------------------------------- 1 | =5.3.2", 11 | "symfony/framework-bundle": "2.*", 12 | "twitter/bootstrap": "origin/master", 13 | "twitter/bootstrap": "2.0-wip", 14 | "leafo/lessphp" : "origin/master" 15 | }, 16 | "target-dir": "bundles/Ruian/TwitterBootstrapBundle" 17 | } --------------------------------------------------------------------------------