├── .gitignore
├── LICENSE
├── README.md
├── app
├── config
│ ├── dev.php
│ └── prod.php
├── db_dump.sql
└── views
│ ├── admin_artists.html.twig
│ ├── admin_comments.html.twig
│ ├── admin_layout.html.twig
│ ├── admin_users.html.twig
│ ├── artist.html.twig
│ ├── artists.html.twig
│ ├── comments.html.twig
│ ├── common
│ └── form_div_layout.html.twig
│ ├── form.html.twig
│ ├── index.html.twig
│ ├── layout.html.twig
│ ├── login.html.twig
│ ├── pagination.html.twig
│ └── profile.html.twig
├── composer.json
├── composer.lock
├── src
├── MusicBox
│ ├── Controller
│ │ ├── AdminArtistController.php
│ │ ├── AdminCommentController.php
│ │ ├── AdminController.php
│ │ ├── AdminUserController.php
│ │ ├── ApiArtistController.php
│ │ ├── ArtistController.php
│ │ ├── IndexController.php
│ │ └── UserController.php
│ ├── Entity
│ │ ├── Artist.php
│ │ ├── Comment.php
│ │ ├── Like.php
│ │ └── User.php
│ ├── Form
│ │ └── Type
│ │ │ ├── ArtistType.php
│ │ │ ├── CommentType.php
│ │ │ └── UserType.php
│ ├── Repository
│ │ ├── ArtistRepository.php
│ │ ├── CommentRepository.php
│ │ ├── LikeRepository.php
│ │ ├── RepositoryInterface.php
│ │ └── UserRepository.php
│ └── Service
│ │ └── SoundCloud.php
├── app.php
└── routes.php
└── web
├── .htaccess
├── css
├── bootstrap-responsive.css
├── bootstrap-responsive.min.css
├── bootstrap.css
├── bootstrap.min.css
├── docs.css
└── main.css
├── font
├── FontAwesome.otf
├── fontawesome-webfont.eot
├── fontawesome-webfont.svg
├── fontawesome-webfont.ttf
└── fontawesome-webfont.woff
├── ico
├── Thumbs.db
├── apple-touch-icon-114-precomposed.png
├── apple-touch-icon-144-precomposed.png
├── apple-touch-icon-57-precomposed.png
├── apple-touch-icon-72-precomposed.png
└── favicon.ico
├── img
├── artists
│ ├── 11.jpg
│ ├── 12.jpg
│ ├── 13.jpg
│ ├── 14.jpg
│ ├── 15.jpg
│ ├── 16.jpg
│ ├── 17.jpg
│ ├── 18.jpg
│ ├── 19.jpg
│ ├── 2.jpg
│ ├── 24.jpg
│ ├── 27.jpeg
│ └── placeholder.gif
├── heart hover.png
├── heart.png
└── users
│ └── placeholder.gif
├── index.php
├── js
├── .jshintrc
├── README.md
├── bootstrap-affix.js
├── bootstrap-alert.js
├── bootstrap-button.js
├── bootstrap-carousel.js
├── bootstrap-collapse.js
├── bootstrap-dropdown.js
├── bootstrap-modal.js
├── bootstrap-popover.js
├── bootstrap-scrollspy.js
├── bootstrap-tab.js
├── bootstrap-tooltip.js
├── bootstrap-transition.js
├── bootstrap-typeahead.js
├── bootstrap.js
├── bootstrap.min.js
├── google-code-prettify
│ ├── prettify.css
│ └── prettify.js
├── holder
│ └── holder.js
├── html5shiv.js
├── jquery.js
├── main.js
└── tests
│ ├── index.html
│ ├── phantom.js
│ ├── server.js
│ ├── unit
│ ├── bootstrap-affix.js
│ ├── bootstrap-alert.js
│ ├── bootstrap-button.js
│ ├── bootstrap-carousel.js
│ ├── bootstrap-collapse.js
│ ├── bootstrap-dropdown.js
│ ├── bootstrap-modal.js
│ ├── bootstrap-phantom.js
│ ├── bootstrap-popover.js
│ ├── bootstrap-scrollspy.js
│ ├── bootstrap-tab.js
│ ├── bootstrap-tooltip.js
│ ├── bootstrap-transition.js
│ └── bootstrap-typeahead.js
│ └── vendor
│ ├── jquery.js
│ ├── qunit.css
│ └── qunit.js
├── less
├── accordion.less
├── alerts.less
├── bootstrap.less
├── breadcrumbs.less
├── button-groups.less
├── buttons.less
├── carousel.less
├── close.less
├── code.less
├── component-animations.less
├── dropdowns.less
├── font-awesome
│ ├── bootstrap.less
│ ├── core.less
│ ├── extras.less
│ ├── font-awesome-ie7.less
│ ├── font-awesome.less
│ ├── icons.less
│ ├── mixins.less
│ ├── path.less
│ └── variables.less
├── forms.less
├── grid.less
├── hero-unit.less
├── labels-badges.less
├── layouts.less
├── media.less
├── mixins.less
├── modals.less
├── navbar.less
├── navs.less
├── pager.less
├── pagination.less
├── popovers.less
├── progress-bars.less
├── reset.less
├── responsive-1200px-min.less
├── responsive-767px-max.less
├── responsive-768px-979px.less
├── responsive-navbar.less
├── responsive-utilities.less
├── responsive.less
├── scaffolding.less
├── sprites.less
├── tables.less
├── tests
│ ├── buttons.html
│ ├── css-tests.css
│ ├── css-tests.html
│ ├── forms-responsive.html
│ ├── forms.html
│ ├── navbar-fixed-top.html
│ ├── navbar-static-top.html
│ └── navbar.html
├── thumbnails.less
├── tooltip.less
├── type.less
├── utilities.less
├── variables.less
└── wells.less
└── scss
├── _accordion.scss
├── _alerts.scss
├── _breadcrumbs.scss
├── _button-groups.scss
├── _buttons.scss
├── _carousel.scss
├── _close.scss
├── _code.scss
├── _component-animations.scss
├── _dropdowns.scss
├── _font-awesome.scss
├── _forms.scss
├── _grid.scss
├── _hero-unit.scss
├── _labels-badges.scss
├── _layouts.scss
├── _media.scss
├── _mixins.scss
├── _modals.scss
├── _navbar.scss
├── _navs.scss
├── _pager.scss
├── _pagination.scss
├── _popovers.scss
├── _progress-bars.scss
├── _reset.scss
├── _responsive-1200px-min.scss
├── _responsive-767px-max.scss
├── _responsive-768px-979px.scss
├── _responsive-navbar.scss
├── _responsive-utilities.scss
├── _scaffolding.scss
├── _tables.scss
├── _thumbnails.scss
├── _tooltip.scss
├── _type.scss
├── _utilities.scss
├── _variables.scss
├── _wells.scss
├── bootstrap-responsive.scss
├── bootstrap.scss
└── tests
├── bootstrap-responsive.css
└── bootstrap.css
/.gitignore:
--------------------------------------------------------------------------------
1 | # Bootstrap
2 | app/bootstrap*
3 |
4 | # Symfony directories
5 | vendor/*
6 | */logs/*
7 | */cache/*
8 | web/uploads/*
9 | web/bundles/*
10 |
11 | # Configuration files
12 | app/config/parameters.ini
13 | app/config/parameters.yml
14 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 Bojan Zivanovic
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Musicbox
2 | ========
3 | MusicBox is a portal based on the Silex framework, built for PHP 5.3 and MySQL 5.
4 | It tries to demonstrate best practices in today's world of development, and has
5 | been written as a university project by Bojan Zivanovic and Lana Petkovic.
6 |
7 | Uses Doctrine DBAL for accessing the database, and Twig for its templates.
8 | Relies on SwiftMailer to send emails.
9 | The UI is based on Bootstrap 2.
10 |
11 | Getting started
12 | ---------------
13 | 1. Move the files
14 | Extract the contents of the "web" folder into your public html directory.
15 | Copy all other folders one level above. Your structure should look like this:
16 |
17 | - app
18 | - src
19 | - vendor
20 | - public_html (Your public html directory, and inside the contents of the "web" folder)
21 |
22 | Make sure that the img/artists and img/users directories in your public_html directory
23 | are writable.
24 |
25 | 2. Create a new empty database, and import the sql dump provided in app/db_dump.sql
26 | Open app/config/prod.php and under $app['db.options'] set your database credentials
27 |
28 | 3. MusicBox should now be functional. An admin user with the admin/admin username/password has been created for you.
29 |
30 | Application structure
31 | ---------------------
32 |
33 | - app
34 | -- cache - Used by Twig to save compiled templates
35 | -- config - Contains the dev.php and prod.php files with configuration data (db credentials, etc).
36 | -- views - Contains the Twig templates called by the controllers, including the main layout file.
37 | - src - Contains the main application code
38 | -- app.php - Called by index.php, initializes the app by registering libraries into the dependency injection container.
39 | -- routes.php - Called by index.php, routes map urls to controller classes.
40 | Each route has a name (such as "admin_artist_edit"), used to generate urls from the views and controllers.
41 | -- MusicBox - this folder contains the root of the namespace. All classes are nested below.
42 | --- Controller - Contains the controller classes.
43 | --- Entity - Contains the entities, POPO (plan old PHP objects) that represent the data that is manipulated by the repositories.
44 | An entity class has properties that mostly correspond to database columns, as well as related getters and setters.
45 | --- Form - Contains the Form classes used by the Symfony Form library to render each form.
46 | --- Repository - Contains classes that manipulate entity data by doing queries against the database. This includes all CRUD operations.
47 | - vendor - Contains the dependencies managed by composer.
48 | - web - Contains static files (CSS, JS, etc) as well as the main entrypoint (index.php)
49 |
50 | Application flow
51 | ----------------
52 | index.php is called for all requests (directed by htaccess file).
53 | index.php includes the config file, and then app.php and routes.php.
54 | At this point, $app knows about all parts of the application, and the routes.
55 | index.php then calls $app->run(), which instantiates the correct controller for the current url.
56 | The controller manipulates data (creating, reading, updating, deleting Entities from their Repository), and passes it to a Twig template.
57 | Twig has template inheritance, so the template file inherits the main layout file in order to provide all of the page elements.
58 |
59 | The API
60 | -------
61 | The application provides a REST API for managing artists.
62 | - GET api/artists - Provides a listing of artists. Possible parameters: limit (default: 20), offset.
63 | - GET api/artist - Retrieves a single artist.
64 | - POST api/artist - Creates a new artist.
65 | - PUT api/artist/{artist} - Updates a single artist.
66 | - DELETE api/artist/{artist} - Deletes a single artist.
67 |
68 | The output format is JSON.
69 |
70 | Emails
71 | ------
72 | The application notifies the admin by email of every new posted comment.
73 | The sending is done in the ArtistController.
74 | The recepient email address is configured in the dev.php config file.
75 |
76 | Blog post: http://bojanz.wordpress.com/2013/11/11/learning-php-development-with-silex
77 |
--------------------------------------------------------------------------------
/app/config/dev.php:
--------------------------------------------------------------------------------
1 | 'pdo_mysql',
19 | 'host' => '127.0.0.1',
20 | 'port' => '3306',
21 | 'dbname' => 'musicbox',
22 | 'user' => '',
23 | 'password' => '',
24 | );
25 | // SwiftMailer
26 | // See http://silex.sensiolabs.org/doc/providers/swiftmailer.html
27 | $app['swiftmailer.options'] = array(
28 | 'host' => 'host',
29 | 'port' => '25',
30 | 'username' => 'username',
31 | 'password' => 'password',
32 | 'encryption' => null,
33 | 'auth_mode' => null
34 | );
35 |
--------------------------------------------------------------------------------
/app/views/admin_artists.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin_layout.html.twig' %}
2 | {% set active = 'admin' %}
3 | {% set adminActive = 'artists' %}
4 |
5 | {% block content %}
6 |