├── .gitignore ├── .travis.yml ├── README.md ├── bat.api.php ├── bat.info ├── bat.install ├── bat.make ├── bat.module ├── composer.json ├── css └── bat_date_range_fields.css ├── js └── bat_date_popup.js ├── modules ├── bat_booking │ ├── bat_booking.admin.inc │ ├── bat_booking.info │ ├── bat_booking.install │ ├── bat_booking.module │ ├── bat_booking.tokens.inc │ ├── bat_booking_example │ │ ├── bat_booking_example.info │ │ ├── bat_booking_example.install │ │ ├── bat_booking_example.module │ │ ├── booking_confirmation_page.tpl.php │ │ └── views │ │ │ ├── bat_booking_example.views.inc │ │ │ └── bat_booking_example_book_this_field.inc │ ├── bat_booking_type.admin.inc │ └── views │ │ ├── bat_booking.views.inc │ │ ├── bat_booking_handler_delete_link_field.inc │ │ ├── bat_booking_handler_edit_link_field.inc │ │ └── bat_booking_handler_night_field.inc ├── bat_calendar_reference │ ├── bat_calendar_reference.info │ ├── bat_calendar_reference.install │ ├── bat_calendar_reference.module │ └── js │ │ └── bat_calendar_reference.js ├── bat_event │ ├── bat_event.admin.inc │ ├── bat_event.api.php │ ├── bat_event.info │ ├── bat_event.install │ ├── bat_event.module │ ├── bat_event.rules.inc │ ├── bat_event.tpl.php │ ├── bat_event_type.admin.inc │ ├── js │ │ ├── bat_color.js │ │ └── bat_event.js │ └── views │ │ ├── bat_event.views.inc │ │ ├── bat_event.views_default.inc │ │ ├── bat_event_handler_blocking_filter.inc │ │ ├── bat_event_handler_date_field.inc │ │ ├── bat_event_handler_date_filter.inc │ │ ├── bat_event_handler_delete_link_field.inc │ │ ├── bat_event_handler_duration_field.inc │ │ ├── bat_event_handler_edit_link_field.inc │ │ ├── bat_event_handler_event_operations_field.inc │ │ ├── bat_event_handler_event_state_filter.inc │ │ ├── bat_event_handler_event_type_field.inc │ │ ├── bat_event_handler_link_field.inc │ │ └── bat_event_handler_value_field.inc ├── bat_event_ui │ ├── bat_event_ui.info │ ├── bat_event_ui.install │ ├── bat_event_ui.module │ └── css │ │ └── bat_event_ui.css ├── bat_facets │ ├── README.md │ ├── bat_facets.facetapi.inc │ ├── bat_facets.info │ ├── bat_facets.install │ ├── bat_facets.module │ └── src │ │ ├── BatStateSearchAPIQuery.php │ │ └── BatStateWidget.php ├── bat_fullcalendar │ ├── bat_fullcalendar.api.php │ ├── bat_fullcalendar.info │ ├── bat_fullcalendar.install │ ├── bat_fullcalendar.module │ ├── css │ │ ├── bat_fullcalendar_timeline.css │ │ ├── bat_modal.css │ │ └── fullcalendar.theme.css │ ├── images │ │ ├── bg-shade-light.png │ │ └── close.png │ ├── js │ │ └── bat_fullcalendar_timeline.js │ └── src │ │ ├── FullCalendarFixedStateEventFormatter.php │ │ └── FullCalendarOpenStateEventFormatter.php ├── bat_options │ ├── bat_options.api.php │ ├── bat_options.info │ ├── bat_options.install │ ├── bat_options.module │ └── css │ │ └── bat_options_widget.css └── bat_unit │ ├── bat_type.admin.inc │ ├── bat_type.diff.inc │ ├── bat_type.tpl.php │ ├── bat_type_bundle.admin.inc │ ├── bat_unit.admin.inc │ ├── bat_unit.info │ ├── bat_unit.install │ ├── bat_unit.module │ ├── bat_unit.rules.inc │ ├── bat_unit.tokens.inc │ ├── bat_unit.tpl.php │ ├── bat_unit_bundle.admin.inc │ ├── css │ └── bat_unit.css │ └── views │ ├── bat_type_handler_delete_link_field.inc │ ├── bat_type_handler_edit_link_field.inc │ ├── bat_type_handler_link_field.inc │ ├── bat_type_handler_type_calendars_field.inc │ ├── bat_type_handler_type_operations_field.inc │ ├── bat_type_handler_type_revision_operations_field.inc │ ├── bat_type_handler_type_revision_status_field.inc │ ├── bat_unit.views.inc │ ├── bat_unit.views_default.inc │ ├── bat_unit_handler_delete_link_field.inc │ ├── bat_unit_handler_edit_link_field.inc │ ├── bat_unit_handler_field_megarow_links.inc │ ├── bat_unit_handler_link_field.inc │ ├── bat_unit_handler_type_id_field.inc │ ├── bat_unit_handler_type_id_filter.inc │ └── bat_unit_handler_unit_type_field.inc └── test ├── behat ├── behat.yml ├── composer.json └── features │ ├── bootstrap │ └── FeatureContext.php │ ├── event.feature │ ├── installation.feature │ └── type.feature ├── project.make └── upload.sh /.gitignore: -------------------------------------------------------------------------------- 1 | test/behat/behat.local.yml 2 | test/behat/composer.lock 3 | test/behat/bin 4 | test/behat/vendor 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | sudo: required 4 | dist: xenial 5 | 6 | services: 7 | - mysql 8 | - xvfb 9 | 10 | php: 11 | - 5.6 12 | - 7.1 13 | - 7.2 14 | - 7.3 15 | 16 | mysql: 17 | database: drupal 18 | username: root 19 | encoding: utf8 20 | 21 | before_install: 22 | - export CHROME_BIN=chromium-browser 23 | - export DISPLAY=:99.0 24 | - wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb 25 | - sudo dpkg -i google-chrome*.deb 26 | - wget http://chromedriver.storage.googleapis.com/2.42/chromedriver_linux64.zip && unzip chromedriver_linux64.zip && sudo mv chromedriver /usr/bin 27 | 28 | install: 29 | # Set unlimited memory_limit. 30 | - if [ "${TRAVIS_PHP_VERSION}" != 'hhvm' ]; then INI_FILE=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; else INI_FILE=/etc/hhvm/php.ini; fi; 31 | - echo "memory_limit = -1" >> "${INI_FILE}" 32 | 33 | # Remove xdebug for the moment. We aren't generating code coverage, and it slows us down. 34 | - if [ "${TRAVIS_PHP_VERSION}" != '7.0' ]; then mv ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini /tmp/xdebug.ini; fi; 35 | 36 | before_script: 37 | # Create drupal database. 38 | - mysql -u root -e "CREATE DATABASE drupal;" 39 | # Set up DB user. 40 | - mysql -uroot -e "CREATE USER drupal@localhost IDENTIFIED BY 'drupal';" 41 | - mysql -uroot -e "GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES ON drupal.* TO 'drupal'@'localhost' IDENTIFIED BY 'drupal';" 42 | 43 | # Set github access token for composer if available. 44 | - if [[ $GITHUB_OAUTH_TOKEN ]]; then git config --global github.accesstoken $GITHUB_OAUTH_TOKEN; fi 45 | # Copy module to tmp dir for later use. 46 | - mkdir /tmp/bat; cp -r * /tmp/bat 47 | # Update composer. 48 | - composer -n self-update 49 | 50 | # Install drush. 51 | - export PATH="$HOME/.composer/vendor/bin:$PATH" 52 | - composer -n global require drush/drush:8.* 53 | # Install drush composer extension. 54 | - drush dl composer-8.x-1.x 55 | # Install code sniffer. 56 | - composer -n global require drupal/coder 57 | # Register Drupal coding standards. 58 | - phpcs --config-set installed_paths ~/.composer/vendor/drupal/coder/coder_sniffer 59 | # Don't display warnings. 60 | - phpcs --config-set show_warnings 0 61 | 62 | # Install required packages for behat. 63 | - cd ./test/behat 64 | - composer -n install 65 | 66 | # Make the site. 67 | - cd $TRAVIS_BUILD_DIR 68 | - drush make test/project.make bat 69 | 70 | # Copy the bat module into the Drupal site. 71 | - mv /tmp/bat bat/sites/all/modules/bat 72 | 73 | - cd bat 74 | - php -d sendmail_path=$(which true) ~/.composer/vendor/bin/drush.php --yes site-install --db-url=mysql://drupal:drupal@127.0.0.1/drupal --account-name=admin --account-pass=test --site-mail=webmaster@roomify.us --site-name="bat" 75 | # Following step with -y should also run composer install. 76 | - drush -y en bat bat_api bat_calendar_reference bat_event bat_event_ui bat_facets bat_fullcalendar bat_unit composer_manager 77 | - drush cc all --yes 78 | 79 | # Run a webserver and wait until it is started up. 80 | - drush --debug runserver "http://127.0.0.1" > ~/debug.txt 2>&1 & 81 | - sleep 10 82 | 83 | # Link test dir into working dir. 84 | - ln -s $TRAVIS_BUILD_DIR/test . 85 | 86 | - mkdir -p $HOME/.cache 87 | - wget -nc -O $HOME/.cache/selenium-server-standalone-3.14.0.jar http://selenium-release.storage.googleapis.com/3.14/selenium-server-standalone-3.14.0.jar || true 88 | - java -jar $HOME/.cache/selenium-server-standalone-3.14.0.jar -port 4444 &> /tmp/selenium.log & 89 | - sleep 5 90 | 91 | script: 92 | - cd $TRAVIS_BUILD_DIR/bat/sites/all/modules/bat 93 | # Check coding standards. 94 | - phpcs --standard=Drupal --exclude=Drupal.Array.Array,Drupal.Commenting.FunctionComment,Drupal.Commenting.DocComment,Drupal.Commenting.FileComment,Drupal.NamingConventions.ValidClassName,Drupal.NamingConventions.ValidFunctionName,Drupal.NamingConventions.ValidVariableName,Drupal.InfoFiles.AutoAddedKeys,Drupal.InfoFiles.ClassFiles --report-width=74 --extensions=php,module,inc,install,test,profile,theme,info,txt,md,yml --ignore=test $TRAVIS_BUILD_DIR/bat/sites/all/modules/bat 95 | 96 | - cd $TRAVIS_BUILD_DIR/bat/test/behat 97 | # behat.yml includes behat.local.yml so it must exist 98 | - touch behat.local.yml 99 | # Set path to drupal root 100 | - export BEHAT_PARAMS="{\"extensions\":{\"Drupal\\\DrupalExtension\":{\"drupal\":{\"drupal_root\":\"$TRAVIS_BUILD_DIR/bat\"}}}}" 101 | - ./bin/behat 102 | 103 | after_failure: 104 | - echo "### DB LOG ###" 105 | - cd $TRAVIS_BUILD_DIR/bat 106 | - drush sqlq 'SELECT * FROM watchdog\G' 107 | - echo "### Server log ###" 108 | - cat ~/debug.txt 109 | - echo "### Selenium log ###" 110 | - cat /tmp/selenium.log 111 | 112 | notifications: 113 | slack: roomify:Z9qyI59J2b9NAF0XvdCn8VhH 114 | 115 | env: 116 | global: 117 | secure: "PUOYps+ygWErjAmF91vh909N927PQad879Kl2X1bZlBpbG5tRgMTdodeG39XxbWjziwnNI+1cybuCg3bqkhAxpf7OmxyIPRbehsIpjIIcVuV+wlkZ7vh0CKlk5fhZA80M3rwqyby6hYxmEj3UpHn4BKJAeH7kwEFGz8DKH96xYfNlmQflAeNCpiGfIFyz1duaWJvLPhw7e2PFpUp3Jt42Sig6w08Ja41v98uagBZ490ZZbZcM6B7GWLNWUcMA5FNCzj1jRHMg7dOZOlw/s1BJkKLE67DDjm0dQVIh5SL/3dZoPbQCqpoW1A6gZxbO61F4EALqfDsEb1LGnTRvzZqqhIQA9zNdrIGgSZzIeHAUGlRaknWjAS+y0WfilSrtvWha2pGYvif5NB2sfhr7wa27C3a6i4L5OZoNzaxxuaS8QJgYIneeESNkiD7/IyT4at0bK0BpV+KFGsa6dO6dWhI3UM7A6PuhSLo8P4CThA0X+US2nHegRgM0slLVC8b0E/ONaEMpHFiygSjf3+z2k2+ETLAa38iQuSLuhrhhUH5luYvim1xlgFvMliCLBk5SCCnTCw2BOLJxq03AdlbAmspw5yrjcOFDov80sTrujSZU98I1dkR8w7nrtuJ7CnRXGPPkbybv1QfYvKIdtzSI0dcsuzNV5kNrvmBRqPgcX3bdCA=" 118 | 119 | # Cache composer/drush files 120 | cache: 121 | directories: 122 | - $HOME/.cache 123 | - $HOME/.composer/cache 124 | - vendor 125 | - test/behat/bin 126 | - test/behat/vendor 127 | - $HOME/.drush/cache 128 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welcome to BAT for Drupal 2 | 3 | BAT stands for Booking and Availability Management Tools. 4 | 5 | [BAT](https://github.com/roomify/bat) on its own is a PHP library that provides some of the core functionality required to build a booking and availability management system. 6 | 7 | BAT for Drupal is a wrapper and UI around BAT. It is build by the [Roomify.us](https://roomify.us) team to provide a foundation through which a wide range of availability management, reservation and booking use cases can be addressed. BAT for Drupal will work with both Drupal 7 and Drupal 8. 8 | 9 | BAT builds on our experience with [Rooms](http://drupal.org/project/rooms), which handles the problem of bookings specifically for the accommodation for rental use case (vacation rentals, hotels, B&B, etc). BAT is essentially a tool to allow you to build modules like Rooms and much more. It handles events with daily or down to the minute granularity. 10 | 11 | As such, BAT is a **booking and availability management framework** - much in the same way that Drupal is a content management framework and Drupal Commerce is an e-commerce framework. Our aim is to build specific solutions on top of BAT to tackle specific application domains. 12 | 13 | 14 | # Objectives 15 | 16 | BAT aims to address the following tasks. 17 | 18 | - **Define bookable things**. Entities that could represent anything within an application domain that have information associated with them about what *state* they find themselves in any given period of time. In addition, you may also need to associate *pricing information* related to the cost of changing the *availability state* of a *thing* over a given time (e.g. booking a hotel room for a few nights). 19 | 20 | - **Manage availability states**. *Bookable things* will find themselves in various states (e.g. "available to book", "unavailable", "currently in use by Bruce", etc). BAT allows you to define such states and provides both GUI-based tools (e.g. interactive calendars) as well as API-based tools to change such states (because machines want to have fun too). 21 | 22 | - **Search for available things**. Given a time range, a set of acceptable availability states, and an arbitrary number of other search filters BAT, should be able to answer questions such as: "BAT, is the car available to pick up from the cave at 4pm today, thanks - Robin". 23 | 24 | - **Determine cost of booking**. At any given time and given state, things may have a cost to change from one state to another (e.g. go from "car sitting in cave" to "car being used by Robin". This cost for the change in state (i.e. a booking) is determined using tools that BAT provides to define what the pricing terms will be. 25 | 26 | 27 | # Installation & Documentation 28 | 29 | Visit [Roomify Documentation](http://docs.roomify.us) for the latest documentation 30 | -------------------------------------------------------------------------------- /bat.api.php: -------------------------------------------------------------------------------- 1 | =2.x) 13 | dependencies[] = xautoload (>=5.x) 14 | -------------------------------------------------------------------------------- /bat.install: -------------------------------------------------------------------------------- 1 | documentation for information on how to fully configure BAT.', array('@DOCS_LINK' => url($docs_path)))); 14 | } 15 | -------------------------------------------------------------------------------- /bat.make: -------------------------------------------------------------------------------- 1 | api = 2 2 | core = 7.x 3 | 4 | ; Required Modules 5 | projects[bat_api][version] = 2.x 6 | projects[xautoload][version] = 5.7 7 | projects[composer_manager][version] = 1.8 8 | projects[date][version] = 2.10 9 | projects[entity][version] = 1.9 10 | projects[entityreference][version] = 1.5 11 | projects[ctools][version] = 1.14 12 | projects[jquery_update][version] = 3.0-alpha5 13 | projects[libraries][version] = 2.4 14 | projects[views][version] = 3.18 15 | projects[views_megarow][version] = 1.7 16 | projects[views_bulk_operations][version] = 3.5 17 | projects[search_api][version] = 1.25 18 | projects[services][version] = 3.20 19 | projects[facetapi][version] = 1.5 20 | projects[facetapi][patch][] = https://www.drupal.org/files/issues/facetapi-cur-search-block-not-exported-1469002_2.patch 21 | 22 | ; FullCalendar 23 | libraries[fullcalendar][directory_name] = fullcalendar 24 | libraries[fullcalendar][type] = library 25 | libraries[fullcalendar][destination] = libraries 26 | libraries[fullcalendar][download][type] = get 27 | ; NB: please update the link in the documentation when changing this version. 28 | libraries[fullcalendar][download][url] = https://github.com/arshaw/fullcalendar/releases/download/v3.9.0/fullcalendar-3.9.0.zip 29 | 30 | ; FullCalendar Scheduler 31 | libraries[scheduler][directory_name] = fullcalendar-scheduler 32 | libraries[scheduler][type] = library 33 | libraries[scheduler][destination] = libraries 34 | libraries[scheduler][download][type] = get 35 | ; NB: please update the link in the documentation when changing this version. 36 | libraries[scheduler][download][url] = https://github.com/fullcalendar/fullcalendar-scheduler/releases/download/v1.9.4/fullcalendar-scheduler-1.9.4.zip 37 | 38 | ; jquery.timepicker 39 | libraries[jquery.timepicker][directory_name] = jquery.timepicker 40 | libraries[jquery.timepicker][type] = library 41 | libraries[jquery.timepicker][destination] = libraries 42 | libraries[jquery.timepicker][download][type] = get 43 | libraries[jquery.timepicker][download][url] = https://github.com/fgelinas/timepicker/archive/24f88f08a9bbf80efd081e99874eea38cb79feba.zip 44 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "roomify/bat": "dev-master" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /css/bat_date_range_fields.css: -------------------------------------------------------------------------------- 1 | /* Theming for unit date range fields. */ 2 | .bat-date-range .start-date, 3 | .bat-date-range .end-date { 4 | display: inline-block; 5 | clear: none; 6 | margin: 0; 7 | } 8 | 9 | .bat-date-range .start-date { 10 | margin-right: 20px; /* LTR */ 11 | } 12 | 13 | /* Start and end date fields */ 14 | .js .bat-date-range .description { 15 | display: none; 16 | } 17 | 18 | .bat-date-range .form-text { 19 | width: 10em; 20 | } 21 | 22 | .bat-date-range .form-item { 23 | margin-right: 0; 24 | } 25 | 26 | .bat-date-range .container-inline-date > .form-item { 27 | margin-right: 0; 28 | display: block; 29 | } 30 | 31 | .bat-date-range .container-inline-date .form-item .form-item { 32 | float: none; 33 | } 34 | 35 | .bat-date-range .container-inline-date .form-item input { 36 | margin-right: 0; 37 | width: 10em; 38 | } 39 | 40 | .bat-date-range .form-type-textfield label { 41 | display: none; 42 | } 43 | 44 | .bat-date-range .date-padding, 45 | .bat-date-range .container-inline-date .date-padding { 46 | padding: 0; 47 | float: none; 48 | } 49 | -------------------------------------------------------------------------------- /js/bat_date_popup.js: -------------------------------------------------------------------------------- 1 | (function ($) { 2 | 3 | /* 4 | * Default settings for all BAT datepickers that come in pairs. 5 | */ 6 | Drupal.behaviors.bat_datepicker = { 7 | attach: function(context) { 8 | 9 | $.datepicker.setDefaults({ 10 | beforeShow: function() { 11 | 12 | // Prevent a negative date range from being selected by updating the 13 | // end date popup's minDate to the specified start date. 14 | instance = $(this).data("datepicker"); 15 | if (instance.settings.startDateSelector !== undefined) { 16 | startDate = $(instance.settings.startDateSelector).val(); 17 | format = instance.settings.dateFormat || $.datepicker._defaults.dateFormat; 18 | if (startDate !== undefined && startDate !== '') { 19 | 20 | // Parse start date using the datepicker format. 21 | date = $.datepicker.parseDate(format, startDate); 22 | 23 | if (instance.settings.endDateDays !== undefined) { 24 | date.setDate(date.getDate() + instance.settings.endDateDays); 25 | } 26 | 27 | // If this event type is of daily granularity, ensure that the end date 28 | // must be at least one day greater than the start date. 29 | if (Drupal.settings.bat.batDateGranularity == 'bat_daily') { 30 | date = new Date(date.valueOf()+864E5); 31 | } 32 | $(this).datepicker("option", "minDate", date); 33 | $(this).datepicker("option", "maxDate", Drupal.settings.datePopup[this.id].settings.maxDate); 34 | } 35 | } 36 | 37 | // If you think this is ugly, you are right - read this though: 38 | // http://blog.foersom.dk/post/598839422/dealing-with-z-index-in-jquery-uis-datepicker 39 | setTimeout(function() { 40 | $(".ui-datepicker").css("z-index", 12); 41 | }, 10); 42 | } 43 | }); 44 | } 45 | }; 46 | })(jQuery); 47 | -------------------------------------------------------------------------------- /modules/bat_booking/bat_booking.info: -------------------------------------------------------------------------------- 1 | name = BAT Booking 2 | description = BAT Booking 3 | core = 7.x 4 | 5 | package = BAT 6 | 7 | dependencies[] = bat_event 8 | 9 | files[] = bat_booking.admin.inc 10 | files[] = bat_booking_type.admin.inc 11 | files[] = views/bat_booking.views.inc 12 | files[] = views/bat_booking_handler_delete_link_field.inc 13 | files[] = views/bat_booking_handler_edit_link_field.inc 14 | files[] = views/bat_booking_handler_night_field.inc 15 | -------------------------------------------------------------------------------- /modules/bat_booking/bat_booking.install: -------------------------------------------------------------------------------- 1 | 'The base table for Bookings.', 24 | 'fields' => array( 25 | 'booking_id' => array( 26 | 'description' => 'Primary Key: Identifier for a Booking.', 27 | 'type' => 'serial', 28 | 'unsigned' => TRUE, 29 | 'not null' => TRUE, 30 | ), 31 | 'type' => array( 32 | 'description' => 'The {booking_type}.type of this Booking.', 33 | 'type' => 'varchar', 34 | 'length' => 255, 35 | 'not null' => TRUE, 36 | 'default' => '', 37 | ), 38 | 'language' => array( 39 | 'description' => 'The language of the Booking.', 40 | 'type' => 'varchar', 41 | 'length' => 32, 42 | 'not null' => TRUE, 43 | 'default' => '', 44 | ), 45 | 'label' => array( 46 | 'description' => 'The label of the Booking - a human-readable identifier.', 47 | 'type' => 'varchar', 48 | 'length' => 255, 49 | 'not null' => TRUE, 50 | 'default' => '', 51 | ), 52 | 'created' => array( 53 | 'description' => 'The Unix timestamp when the Booking was created.', 54 | 'type' => 'int', 55 | 'not null' => TRUE, 56 | 'default' => 0, 57 | ), 58 | 'changed' => array( 59 | 'description' => 'The Unix timestamp when the Booking was most recently saved.', 60 | 'type' => 'int', 61 | 'not null' => TRUE, 62 | 'default' => 0, 63 | ), 64 | 'uid' => array( 65 | 'description' => 'The {users}.uid that created this booking.', 66 | 'type' => 'int', 67 | 'not null' => TRUE, 68 | 'default' => 0, 69 | ), 70 | 'status' => array( 71 | 'type' => 'int', 72 | 'not null' => TRUE, 73 | 'default' => 0x01, 74 | 'size' => 'tiny', 75 | 'description' => 'The exportable status of the entity.', 76 | ), 77 | 'data' => array( 78 | 'type' => 'blob', 79 | 'not null' => FALSE, 80 | 'size' => 'big', 81 | 'serialize' => TRUE, 82 | 'description' => 'A serialized array of additional data.', 83 | ), 84 | ), 85 | 'primary key' => array('booking_id'), 86 | 'indexes' => array( 87 | 'type' => array('type'), 88 | ), 89 | ); 90 | 91 | $schema['bat_booking_types'] = array( 92 | 'description' => 'The base table for Types.', 93 | 'fields' => array( 94 | 'id' => array( 95 | 'type' => 'serial', 96 | 'not null' => TRUE, 97 | 'description' => 'Primary Key: Identifier for a Type.', 98 | ), 99 | 'type' => array( 100 | 'description' => 'The {type_bundle}.type of this Type.', 101 | 'type' => 'varchar', 102 | 'length' => 255, 103 | 'not null' => TRUE, 104 | ), 105 | 'label' => array( 106 | 'description' => 'The human-readable name of this booking type.', 107 | 'type' => 'varchar', 108 | 'length' => 255, 109 | 'not null' => TRUE, 110 | 'default' => '', 111 | ), 112 | 'default_booking_label_field_name' => array( 113 | 'type' => 'varchar', 114 | 'not null' => FALSE, 115 | 'length' => 32, 116 | 'description' => 'The name of a field to use to retrieve label information.', 117 | ), 118 | 'data' => array( 119 | 'type' => 'blob', 120 | 'not null' => FALSE, 121 | 'size' => 'big', 122 | 'serialize' => TRUE, 123 | 'description' => 'A serialized array of additional data.', 124 | ), 125 | 'status' => array( 126 | 'type' => 'int', 127 | 'not null' => TRUE, 128 | 'default' => 0x01, 129 | 'size' => 'tiny', 130 | 'description' => 'The exportable status of the entity.', 131 | ), 132 | 'module' => array( 133 | 'description' => 'The name of the providing module if the entity has been defined in code.', 134 | 'type' => 'varchar', 135 | 'length' => 255, 136 | 'not null' => FALSE, 137 | ), 138 | ), 139 | 'primary key' => array('id'), 140 | 'unique keys' => array( 141 | 'type' => array('type'), 142 | ), 143 | ); 144 | 145 | return $schema; 146 | } 147 | 148 | /** 149 | * Create "Standard" booking type. 150 | */ 151 | function bat_booking_create_standard_booking_type() { 152 | $booking_type = bat_booking_type_create(array( 153 | 'label' => 'Standard', 154 | 'type' => 'standard', 155 | )); 156 | 157 | $booking_type->save(); 158 | } 159 | 160 | /** 161 | * Add default label name field. 162 | */ 163 | function bat_booking_update_7100() { 164 | $field = array( 165 | 'type' => 'varchar', 166 | 'not null' => FALSE, 167 | 'length' => 32, 168 | 'description' => 'The name of a field to use to retrieve label information.', 169 | ); 170 | 171 | db_add_field('bat_booking_types', 'default_booking_label_field_name', $field); 172 | } 173 | 174 | /** 175 | * Rename 'name' field in 'label'. 176 | */ 177 | function bat_booking_update_7101() { 178 | db_change_field('bat_bookings', 'name', 'label', array( 179 | 'description' => 'The label of the Booking - a human-readable identifier.', 180 | 'type' => 'varchar', 181 | 'length' => 255, 182 | 'not null' => TRUE, 183 | 'default' => '', 184 | )); 185 | } 186 | 187 | /** 188 | * Add booking status field. 189 | */ 190 | function bat_booking_update_7102() { 191 | $field = array( 192 | 'type' => 'int', 193 | 'not null' => TRUE, 194 | 'default' => 0x01, 195 | 'size' => 'tiny', 196 | 'description' => 'The exportable status of the entity.', 197 | ); 198 | 199 | db_add_field('bat_bookings', 'status', $field); 200 | } 201 | -------------------------------------------------------------------------------- /modules/bat_booking/bat_booking.tokens.inc: -------------------------------------------------------------------------------- 1 | t('BAT Booking', array(), array('context' => 'a bat booking')), 14 | 'description' => t('Tokens related to bat booking.'), 15 | 'needs-data' => 'bat-booking', 16 | ); 17 | 18 | return array( 19 | 'types' => array('bat_booking' => $type), 20 | 'tokens' => array('bat_booking' => array()), 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /modules/bat_booking/bat_booking_example/bat_booking_example.info: -------------------------------------------------------------------------------- 1 | name = BAT Booking Example 2 | description = BAT Booking Example 3 | core = 7.x 4 | 5 | package = BAT 6 | 7 | dependencies[] = bat_booking 8 | dependencies[] = bat_facets 9 | 10 | files[] = views/bat_booking_example.views.inc 11 | files[] = views/bat_booking_example_book_this_field.inc 12 | -------------------------------------------------------------------------------- /modules/bat_booking/bat_booking_example/bat_booking_example.install: -------------------------------------------------------------------------------- 1 | 'Availability Example', 28 | 'type' => 'availability_example', 29 | 'fixed_event_states' => 1, 30 | 'event_granularity' => 'bat_daily', 31 | 'target_entity_type' => 'bat_unit', 32 | )); 33 | 34 | bat_event_type_save($event); 35 | } 36 | 37 | /** 38 | * Creates the default event states. 39 | */ 40 | function bat_booking_example_create_standard_event_states() { 41 | $event_state = array( 42 | 'label' => 'Available', 43 | 'color' => '#8BA175', 44 | 'calendar_label' => 'AV', 45 | 'machine_name' => 'availability_example_available', 46 | ); 47 | 48 | bat_event_save_state($event_state, 'availability_example'); 49 | 50 | $event_state = array( 51 | 'label' => 'Not Available', 52 | 'color' => '#CC2727', 53 | 'calendar_label' => 'N/A', 54 | 'machine_name' => 'availability_example_not_available', 55 | ); 56 | 57 | bat_event_save_state($event_state, 'availability_example'); 58 | 59 | $event_state = array( 60 | 'label' => 'Booked', 61 | 'color' => '#1A1A73', 62 | 'calendar_label' => 'Booked', 63 | 'blocking' => 1, 64 | 'machine_name' => 'availability_example_available_booked', 65 | ); 66 | 67 | bat_event_save_state($event_state, 'availability_example'); 68 | } 69 | 70 | /** 71 | * Delete the "Availability Example" event type. 72 | */ 73 | function bat_booking_example_delete_availability_event_type() { 74 | if (module_exists('bat_event')) { 75 | if ($event_type = bat_event_type_load('availability_example')) { 76 | bat_event_type_delete($event_type); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /modules/bat_booking/bat_booking_example/bat_booking_example.module: -------------------------------------------------------------------------------- 1 | 'Booking', 20 | 'page callback' => 'bat_booking_confirmation_page', 21 | 'page arguments' => array(1, 2, 3), 22 | 'access arguments' => array('book units'), 23 | 'type' => MENU_CALLBACK, 24 | ); 25 | 26 | return $items; 27 | } 28 | 29 | /** 30 | * Implements hook_theme(). 31 | */ 32 | function bat_booking_example_theme() { 33 | return array( 34 | 'booking_confirmation_page' => array( 35 | 'template' => 'booking_confirmation_page', 36 | 'variables' => array( 37 | 'header' => NULL, 38 | 'form' => NULL, 39 | ), 40 | ), 41 | ); 42 | } 43 | 44 | /** 45 | * Implements hook_views_api(). 46 | */ 47 | function bat_booking_example_views_api() { 48 | return array( 49 | 'api' => 3, 50 | 'path' => drupal_get_path('module', 'bat_booking_example') . '/views', 51 | ); 52 | } 53 | 54 | /** 55 | * Booking confirmation page. 56 | */ 57 | function bat_booking_confirmation_page($start_date, $end_date, $type_id) { 58 | $header = $start_date->format('Y-m-d') . ' - ' . $end_date->format('Y-m-d'); 59 | $form = drupal_get_form('bat_booking_confirmation_form', $start_date, $end_date, $type_id); 60 | 61 | return array( 62 | '#theme' => 'booking_confirmation_page', 63 | '#header' => $header, 64 | '#form' => $form, 65 | ); 66 | } 67 | 68 | /** 69 | * Booking confirmation form. 70 | */ 71 | function bat_booking_confirmation_form($form, &$form_state, $start_date, $end_date, $type_id) { 72 | $form['start_date'] = array( 73 | '#type' => 'hidden', 74 | '#value' => $start_date, 75 | ); 76 | 77 | $form['end_date'] = array( 78 | '#type' => 'hidden', 79 | '#value' => $end_date, 80 | ); 81 | 82 | $form['type_id'] = array( 83 | '#type' => 'hidden', 84 | '#value' => $type_id, 85 | ); 86 | 87 | $form['submit'] = array( 88 | '#type' => 'submit', 89 | '#value' => 'Confirm booking', 90 | ); 91 | 92 | return $form; 93 | } 94 | 95 | /** 96 | * Submit function for the bat_booking_confirmation_form form. 97 | */ 98 | function bat_booking_confirmation_form_submit($form, &$form_state) { 99 | global $user; 100 | 101 | $event_type = 'availability_example'; 102 | 103 | $start_date = $form_state['values']['start_date']; 104 | $end_date = $form_state['values']['end_date']; 105 | $end_date->sub(new DateInterval('PT1M')); 106 | 107 | $type_id = $form_state['values']['type_id']; 108 | 109 | $state_ids = array_keys(bat_event_get_states($event_type)); 110 | 111 | $state_store = new DrupalDBStore($event_type, DrupalDBStore::BAT_STATE); 112 | 113 | $valid_states = array_merge(array(0), array_slice($state_ids, 0, 1)); 114 | 115 | $drupal_units = bat_unit_load_multiple(FALSE, array('type_id' => $type_id)); 116 | $bat_units = array(); 117 | foreach ($drupal_units as $unit_id => $unit) { 118 | $bat_units[] = new Unit($unit_id, $unit->getEventDefaultValue($event_type)); 119 | } 120 | 121 | if (count($bat_units)) { 122 | $calendar = new Calendar($bat_units, $state_store); 123 | 124 | $response = $calendar->getMatchingUnits($start_date, $end_date, $valid_states, array()); 125 | $valid_unit_ids = array_keys($response->getIncluded()); 126 | 127 | if (count($valid_unit_ids)) { 128 | // Create a new Event. 129 | $event = bat_event_create(array( 130 | 'type' => $event_type, 131 | 'start_date' => $start_date->format('Y-m-d H:i:s'), 132 | 'end_date' => $end_date->format('Y-m-d H:i:s'), 133 | 'uid' => $user->uid, 134 | )); 135 | 136 | $event->event_bat_unit_reference[LANGUAGE_NONE][0]['target_id'] = reset($valid_unit_ids); 137 | $event->event_state_reference[LANGUAGE_NONE][0]['state_id'] = end($state_ids); 138 | 139 | $event->save(); 140 | 141 | // Create a new Booking. 142 | $booking = bat_booking_create(array( 143 | 'type' => 'standard', 144 | 'label' => 'Example Booking', 145 | )); 146 | 147 | $booking->booking_start_date[LANGUAGE_NONE][0]['value'] = $start_date->format('Y-m-d H:i:s'); 148 | $booking->booking_end_date[LANGUAGE_NONE][0]['value'] = $end_date->format('Y-m-d H:i:s'); 149 | $booking->booking_event_reference[LANGUAGE_NONE][0]['target_id'] = $event->event_id; 150 | 151 | $booking->save(); 152 | 153 | drupal_set_message(t('Booking created')); 154 | } 155 | else { 156 | drupal_set_message(t('No units'), 'error'); 157 | } 158 | } 159 | } 160 | 161 | /** 162 | * Loads a DateTime object from a string. 163 | * 164 | * @param string $start_date 165 | * Expects to see a date in the form Y-m-d. 166 | * 167 | * @return DateTime 168 | * Object or null if invalid 169 | */ 170 | function start_date_load($start_date) { 171 | $start_date = check_plain($start_date); 172 | 173 | try { 174 | $sd = new DateTime($start_date); 175 | } 176 | catch (Exception $e) { 177 | $sd = 0; 178 | } 179 | 180 | return $sd; 181 | } 182 | 183 | /** 184 | * Loads a DateTime object from a string. 185 | * 186 | * @param string $end_date 187 | * Expects to see a date in the form Y-m-d. 188 | * 189 | * @return DateTime 190 | * Object or null if invalid 191 | */ 192 | function end_date_load($end_date) { 193 | $end_date = check_plain($end_date); 194 | 195 | try { 196 | $ed = new DateTime($end_date); 197 | } 198 | catch (Exception $e) { 199 | $ed = 0; 200 | } 201 | 202 | return $ed; 203 | } 204 | -------------------------------------------------------------------------------- /modules/bat_booking/bat_booking_example/booking_confirmation_page.tpl.php: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /modules/bat_booking/bat_booking_example/views/bat_booking_example.views.inc: -------------------------------------------------------------------------------- 1 | item_type == 'bat_type') { 13 | $data['search_api_index_' . $index->machine_name]['book_this'] = array( 14 | 'field' => array( 15 | 'title' => t('Book this'), 16 | 'help' => t('Display links to create a new booking.'), 17 | 'handler' => 'bat_booking_example_book_this_field', 18 | 'type' => 'text', 19 | ), 20 | ); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /modules/bat_booking/bat_booking_example/views/bat_booking_example_book_this_field.inc: -------------------------------------------------------------------------------- 1 | entity); 18 | } 19 | else { 20 | return '' . t('Insert dates to book') . ''; 21 | } 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /modules/bat_booking/bat_booking_type.admin.inc: -------------------------------------------------------------------------------- 1 | label .= ' (cloned)'; 35 | $booking_type->type = ''; 36 | } 37 | 38 | $form['label'] = array( 39 | '#title' => t('Booking type name'), 40 | '#type' => 'textfield', 41 | '#default_value' => $booking_type->label, 42 | '#description' => t('The human-readable name of this booking type.'), 43 | '#required' => TRUE, 44 | '#size' => 30, 45 | '#weight' => -100, 46 | ); 47 | 48 | // Machine-readable type name. 49 | $form['type'] = array( 50 | '#type' => 'machine_name', 51 | '#default_value' => isset($booking_type->type) ? $booking_type->type : '', 52 | '#maxlength' => 32, 53 | '#machine_name' => array( 54 | 'exists' => 'bat_booking_get_types', 55 | 'source' => array('label'), 56 | ), 57 | '#description' => t('A unique machine-readable name for this booking type. It must only contain lowercase letters, numbers, and underscores.'), 58 | '#weight' => -99, 59 | ); 60 | 61 | if ($op == 'edit') { 62 | $form['type']['#disabled'] = TRUE; 63 | } 64 | 65 | // Add the field related form elements. 66 | $form_state['bat_booking_type'] = $booking_type; 67 | field_attach_form('bat_booking_type', $booking_type, $form, $form_state); 68 | 69 | $form['additional_settings'] = array( 70 | '#type' => 'vertical_tabs', 71 | '#weight' => 99, 72 | ); 73 | 74 | if (!isset($booking_type->is_new)) { 75 | $fields_options = array(); 76 | $fields = field_info_instances('bat_booking', $booking_type->type); 77 | 78 | foreach ($fields as $field) { 79 | $field_info = field_info_field($field['field_name']); 80 | $fields_options[$field['field_name']] = $field['field_name']; 81 | } 82 | 83 | $form['event_label'] = array( 84 | '#type' => 'fieldset', 85 | '#group' => 'additional_settings', 86 | '#title' => t('Label Source'), 87 | '#tree' => TRUE, 88 | '#weight' => 80, 89 | ); 90 | 91 | $form['event_label']['default_booking_label_field_name'] = array( 92 | '#type' => 'select', 93 | '#title' => t('Select your label field', array('@booking' => $booking_type->label)), 94 | '#default_value' => isset($booking_type->default_booking_label_field_name) ? $booking_type->default_booking_label_field_name : NULL, 95 | '#empty_option' => t('- Select a field -'), 96 | '#description' => t('If you select a field here, its value will be used as the label for your booking. BAT will fall back to using the property name as the label if the field has no value.'), 97 | '#options' => $fields_options, 98 | ); 99 | } 100 | 101 | $form['actions'] = array( 102 | '#type' => 'actions', 103 | '#tree' => FALSE, 104 | ); 105 | 106 | $form['actions']['submit'] = array( 107 | '#type' => 'submit', 108 | '#value' => t('Save booking type'), 109 | '#weight' => 100, 110 | '#submit' => array('bat_booking_type_form_submit'), 111 | ); 112 | 113 | $form['#validate'][] = 'bat_booking_type_form_validate'; 114 | return $form; 115 | } 116 | 117 | /** 118 | * Form API validation callback for the booking type form. 119 | */ 120 | function bat_booking_type_form_validate(&$form, &$form_state) { 121 | // Notify field widgets to validate their data. 122 | entity_form_field_validate('bat_booking_type', $form, $form_state); 123 | } 124 | 125 | /** 126 | * Form API submit callback for the booking type form. 127 | */ 128 | function bat_booking_type_form_submit(&$form, &$form_state) { 129 | if (isset($form_state['values']['event_label']['default_booking_label_field_name'])) { 130 | $form_state['bat_booking_type']->default_booking_label_field_name = $form_state['values']['event_label']['default_booking_label_field_name']; 131 | } 132 | 133 | $booking_type = entity_ui_controller('bat_booking_type')->entityFormSubmitBuildEntity($form, $form_state); 134 | // Save and go back. 135 | $booking_type->save(); 136 | 137 | $form_state['booking_type'] = $booking_type; 138 | 139 | $form_state['redirect'] = 'admin/bat/config/booking-types'; 140 | } 141 | -------------------------------------------------------------------------------- /modules/bat_booking/views/bat_booking.views.inc: -------------------------------------------------------------------------------- 1 | array( 13 | 'title' => t('Edit Link'), 14 | 'help' => t('Provide a link to the edit form for the booking.'), 15 | 'handler' => 'bat_booking_handler_edit_link_field', 16 | ), 17 | ); 18 | $data['bat_bookings']['delete_unit'] = array( 19 | 'field' => array( 20 | 'title' => t('Delete Link'), 21 | 'help' => t('Provide a link to delete the booking.'), 22 | 'handler' => 'bat_booking_handler_delete_link_field', 23 | ), 24 | ); 25 | 26 | $data['bat_bookings']['nights'] = array( 27 | 'field' => array( 28 | 'title' => t('Nights'), 29 | 'help' => t('Provide number of nights.'), 30 | 'handler' => 'bat_booking_handler_night_field', 31 | ), 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /modules/bat_booking/views/bat_booking_handler_delete_link_field.inc: -------------------------------------------------------------------------------- 1 | additional_fields['booking_id'] = 'booking_id'; 21 | } 22 | 23 | /** 24 | * {@inheritdoc} 25 | */ 26 | public function option_definition() { 27 | $options = parent::option_definition(); 28 | 29 | $options['text'] = array('default' => '', 'translatable' => TRUE); 30 | 31 | return $options; 32 | } 33 | 34 | /** 35 | * {@inheritdoc} 36 | */ 37 | public function options_form(&$form, &$form_state) { 38 | parent::options_form($form, $form_state); 39 | 40 | $form['text'] = array( 41 | '#type' => 'textfield', 42 | '#title' => t('Text to display'), 43 | '#default_value' => $this->options['text'], 44 | ); 45 | } 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | public function query() { 51 | $this->ensure_my_table(); 52 | $this->add_additional_fields(); 53 | } 54 | 55 | /** 56 | * {@inheritdoc} 57 | */ 58 | public function render($values) { 59 | $text = !empty($this->options['text']) ? $this->options['text'] : t('delete'); 60 | $booking_id = $values->{$this->aliases['booking_id']}; 61 | 62 | return l($text, 'admin/bat/config/booking/manage/' . $booking_id . '/delete', array('query' => drupal_get_destination())); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /modules/bat_booking/views/bat_booking_handler_edit_link_field.inc: -------------------------------------------------------------------------------- 1 | additional_fields['booking_id'] = 'booking_id'; 21 | } 22 | 23 | /** 24 | * {@inheritdoc} 25 | */ 26 | public function option_definition() { 27 | $options = parent::option_definition(); 28 | 29 | $options['text'] = array('default' => '', 'translatable' => TRUE); 30 | 31 | return $options; 32 | } 33 | 34 | /** 35 | * {@inheritdoc} 36 | */ 37 | public function options_form(&$form, &$form_state) { 38 | parent::options_form($form, $form_state); 39 | 40 | $form['text'] = array( 41 | '#type' => 'textfield', 42 | '#title' => t('Text to display'), 43 | '#default_value' => $this->options['text'], 44 | ); 45 | } 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | public function query() { 51 | $this->ensure_my_table(); 52 | $this->add_additional_fields(); 53 | } 54 | 55 | /** 56 | * {@inheritdoc} 57 | */ 58 | public function render($values) { 59 | $text = !empty($this->options['text']) ? $this->options['text'] : t('edit'); 60 | $booking_id = $values->{$this->aliases['booking_id']}; 61 | 62 | return l($text, 'admin/bat/config/booking/manage/' . $booking_id, array('query' => drupal_get_destination())); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /modules/bat_booking/views/bat_booking_handler_night_field.inc: -------------------------------------------------------------------------------- 1 | additional_fields['booking_id'] = 'booking_id'; 19 | } 20 | 21 | /** 22 | * {@inheritdoc} 23 | */ 24 | public function query() { 25 | $this->ensure_my_table(); 26 | $this->add_additional_fields(); 27 | } 28 | 29 | /** 30 | * {@inheritdoc} 31 | */ 32 | public function render($values) { 33 | $booking = bat_booking_load($values->{$this->aliases['booking_id']}); 34 | 35 | $start_date = new DateTime($booking->booking_start_date[LANGUAGE_NONE][0]['value']); 36 | $end_date = new DateTime($booking->booking_end_date[LANGUAGE_NONE][0]['value']); 37 | 38 | return $end_date->diff($start_date)->days; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /modules/bat_calendar_reference/bat_calendar_reference.info: -------------------------------------------------------------------------------- 1 | name = BAT Calendar Reference 2 | description = Provides a field to reference and display event information on any fieldable entity. 3 | core = 7.x 4 | 5 | package = BAT 6 | 7 | dependencies[] = bat_fullcalendar 8 | -------------------------------------------------------------------------------- /modules/bat_calendar_reference/bat_calendar_reference.install: -------------------------------------------------------------------------------- 1 | array( 16 | 'type' => 'int', 17 | 'unsigned' => TRUE, 18 | 'not null' => FALSE, 19 | ), 20 | 'event_type_id' => array( 21 | 'type' => 'int', 22 | 'unsigned' => TRUE, 23 | 'not null' => FALSE, 24 | ), 25 | ); 26 | return array( 27 | 'columns' => $columns, 28 | 'indexes' => array('unit_id' => array('unit_id')), 29 | 'foreign keys' => array( 30 | 'unit_id' => array( 31 | 'table' => 'bat_units', 32 | 'columns' => array('unit_id' => 'unit_id'), 33 | ), 34 | 'event_type_id' => array( 35 | 'table' => 'bat_calendar_type', 36 | 'columns' => array('id' => 'id'), 37 | ), 38 | ), 39 | ); 40 | } 41 | elseif ($field['type'] == 'bat_calendar_unit_type_reference') { 42 | $columns = array( 43 | 'unit_type_id' => array( 44 | 'type' => 'int', 45 | 'unsigned' => TRUE, 46 | 'not null' => FALSE, 47 | ), 48 | 'event_type_id' => array( 49 | 'type' => 'int', 50 | 'unsigned' => TRUE, 51 | 'not null' => FALSE, 52 | ), 53 | ); 54 | return array( 55 | 'columns' => $columns, 56 | 'indexes' => array('unit_type_id' => array('unit_type_id')), 57 | 'foreign keys' => array( 58 | 'unit_type_id' => array( 59 | 'table' => 'bat_types', 60 | 'columns' => array('type_id' => 'type_id'), 61 | ), 62 | 'event_type_id' => array( 63 | 'table' => 'bat_calendar_type', 64 | 'columns' => array('id' => 'id'), 65 | ), 66 | ), 67 | ); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /modules/bat_calendar_reference/js/bat_calendar_reference.js: -------------------------------------------------------------------------------- 1 | (function ($) { 2 | 3 | Drupal.behaviors.bat_calendar_reference = { 4 | attach: function(context) { 5 | var today = moment(); 6 | 7 | businessHours = { 8 | start: '00:00', 9 | end: '24:00', 10 | dow: [0, 1, 2, 3, 4, 5, 6], 11 | }; 12 | 13 | $('.cal').once('cal', function() { 14 | var lastSource; 15 | var cal_id = $(this).attr('id'); 16 | 17 | $(this).fullCalendar({ 18 | schedulerLicenseKey: Drupal.settings.batCalendar[cal_id].schedulerLicenseKey, 19 | themeSystem: Drupal.settings.batCalendar[cal_id].themeSystem, 20 | locale: Drupal.settings.batCalendar[cal_id].locale, 21 | slotWidth: Drupal.settings.batCalendar[cal_id].slotWidth, 22 | height: Drupal.settings.batCalendar[cal_id].calendarHeight, 23 | editable: Drupal.settings.batCalendar[cal_id].editable, 24 | selectable: Drupal.settings.batCalendar[cal_id].selectable, 25 | eventStartEditable: Drupal.settings.batCalendar[cal_id].eventStartEditable, 26 | eventDurationEditable: Drupal.settings.batCalendar[cal_id].eventDurationEditable, 27 | dayNamesShort:[Drupal.t('Sun'), Drupal.t('Mon'), Drupal.t('Tue'), Drupal.t('Wed'), Drupal.t('Thu'), Drupal.t('Fri'), Drupal.t('Sat')], 28 | monthNames:[Drupal.t('January'), Drupal.t('February'), Drupal.t('March'), Drupal.t('April'), Drupal.t('May'), Drupal.t('June'), Drupal.t('July'), Drupal.t('August'), Drupal.t('September'), Drupal.t('October'), Drupal.t('November'), Drupal.t('December')], 29 | header: { 30 | left: Drupal.settings.batCalendar[cal_id].headerLeft, 31 | center: Drupal.settings.batCalendar[cal_id].headerCenter, 32 | right: Drupal.settings.batCalendar[cal_id].headerRight, 33 | }, 34 | allDayDefault: Drupal.settings.batCalendar[cal_id].allDayDefault, 35 | validRange: Drupal.settings.batCalendar[cal_id].validRange, 36 | businessHours: Drupal.settings.batCalendar[cal_id].businessHours, 37 | defaultView: Drupal.settings.batCalendar[cal_id].defaultView, 38 | scrollTime: Drupal.settings.batCalendar[cal_id].scrollTime, 39 | selectConstraint: (Drupal.settings.batCalendar[cal_id].selectConstraint == null) ? undefined : Drupal.settings.batCalendar[cal_id].selectConstraint, 40 | minTime: Drupal.settings.batCalendar[cal_id].minTime, 41 | maxTime: Drupal.settings.batCalendar[cal_id].maxTime, 42 | hiddenDays: Drupal.settings.batCalendar[cal_id].hiddenDays, 43 | validRange: Drupal.settings.batCalendar[cal_id].validRange, 44 | defaultDate: $.fullCalendar.moment(Drupal.settings.batCalendar[cal_id].defaultDate), 45 | views: { 46 | timelineDay: { 47 | buttonText: Drupal.settings.batCalendar[cal_id].viewsTimelineDayButtonText, 48 | slotDuration: Drupal.settings.batCalendar[cal_id].viewsTimelineDaySlotDuration, 49 | slotLabelFormat: Drupal.settings.batCalendar[cal_id].viewsTimelineDaySlotLabelFormat, 50 | titleFormat: Drupal.settings.batCalendar[cal_id].viewsTimelineDayTitleFormat 51 | }, 52 | timelineSevenDay: { 53 | buttonText: Drupal.settings.batCalendar[cal_id].viewsTimelineSevenDayButtonText, 54 | duration: Drupal.settings.batCalendar[cal_id].viewsTimelineSevenDayDuration, 55 | slotDuration: Drupal.settings.batCalendar[cal_id].viewsTimelineSevenDaySlotDuration, 56 | slotLabelFormat: Drupal.settings.batCalendar[cal_id].viewsTimelineSevenDaySlotLabelFormat, 57 | titleFormat: Drupal.settings.batCalendar[cal_id].viewsTimelineSevenDayTitleFormat, 58 | type: 'timeline' 59 | }, 60 | timelineTenDay: { 61 | buttonText: Drupal.settings.batCalendar[cal_id].viewsTimelineTenDayButtonText, 62 | duration: Drupal.settings.batCalendar[cal_id].viewsTimelineTenDayDuration, 63 | slotDuration: Drupal.settings.batCalendar[cal_id].viewsTimelineTenDaySlotDuration, 64 | slotLabelFormat: Drupal.settings.batCalendar[cal_id].viewsTimelineTenDaySlotLabelFormat, 65 | titleFormat: Drupal.settings.batCalendar[cal_id].viewsTimelineTenDayTitleFormat, 66 | type: 'timeline' 67 | }, 68 | timelineThirtyDay: { 69 | buttonText: Drupal.settings.batCalendar[cal_id].viewsTimelineThirtyDayButtonText, 70 | duration: Drupal.settings.batCalendar[cal_id].viewsTimelineThirtyDayDuration, 71 | slotDuration: Drupal.settings.batCalendar[cal_id].viewsTimelineThirtyDaySlotDuration, 72 | slotLabelFormat: Drupal.settings.batCalendar[cal_id].viewsTimelineThirtyDaySlotLabelFormat, 73 | titleFormat: Drupal.settings.batCalendar[cal_id].viewsTimelineThirtyDayTitleFormat, 74 | type: 'timeline' 75 | }, 76 | timeline365Day: { 77 | buttonText: Drupal.settings.batCalendar[cal_id].viewsTimeline365DayButtonText, 78 | duration: Drupal.settings.batCalendar[cal_id].viewsTimeline365DayDuration, 79 | slotLabelFormat: Drupal.settings.batCalendar[cal_id].viewsTimeline365DaySlotLabelFormat, 80 | titleFormat: Drupal.settings.batCalendar[cal_id].viewsTimeline365DayTitleFormat, 81 | type: 'timeline' 82 | } 83 | }, 84 | groupByResource: Drupal.settings.batCalendar[cal_id].groupByResource, 85 | groupByDateAndResource: Drupal.settings.batCalendar[cal_id].groupByDateAndResource, 86 | firstDay: Drupal.settings.batCalendar[cal_id].firstDay, 87 | eventOrder: Drupal.settings.batCalendar[cal_id].eventOrder, 88 | titleFormat: Drupal.settings.batCalendar[cal_id].titleFormat, 89 | slotLabelFormat: Drupal.settings.batCalendar[cal_id].slotLabelFormat, 90 | resourceAreaWidth: Drupal.settings.batCalendar[cal_id].resourceAreaWidth, 91 | resourceLabelText: Drupal.settings.batCalendar[cal_id].resourceLabelText, 92 | resources: Drupal.settings.basePath + '?q=' + Drupal.settings.pathPrefix + 'bat/v2/units-calendar&types=' + Drupal.settings.batCalendar[cal_id].unitTypes + '&ids=' + Drupal.settings.batCalendar[cal_id].unitIDs + '&event_type=' + Drupal.settings.batCalendar[cal_id].eventType, 93 | events: Drupal.settings.basePath + '?q=' + Drupal.settings.pathPrefix + 'bat/v2/events-calendar&unit_types=' + Drupal.settings.batCalendar[cal_id].unitTypes + '&event_types=' + Drupal.settings.batCalendar[cal_id].eventType + '&unit_ids=' + Drupal.settings.batCalendar[cal_id].unitIDs + '&background=' + Drupal.settings.batCalendar[cal_id].background, 94 | windowResize: function(view) { 95 | $(this).fullCalendar('refetchEvents'); 96 | }, 97 | eventRender: function(event, el, view) { 98 | // Remove Time from events. 99 | el.find('.fc-time').remove(); 100 | 101 | // Append event title when rendering as background. 102 | if (event.rendering == 'background' && event.fixed == 0) { 103 | el.append('' + (event.title || ' ') + ''); 104 | } 105 | } 106 | }); 107 | 108 | }); 109 | 110 | // Resize takes care of some quirks on occasion 111 | $(window).resize(); 112 | 113 | } 114 | }; 115 | 116 | })(jQuery); 117 | -------------------------------------------------------------------------------- /modules/bat_event/bat_event.api.php: -------------------------------------------------------------------------------- 1 | array( 13 | 'label' => t('state'), 14 | 'ui class' => 'RulesDataUIEventStateReference', 15 | 'wrap' => TRUE, 16 | 'property info' => bat_event_state_reference_field_data_property_info(), 17 | ), 18 | ); 19 | } 20 | 21 | /** 22 | * Defines a bat_event_state_reference input form for Rules. 23 | */ 24 | class RulesDataUIEventStateReference extends RulesDataUI implements RulesDataDirectInputFormInterface { 25 | 26 | /** 27 | * {@inheritdoc} 28 | */ 29 | public static function getDefaultMode() { 30 | return 'input'; 31 | } 32 | 33 | /** 34 | * {@inheritdoc} 35 | */ 36 | public static function inputForm($name, $info, $settings, RulesPlugin $element) { 37 | $settings += array($name => isset($info['default value']) ? $info['default value'] : array('state' => '')); 38 | $value = $settings[$name]; 39 | 40 | $options = array(); 41 | foreach (bat_event_get_states() as $state) { 42 | $options[$state['machine_name']] = $state['label'] . ' (' . $state['id'] . ')'; 43 | } 44 | 45 | $form[$name]['state'] = array( 46 | '#type' => 'select', 47 | '#options' => $options, 48 | '#default_value' => isset($value['state']) ? $value['state'] : '', 49 | '#required' => TRUE, 50 | ); 51 | 52 | return $form; 53 | } 54 | 55 | /** 56 | * {@inheritdoc} 57 | */ 58 | public static function render($value) { 59 | return array( 60 | 'content' => array( 61 | '#markup' => $value['state'], 62 | ), 63 | ); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /modules/bat_event/bat_event.tpl.php: -------------------------------------------------------------------------------- 1 | 31 |
> 32 | 33 | > 34 | 35 | 36 | 37 | 38 |
> 39 | 44 |
45 |
46 | -------------------------------------------------------------------------------- /modules/bat_event/bat_event_type.admin.inc: -------------------------------------------------------------------------------- 1 | path]['description'] = 'Manage event types, including adding and removing fields and the display of fields.'; 23 | $items[$this->path]['weight'] = '3'; 24 | $items[$this->path]['type'] = MENU_LOCAL_TASK; 25 | 26 | return $items; 27 | } 28 | 29 | /** 30 | * {@inheritdoc} 31 | */ 32 | protected function overviewTableRow($conditions, $id, $entity, $additional_cols = array()) { 33 | $row = parent::overviewTableRow($conditions, $id, $entity, $additional_cols); 34 | $row[] = l(t('manage states'), $this->path . '/manage/' . $id . '/states'); 35 | 36 | return $row; 37 | } 38 | 39 | /** 40 | * {@inheritdoc} 41 | */ 42 | protected function operationCount() { 43 | return parent::operationCount() + 1; 44 | } 45 | 46 | } 47 | 48 | /** 49 | * Generates the Event type editing form. 50 | */ 51 | function bat_event_type_form($form, &$form_state, $event_type, $op = 'edit') { 52 | $form['#attributes']['class'][] = 'bat-management-form bat-event-type-form'; 53 | 54 | if ($op == 'clone') { 55 | $event_type->label .= ' (cloned)'; 56 | $event_type->type = ''; 57 | } 58 | 59 | $form['label'] = array( 60 | '#title' => t('Label'), 61 | '#type' => 'textfield', 62 | '#default_value' => $event_type->label, 63 | '#description' => t('The human-readable name of this event type.'), 64 | '#required' => TRUE, 65 | '#size' => 30, 66 | ); 67 | 68 | // Machine-readable type name. 69 | $form['type'] = array( 70 | '#type' => 'machine_name', 71 | '#default_value' => isset($event_type->type) ? $event_type->type : '', 72 | '#maxlength' => 32, 73 | '#machine_name' => array( 74 | 'exists' => 'bat_event_get_types', 75 | 'source' => array('label'), 76 | ), 77 | '#description' => t('A unique machine-readable name for this event type. It must only contain lowercase letters, numbers, and underscores.'), 78 | ); 79 | 80 | if ($op == 'add') { 81 | $form['fixed_event_states'] = array( 82 | '#type' => 'checkbox', 83 | '#title' => t('Fixed event states'), 84 | ); 85 | } 86 | elseif ($op == 'edit') { 87 | $form['type']['#disabled'] = TRUE; 88 | } 89 | 90 | $form['event_granularity'] = array( 91 | '#type' => 'select', 92 | '#title' => t('Event Granularity'), 93 | '#options' => array('bat_daily' => t('Daily'), 'bat_hourly' => t('Hourly')), 94 | '#default_value' => isset($event_type->event_granularity) ? $event_type->event_granularity : 'bat_daily', 95 | ); 96 | 97 | if (isset($event_type->is_new)) { 98 | // Check for available Target Entity types. 99 | $target_entity_types = module_invoke_all('bat_event_target_entity_types'); 100 | if (count($target_entity_types) == 1) { 101 | // If there's only one target entity type, we simply store the value 102 | // without showing it to the user. 103 | $form['target_entity_type'] = array( 104 | '#type' => 'value', 105 | '#value' => $target_entity_types[0], 106 | ); 107 | } 108 | else { 109 | // Build option list. 110 | $options = array(); 111 | foreach ($target_entity_types as $target_entity_type) { 112 | $target_entity_info = entity_get_info($target_entity_type); 113 | $options[$target_entity_type] = $target_entity_info['label']; 114 | } 115 | $form['target_entity_type'] = array( 116 | '#type' => 'select', 117 | '#title' => t('Target Entity Type'), 118 | '#description' => t('Select the target entity type for this Event type. In most cases you will wish to leave this as "Unit".'), 119 | '#options' => $options, 120 | // Default to BAT Unit if available. 121 | '#default_value' => isset($target_entity_types['bat_unit']) ? 'bat_unit' : '', 122 | ); 123 | } 124 | } 125 | 126 | if (!isset($event_type->is_new) && $event_type->fixed_event_states == 0) { 127 | $fields_options = array(); 128 | 129 | $fields = field_info_instances('bat_event', $event_type->type); 130 | 131 | foreach ($fields as $field) { 132 | $fields_options[$field['field_name']] = $field['field_name']; 133 | } 134 | 135 | $form['events'] = array( 136 | '#type' => 'fieldset', 137 | '#group' => 'additional_settings', 138 | '#title' => t('Events'), 139 | '#tree' => TRUE, 140 | '#weight' => 80, 141 | ); 142 | 143 | $form['events'][$event_type->type] = array( 144 | '#type' => 'select', 145 | '#title' => t('Select your default @event field', array('@event' => $event_type->label)), 146 | '#options' => $fields_options, 147 | '#default_value' => isset($event_type->default_event_value_field_ids[$event_type->type]) ? $event_type->default_event_value_field_ids[$event_type->type] : NULL, 148 | '#empty_option' => t('- Select a field -'), 149 | ); 150 | } 151 | 152 | if (!isset($event_type->is_new)) { 153 | $fields_options = array(); 154 | $fields = field_info_instances('bat_event', $event_type->type); 155 | 156 | foreach ($fields as $field) { 157 | $fields_options[$field['field_name']] = $field['field_name']; 158 | } 159 | 160 | $form['event_label'] = array( 161 | '#type' => 'fieldset', 162 | '#group' => 'additional_settings', 163 | '#title' => t('Label Source'), 164 | '#tree' => TRUE, 165 | '#weight' => 80, 166 | ); 167 | 168 | $form['event_label']['default_event_label_field_name'] = array( 169 | '#type' => 'select', 170 | '#title' => t('Select your label field', array('@event' => $event_type->label)), 171 | '#default_value' => isset($event_type->default_event_label_field_name) ? $event_type->default_event_label_field_name : NULL, 172 | '#empty_option' => t('- Select a field -'), 173 | '#description' => t('If you select a field here, its value will be used as the label for your event. BAT will fall back to using the event state as the label if the field has no value.'), 174 | '#options' => $fields_options, 175 | ); 176 | } 177 | 178 | $form['actions'] = array( 179 | '#type' => 'actions', 180 | '#tree' => FALSE, 181 | ); 182 | $form['actions']['submit'] = array( 183 | '#type' => 'submit', 184 | '#value' => t('Save Event type'), 185 | '#weight' => 40, 186 | '#submit' => array('bat_event_type_form_submit'), 187 | ); 188 | 189 | return $form; 190 | } 191 | 192 | /** 193 | * Form API submit callback for the event type form. 194 | */ 195 | function bat_event_type_form_submit(&$form, &$form_state) { 196 | if (isset($form_state['values']['events'][$form_state['values']['type']])) { 197 | foreach ($form_state['values']['events'] as $event => $field) { 198 | $form_state['bat_event_type']->default_event_value_field_ids[$event] = $field; 199 | } 200 | } 201 | if (isset($form_state['values']['event_label']['default_event_label_field_name'])) { 202 | $form_state['bat_event_type']->default_event_label_field_name = $form_state['values']['event_label']['default_event_label_field_name']; 203 | } 204 | 205 | $event_type = entity_ui_form_submit_build_entity($form, $form_state); 206 | // Save and go back. 207 | $event_type->save(); 208 | $form_state['redirect'] = 'admin/bat/events/event-types'; 209 | } 210 | 211 | /** 212 | * Form API submit callback for the delete button. 213 | */ 214 | function bat_event_type_form_submit_delete(&$form, &$form_state) { 215 | $destination = array(); 216 | if (isset($_GET['destination'])) { 217 | $destination = drupal_get_destination(); 218 | unset($_GET['destination']); 219 | } 220 | 221 | $form_state['redirect'] = array('admin/bat/events/event_types/manage/' . $form_state['bat_event_type']->type . '/delete', array('query' => $destination)); 222 | } 223 | -------------------------------------------------------------------------------- /modules/bat_event/js/bat_color.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementation of hook_elements. 3 | * 4 | * Much of the colorpicker code was adapted from the Colorpicker module. 5 | * That module has no stable release yet nor any D6 branch. 6 | */ 7 | /* 8 | * Bind the colorpicker event to the form element 9 | */ 10 | (function ($) { 11 | Drupal.behaviors.field_example_colorpicker = { 12 | attach: function(context) { 13 | $(".bat-edit-colorpicker").on("focus", function(event) { 14 | var edit_field = this; 15 | var picker = $(this).closest('div').parent().find(".bat-colorpicker"); 16 | 17 | // Hide all color pickers except this one. 18 | $(".bat-colorpicker").hide(); 19 | $(picker).show(); 20 | $.farbtastic(picker, function(color) { 21 | edit_field.value = color; 22 | }).setColor(edit_field.value); 23 | }); 24 | } 25 | }; 26 | })(jQuery); 27 | -------------------------------------------------------------------------------- /modules/bat_event/js/bat_event.js: -------------------------------------------------------------------------------- 1 | 2 | (function ($) { 3 | 4 | Drupal.behaviors.eventFieldsetSummaries = { 5 | attach: function (context) { 6 | $('fieldset#edit-user', context).drupalSetSummary(function (context) { 7 | var name = $('#edit-owner-name').val() || Drupal.settings.anonymous; 8 | return Drupal.t('Owned by @name', { '@name': name }); 9 | }); 10 | 11 | $('fieldset#edit-event-history', context).drupalSetSummary(function (context) { 12 | var summary = $('#edit-created', context).val() ? 13 | Drupal.t('Created @date', { '@date' : $('#edit-created').val() }) : 14 | Drupal.t('New order'); 15 | 16 | // Add the changed date to the summary if it's different from the created. 17 | if ($('#edit-created', context).val() != $('#edit-changed', context).val()) { 18 | summary += '
' + Drupal.t('Updated @date', { '@date' : $('#edit-changed').val() }); 19 | } 20 | 21 | return summary; 22 | }); 23 | } 24 | }; 25 | 26 | })(jQuery); 27 | -------------------------------------------------------------------------------- /modules/bat_event/views/bat_event.views.inc: -------------------------------------------------------------------------------- 1 | array( 14 | 'title' => t('Link'), 15 | 'help' => t('Provide a link to the event.'), 16 | 'handler' => 'bat_event_handler_link_field', 17 | ), 18 | ); 19 | $data['bat_events']['edit_event'] = array( 20 | 'field' => array( 21 | 'title' => t('Edit Link'), 22 | 'help' => t('Provide a link to the edit form for the event.'), 23 | 'handler' => 'bat_event_handler_edit_link_field', 24 | ), 25 | ); 26 | $data['bat_events']['delete_event'] = array( 27 | 'field' => array( 28 | 'title' => t('Delete Link'), 29 | 'help' => t('Provide a link to delete the event.'), 30 | 'handler' => 'bat_event_handler_delete_link_field', 31 | ), 32 | ); 33 | // This content of this field are decided based on the menu structure that 34 | // follows bat/event/%event_id/op. 35 | $data['bat_events']['operations'] = array( 36 | 'field' => array( 37 | 'title' => t('Operations links'), 38 | 'help' => t('Display all operations available for this event.'), 39 | 'handler' => 'bat_event_handler_event_operations_field', 40 | ), 41 | ); 42 | $data['bat_events']['start_date'] = array( 43 | 'title' => t('Start Date'), 44 | 'help' => t("A event's start date."), 45 | 'field' => array( 46 | 'float' => TRUE, 47 | 'handler' => 'bat_event_handler_date_field', 48 | 'click sortable' => TRUE, 49 | ), 50 | 'sort' => array( 51 | 'handler' => 'views_handler_sort_date', 52 | ), 53 | 'filter' => array( 54 | 'handler' => 'bat_event_handler_date_filter', 55 | ), 56 | ); 57 | $data['bat_events']['end_date'] = array( 58 | 'title' => t('End Date'), 59 | 'help' => t("A event's end date."), 60 | 'field' => array( 61 | 'float' => TRUE, 62 | 'handler' => 'bat_event_handler_date_field', 63 | 'click sortable' => TRUE, 64 | ), 65 | 'sort' => array( 66 | 'handler' => 'views_handler_sort_date', 67 | ), 68 | 'filter' => array( 69 | 'handler' => 'bat_event_handler_date_filter', 70 | ), 71 | ); 72 | $data['bat_events']['type']['field'] = array( 73 | 'title' => t('Event Type'), 74 | 'help' => t('The event type label.'), 75 | 'handler' => 'bat_event_handler_event_type_field', 76 | ); 77 | 78 | // Expose the uid as a relationship to users. 79 | $data['bat_events']['uid'] = array( 80 | 'title' => t('Uid'), 81 | 'help' => t("The owner's user ID."), 82 | 'field' => array( 83 | 'handler' => 'views_handler_field_user', 84 | 'click sortable' => TRUE, 85 | ), 86 | 'argument' => array( 87 | 'handler' => 'views_handler_argument_user_uid', 88 | 'name field' => 'name', 89 | ), 90 | 'filter' => array( 91 | 'title' => t('Name'), 92 | 'handler' => 'views_handler_filter_user_name', 93 | ), 94 | 'sort' => array( 95 | 'handler' => 'views_handler_sort', 96 | ), 97 | 'relationship' => array( 98 | 'title' => t('Owner'), 99 | 'help' => t("Relate this event to its owner's user account"), 100 | 'handler' => 'views_handler_relationship', 101 | 'base' => 'users', 102 | 'base field' => 'uid', 103 | 'field' => 'uid', 104 | 'label' => t('Event owner'), 105 | ), 106 | ); 107 | 108 | $data['bat_events']['duration'] = array( 109 | 'title' => t('Duration'), 110 | 'help' => t("Event's duration."), 111 | 'field' => array( 112 | 'handler' => 'bat_event_handler_duration_field', 113 | 'click sortable' => TRUE, 114 | ), 115 | ); 116 | 117 | $data['bat_events']['event_value'] = array( 118 | 'title' => t('Value'), 119 | 'help' => t("Event's value."), 120 | 'field' => array( 121 | 'handler' => 'bat_event_handler_value_field', 122 | ), 123 | ); 124 | 125 | $data['bat_events']['blocking'] = array( 126 | 'title' => t('Blocking'), 127 | 'help' => t("Event's blocking state."), 128 | 'filter' => array( 129 | 'handler' => 'bat_event_handler_blocking_filter', 130 | ), 131 | ); 132 | } 133 | 134 | /** 135 | * Implements hook_field_views_data(). 136 | */ 137 | function bat_event_field_views_data($field) { 138 | $data = field_views_field_default_views_data($field); 139 | $field_name = $field['field_name']; 140 | 141 | if (isset($data['field_data_' . $field_name])) { 142 | if ($field['type'] == 'bat_event_state_reference') { 143 | $data['field_data_' . $field_name][$field_name . '_state_id']['filter']['handler'] = 'bat_event_handler_event_state_filter'; 144 | } 145 | } 146 | 147 | return $data; 148 | } 149 | -------------------------------------------------------------------------------- /modules/bat_event/views/bat_event_handler_blocking_filter.inc: -------------------------------------------------------------------------------- 1 | value_value = t('State'); 19 | } 20 | 21 | /** 22 | * {@inheritdoc} 23 | */ 24 | public function get_value_options() { 25 | $options = array( 26 | 'blocking' => t('Blocking'), 27 | 'not_blocking' => t('Not blocking'), 28 | ); 29 | 30 | $this->value_options = $options; 31 | } 32 | 33 | /** 34 | * {@inheritdoc} 35 | */ 36 | public function query() { 37 | $this->ensure_my_table(); 38 | 39 | if ($this->value == 'not_blocking' || $this->value == 'blocking') { 40 | $state_reference_join = new views_join(); 41 | $state_reference_join->table = 'field_data_event_state_reference'; 42 | $state_reference_join->field = 'entity_id'; 43 | $state_reference_join->left_table = 'bat_events'; 44 | $state_reference_join->left_field = 'event_id'; 45 | $state_reference_join->type = 'left'; 46 | 47 | $this->query->add_relationship('field_data_event_state_reference', $state_reference_join, 'bat_events'); 48 | 49 | $state_join = new views_join(); 50 | $state_join->table = 'bat_event_state'; 51 | $state_join->field = 'id'; 52 | $state_join->left_table = 'field_data_event_state_reference'; 53 | $state_join->left_field = 'event_state_reference_state_id'; 54 | $state_join->type = 'left'; 55 | 56 | $this->query->add_relationship('bat_event_state', $state_join, 'field_data_event_state_reference'); 57 | 58 | if ($this->value == 'not_blocking') { 59 | $this->query->add_where(1, 'bat_event_state.blocking', '0', '='); 60 | } 61 | elseif ($this->value == 'blocking') { 62 | $this->query->add_where(1, 'bat_event_state.blocking', '1', '='); 63 | } 64 | } 65 | } 66 | 67 | /** 68 | * {@inheritdoc} 69 | */ 70 | public function admin_summary() { 71 | if ($this->is_a_group()) { 72 | return t('grouped'); 73 | } 74 | if (!empty($this->options['exposed'])) { 75 | return t('exposed'); 76 | } 77 | if (empty($this->value_options)) { 78 | $this->get_value_options(); 79 | } 80 | 81 | return $this->value_options[$this->value]; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /modules/bat_event/views/bat_event_handler_date_field.inc: -------------------------------------------------------------------------------- 1 | get_value($values); 27 | $date = new DateTime($value); 28 | 29 | if ($this->table == 'bat_events' && $this->field == 'end_date') { 30 | // Add a minute to then end date. 31 | $date->add(new DateInterval('PT1M')); 32 | } 33 | 34 | $value = $date->getTimestamp(); 35 | $format = $this->options['date_format']; 36 | $date_formats = array( 37 | 'custom', 38 | 'raw time ago', 39 | 'time ago', 40 | 'raw time span', 41 | 'time span', 42 | 'raw time span', 43 | 'inverse time span', 44 | 'time span', 45 | ); 46 | if (in_array($format, $date_formats)) { 47 | $custom_format = $this->options['custom_date_format']; 48 | } 49 | 50 | if ($value) { 51 | $time_diff = REQUEST_TIME - $value; 52 | switch ($format) { 53 | case 'raw time ago': 54 | return format_interval($time_diff, is_numeric($custom_format) ? $custom_format : 2); 55 | 56 | case 'time ago': 57 | return t('%time ago', array('%time' => format_interval($time_diff, is_numeric($custom_format) ? $custom_format : 2))); 58 | 59 | case 'raw time hence': 60 | return format_interval(-$time_diff, is_numeric($custom_format) ? $custom_format : 2); 61 | 62 | case 'time hence': 63 | return t('%time hence', array('%time' => format_interval(-$time_diff, is_numeric($custom_format) ? $custom_format : 2))); 64 | 65 | case 'raw time span': 66 | return ($time_diff < 0 ? '-' : '') . format_interval(abs($time_diff), is_numeric($custom_format) ? $custom_format : 2); 67 | 68 | case 'inverse time span': 69 | return ($time_diff > 0 ? '-' : '') . format_interval(abs($time_diff), is_numeric($custom_format) ? $custom_format : 2); 70 | 71 | case 'time span': 72 | return t(($time_diff < 0 ? '%time hence' : '%time ago'), array('%time' => format_interval(abs($time_diff), is_numeric($custom_format) ? $custom_format : 2))); 73 | 74 | case 'custom': 75 | if ($custom_format == 'r') { 76 | return format_date($value, $format, $custom_format, NULL, 'en'); 77 | } 78 | return format_date($value, $format, $custom_format); 79 | 80 | default: 81 | return format_date($value, $format); 82 | } 83 | } 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /modules/bat_event/views/bat_event_handler_date_filter.inc: -------------------------------------------------------------------------------- 1 | view); 18 | 19 | $value = date('Y-m-d', intval(strtotime($this->value['value'], $query_substitutions['***CURRENT_TIME***']))); 20 | 21 | $this->query->add_where_expression($this->options['group'], "$field $this->operator '$value'"); 22 | } 23 | 24 | /** 25 | * {@inheritdoc} 26 | */ 27 | public function op_between($field) { 28 | // Use the substitutions to ensure a consistent timestamp. 29 | $query_substitutions = views_views_query_substitutions($this->view); 30 | $a = date('Y-m-d', intval(strtotime($this->value['min'], $query_substitutions['***CURRENT_TIME***']))); 31 | $b = date('Y-m-d', intval(strtotime($this->value['max'], $query_substitutions['***CURRENT_TIME***']))); 32 | 33 | // This is safe because we are manually scrubbing the values. 34 | // It is necessary to do it this way because $a and $b are formulas when using an offset. 35 | $operator = strtoupper($this->operator); 36 | $this->query->add_where_expression($this->options['group'], "$field $operator '$a' AND '$b'"); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /modules/bat_event/views/bat_event_handler_delete_link_field.inc: -------------------------------------------------------------------------------- 1 | additional_fields['type'] = 'type'; 20 | } 21 | 22 | /** 23 | * {@inheritdoc} 24 | */ 25 | public function render($values) { 26 | $type = $values->{$this->aliases['type']}; 27 | 28 | // Creating a dummy unit to check access against. 29 | $dummy_event = bat_event_create(array('type' => $type)); 30 | if (!bat_event_access('delete', $dummy_event)) { 31 | return; 32 | } 33 | 34 | $text = !empty($this->options['text']) ? $this->options['text'] : t('delete'); 35 | $event_id = $values->{$this->aliases['event_id']}; 36 | 37 | return l($text, 'admin/bat/events/event/' . $event_id . '/delete'); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /modules/bat_event/views/bat_event_handler_duration_field.inc: -------------------------------------------------------------------------------- 1 | options['group_type'] != 'group' ? array('function' => $this->options['group_type']) : array(); 24 | $this->query->add_orderby(NULL, NULL, $order, $this->field_alias, $params); 25 | } 26 | 27 | /** 28 | * {@inheritdoc} 29 | */ 30 | public function query() { 31 | $this->ensure_my_table(); 32 | 33 | $this->field_alias = $this->table_alias . '_duration'; 34 | 35 | $alias = $this->field_alias; 36 | $counter = 0; 37 | while (!empty($this->query->fields[$this->field_alias])) { 38 | $this->field_alias = $alias . '_' . ++$counter; 39 | } 40 | 41 | // Add the field. 42 | $params = $this->options['group_type'] != 'group' ? array('function' => $this->options['group_type']) : array(); 43 | $this->query->add_field(NULL, 'TIMESTAMPDIFF(SECOND, ' . $this->table_alias . '.start_date, ' . $this->table_alias . '.end_date)', $this->field_alias, $params); 44 | 45 | $this->add_additional_fields(); 46 | } 47 | 48 | /** 49 | * {@inheritdoc} 50 | */ 51 | public function render($values) { 52 | $value = $values->{$this->field_alias}; 53 | $value += 60; 54 | 55 | return $this->sanitize_value(format_interval($value)); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /modules/bat_event/views/bat_event_handler_edit_link_field.inc: -------------------------------------------------------------------------------- 1 | additional_fields['type'] = 'type'; 20 | } 21 | 22 | /** 23 | * {@inheritdoc} 24 | */ 25 | public function render($values) { 26 | $type = $values->{$this->aliases['type']}; 27 | 28 | // Creating a dummy event to check access against. 29 | $dummy_event = bat_event_create(array('type' => $type)); 30 | if (!bat_event_access('update', $dummy_event)) { 31 | return; 32 | } 33 | $text = !empty($this->options['text']) ? $this->options['text'] : t('edit'); 34 | $event_id = $values->{$this->aliases['event_id']}; 35 | 36 | return l($text, 'admin/bat/events/event/' . $event_id . '/edit'); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /modules/bat_event/views/bat_event_handler_event_operations_field.inc: -------------------------------------------------------------------------------- 1 | additional_fields['event_id'] = 'event_id'; 21 | } 22 | 23 | /** 24 | * {@inheritdoc} 25 | */ 26 | public function query() { 27 | $this->ensure_my_table(); 28 | $this->add_additional_fields(); 29 | } 30 | 31 | /** 32 | * {@inheritdoc} 33 | */ 34 | public function render($values) { 35 | $links = menu_contextual_links('bat_event', 'admin/bat/events/event', array($this->get_value($values, 'event_id'))); 36 | if (!empty($links)) { 37 | return theme('links', array( 38 | 'links' => $links, 39 | 'attributes' => array( 40 | 'class' => array('links', 41 | 'inline', 42 | 'operations', 43 | ), 44 | ), 45 | )); 46 | } 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /modules/bat_event/views/bat_event_handler_event_state_filter.inc: -------------------------------------------------------------------------------- 1 | value_options = $options; 23 | 24 | return $this->value_options; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /modules/bat_event/views/bat_event_handler_event_type_field.inc: -------------------------------------------------------------------------------- 1 | get_value($values)); 26 | return $event_type->label; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /modules/bat_event/views/bat_event_handler_link_field.inc: -------------------------------------------------------------------------------- 1 | additional_fields['event_id'] = 'event_id'; 21 | $this->additional_fields['type'] = 'type'; 22 | } 23 | 24 | /** 25 | * {@inheritdoc} 26 | */ 27 | public function option_definition() { 28 | $options = parent::option_definition(); 29 | 30 | $options['text'] = array('default' => '', 'translatable' => TRUE); 31 | 32 | return $options; 33 | } 34 | 35 | /** 36 | * {@inheritdoc} 37 | */ 38 | public function options_form(&$form, &$form_state) { 39 | parent::options_form($form, $form_state); 40 | 41 | $form['text'] = array( 42 | '#type' => 'textfield', 43 | '#title' => t('Text to display'), 44 | '#default_value' => $this->options['text'], 45 | ); 46 | } 47 | 48 | /** 49 | * {@inheritdoc} 50 | */ 51 | public function query() { 52 | $this->ensure_my_table(); 53 | $this->add_additional_fields(); 54 | } 55 | 56 | /** 57 | * {@inheritdoc} 58 | */ 59 | public function render($values) { 60 | $text = !empty($this->options['text']) ? $this->options['text'] : t('view'); 61 | $event_id = $values->{$this->aliases['event_id']}; 62 | 63 | return l($text, 'event/' . $event_id); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /modules/bat_event/views/bat_event_handler_value_field.inc: -------------------------------------------------------------------------------- 1 | field_alias = 'event_id'; 24 | } 25 | 26 | /** 27 | * {@inheritdoc} 28 | */ 29 | public function render($values) { 30 | $event = bat_event_load($this->get_value($values)); 31 | $event_type = bat_event_type_load($event->type); 32 | 33 | if ($event_type->fixed_event_states) { 34 | $state = bat_event_load_state($event->event_state_reference[LANGUAGE_NONE][0]['state_id']); 35 | 36 | return $state['label']; 37 | } 38 | else { 39 | $field_name = $event_type->default_event_value_field_ids[$event->type]; 40 | 41 | $value = field_get_items('bat_event', $event, $field_name); 42 | $field_view_value = field_view_value('bat_event', $event, $field_name, $value[0]); 43 | 44 | return $field_view_value['#markup']; 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /modules/bat_event_ui/bat_event_ui.info: -------------------------------------------------------------------------------- 1 | name = BAT Event UI 2 | description = Interface support to the BAT Event module. 3 | core = 7.x 4 | 5 | package = BAT 6 | 7 | dependencies[] = bat_event 8 | dependencies[] = bat_fullcalendar 9 | -------------------------------------------------------------------------------- /modules/bat_event_ui/bat_event_ui.install: -------------------------------------------------------------------------------- 1 | 'Calendar', 19 | 'page callback' => 'bat_event_ui_calendar_page', 20 | 'page arguments' => array(3, 4), 21 | 'access arguments' => array('administer calendar events'), 22 | 'type' => MENU_CALLBACK, 23 | 'weight' => 20, 24 | ); 25 | 26 | return $items; 27 | } 28 | 29 | /** 30 | * Callback for admin/bat/calendar. 31 | */ 32 | function bat_event_ui_calendar_page($unit_type, $event_type) { 33 | module_load_include('inc', 'composer_manager', 'composer_manager.admin'); 34 | $composer_manager_installed_packages = composer_manager_installed_packages(); 35 | 36 | if (!isset($composer_manager_installed_packages['roomify/bat'])) { 37 | drupal_set_message(t('Please install the BAT PHP Library. For instructions click here.', array('@link' => 'http://docs.roomify.us/bat/drupal/installation.html#install-bat-php-library')), 'error'); 38 | 39 | return ''; 40 | } 41 | 42 | $ev_type = bat_event_type_load($event_type); 43 | 44 | // Check if current type support this event type. 45 | if ($type = bat_type_load($unit_type)) { 46 | $type_bundle = bat_type_bundle_load($type->type); 47 | 48 | if (is_array($type_bundle->default_event_value_field_ids)) { 49 | if (!(isset($type_bundle->default_event_value_field_ids[$event_type]) && !empty($type_bundle->default_event_value_field_ids[$event_type]))) { 50 | return drupal_not_found(); 51 | } 52 | } 53 | else { 54 | return drupal_not_found(); 55 | } 56 | } 57 | elseif ($unit_type != 'all') { 58 | return drupal_not_found(); 59 | } 60 | 61 | // Check if user has permission to view calendar data for this event type. 62 | if (!user_access('view calendar data for any ' . $ev_type->type . ' event')) { 63 | return drupal_access_denied(); 64 | } 65 | 66 | // Set the page title. 67 | drupal_set_title(t('View Event Data')); 68 | 69 | // Pick what modal style to use. 70 | $calendar_settings['modal_style'] = 'default'; 71 | 72 | if ($type = bat_event_type_load($event_type)) { 73 | $event_granularity = $type->event_granularity; 74 | } 75 | else { 76 | $event_granularity = 'both'; 77 | } 78 | 79 | // All Drupal JS settings inside the batCalendar object. 80 | $fc_user_settings = array( 81 | 'batCalendar' => array( 82 | array( 83 | 'unitType' => $unit_type, 84 | 'eventType' => $event_type, 85 | 'eventGranularity' => $event_granularity, 86 | ), 87 | ), 88 | ); 89 | 90 | $calendar_settings['user_settings'] = $fc_user_settings; 91 | $calendar_settings['calendar_id'] = 'fullcalendar-scheduler'; 92 | 93 | if ($ev_type->fixed_event_states) { 94 | $calendar_settings['class'] = array('fixed_event_states'); 95 | } 96 | else { 97 | $calendar_settings['class'] = array('open_event_states'); 98 | } 99 | 100 | drupal_add_css(drupal_get_path('module', 'bat_event_ui') . '/css/bat_event_ui.css'); 101 | 102 | $render_array = array( 103 | 'event_type_form' => drupal_get_form('bat_event_ui_event_type_form', $unit_type, $event_type), 104 | 'bulk_update_form' => array(), 105 | 'calendar' => array( 106 | '#theme' => 'bat_fullcalendar', 107 | '#calendar_settings' => $calendar_settings, 108 | ), 109 | ); 110 | 111 | if ($ev_type->fixed_event_states) { 112 | $render_array['bulk_update_form'] = drupal_get_form('bat_event_ui_bulk_update_form', $unit_type, $event_type); 113 | } 114 | 115 | $jquery_version = variable_get('jquery_update_jquery_version', '1.10'); 116 | 117 | $admin_theme = variable_get('admin_theme', FALSE); 118 | if (theme_get_setting('jquery_update_jquery_version', $admin_theme) != '') { 119 | $jquery_version = theme_get_setting('jquery_update_jquery_version', $admin_theme); 120 | } 121 | 122 | if (function_exists('jquery_update_get_versions')) { 123 | $jquery_versions = array_keys(jquery_update_get_versions()); 124 | } 125 | else { 126 | $jquery_versions = array('1.5', '1.6', '1.7', '1.8', '1.9', '1.10'); 127 | } 128 | 129 | if ($jquery_version == 'default' || array_search($jquery_version, $jquery_versions) < array_search('1.8', $jquery_versions)) { 130 | drupal_set_message(t('Please ensure that you are using version 1.8 or greater of the jQuery library (configure)', array('@link' => url('admin/config/development/jquery_update'))), 'error'); 131 | } 132 | 133 | return $render_array; 134 | } 135 | 136 | /** 137 | * Bulk update form. 138 | */ 139 | function bat_event_ui_bulk_update_form($form, &$form_state, $unit_type, $event_type) { 140 | $form['bulk_update'] = array( 141 | '#type' => 'fieldset', 142 | '#title' => t('Update event state'), 143 | '#collapsible' => TRUE, 144 | '#collapsed' => TRUE, 145 | ); 146 | 147 | $form['bulk_update']['event_type'] = array( 148 | '#type' => 'hidden', 149 | '#value' => $event_type, 150 | ); 151 | 152 | if ($unit_type == 'all') { 153 | $types = bat_unit_get_types(NULL, TRUE); 154 | 155 | $types_options = array(); 156 | 157 | foreach ($types as $type) { 158 | $type_bundle = bat_type_bundle_load($type->type); 159 | 160 | if (is_array($type_bundle->default_event_value_field_ids)) { 161 | if (isset($type_bundle->default_event_value_field_ids[$event_type]) && !empty($type_bundle->default_event_value_field_ids[$event_type])) { 162 | $types_options[$type->type_id] = $type->name; 163 | } 164 | } 165 | } 166 | 167 | $form['bulk_update']['type'] = array( 168 | '#type' => 'select', 169 | '#title' => t('Type'), 170 | '#options' => $types_options, 171 | '#required' => TRUE, 172 | ); 173 | } 174 | else { 175 | $form['bulk_update']['type'] = array( 176 | '#type' => 'hidden', 177 | '#value' => $unit_type, 178 | ); 179 | } 180 | 181 | $form['bulk_update'] += bat_date_range_fields(); 182 | 183 | $form['bulk_update']['state'] = array( 184 | '#type' => 'select', 185 | '#title' => t('State'), 186 | '#options' => bat_unit_state_options($event_type, array('blocking' => 0)), 187 | '#required' => TRUE, 188 | ); 189 | 190 | $form['bulk_update']['submit'] = array( 191 | '#type' => 'submit', 192 | '#value' => t('Update'), 193 | ); 194 | 195 | return $form; 196 | } 197 | 198 | /** 199 | * Submit callback for bat_event_ui_bulk_update_form form. 200 | */ 201 | function bat_event_ui_bulk_update_form_submit($form, &$form_state) { 202 | $values = $form_state['values']; 203 | 204 | $start_date = new DateTime($values['bat_start_date']); 205 | $end_date = new DateTime($values['bat_end_date']); 206 | $end_date->sub(new DateInterval('PT1M')); 207 | 208 | $event_type = $values['event_type']; 209 | $event_state = $values['state']; 210 | $type = bat_type_load($values['type']); 211 | 212 | $units = bat_unit_load_multiple(FALSE, array('type_id' => $type->type_id)); 213 | 214 | foreach ($units as $unit) { 215 | $event = bat_event_create(array( 216 | 'type' => $event_type, 217 | 'start_date' => $start_date->format('Y-m-d H:i:s'), 218 | 'end_date' => $end_date->format('Y-m-d H:i:s'), 219 | 'uid' => $type->uid, 220 | 'created' => REQUEST_TIME, 221 | )); 222 | 223 | $event->event_bat_unit_reference[LANGUAGE_NONE][0]['target_id'] = $unit->unit_id; 224 | $event->event_state_reference[LANGUAGE_NONE][0]['state_id'] = $event_state; 225 | 226 | $event->save(); 227 | } 228 | } 229 | 230 | /** 231 | * Form - "Event type" and "Unit type" to shows in the calendar view. 232 | */ 233 | function bat_event_ui_event_type_form($form, &$form_state, $unit_type, $event_type) { 234 | if (isset($form_state['values']['event_types'])) { 235 | $event_type = $form_state['values']['event_types']; 236 | } 237 | 238 | $event_types = bat_event_get_types(); 239 | foreach ($event_types as $ev_type) { 240 | if (user_access('view calendar data for any ' . $ev_type->type . ' event')) { 241 | $event_types_options[$ev_type->type] = $ev_type->label; 242 | } 243 | } 244 | 245 | $form['event_types'] = array( 246 | '#type' => 'select', 247 | '#title' => 'Event type', 248 | '#options' => $event_types_options, 249 | '#default_value' => $event_type, 250 | '#ajax' => array( 251 | 'callback' => 'bat_event_ui_event_type_form_callback', 252 | 'wrapper' => 'unit-type-wrapper', 253 | ), 254 | ); 255 | 256 | $types = bat_unit_get_types(); 257 | if (!empty($types)) { 258 | $types_options = array( 259 | 'all' => t('All'), 260 | ); 261 | 262 | foreach ($types as $type) { 263 | $type_bundle = bat_type_bundle_load($type->type); 264 | 265 | if (is_array($type_bundle->default_event_value_field_ids)) { 266 | if (isset($type_bundle->default_event_value_field_ids[$event_type]) && !empty($type_bundle->default_event_value_field_ids[$event_type])) { 267 | $types_options[$type->type_id] = $type->name; 268 | } 269 | } 270 | } 271 | 272 | $form['unit_type'] = array( 273 | '#type' => 'select', 274 | '#title' => 'Unit type', 275 | '#options' => $types_options, 276 | '#default_value' => $unit_type, 277 | '#prefix' => '
', 278 | '#suffix' => '
', 279 | ); 280 | } 281 | 282 | $form['submit'] = array( 283 | '#type' => 'submit', 284 | '#value' => 'Change', 285 | ); 286 | 287 | return $form; 288 | } 289 | 290 | /** 291 | * Ajax callback for bat_event_ui_event_type_form form. 292 | */ 293 | function bat_event_ui_event_type_form_callback($form, &$form_state) { 294 | return $form['unit_type']; 295 | } 296 | 297 | /** 298 | * Submit callback for bat_event_ui_event_type_form form. 299 | */ 300 | function bat_event_ui_event_type_form_submit($form, &$form_state) { 301 | $type = $form_state['values']['unit_type']; 302 | $event_type = $form_state['values']['event_types']; 303 | 304 | $form_state['redirect'] = 'admin/bat/calendar/' . $type . '/' . $event_type; 305 | } 306 | -------------------------------------------------------------------------------- /modules/bat_event_ui/css/bat_event_ui.css: -------------------------------------------------------------------------------- 1 | /* Ensure that datepicker is visible in the modal popup. */ 2 | #ui-datepicker-div { 3 | z-index: 1005 !important; 4 | } 5 | 6 | #bat-event-ui-event-type-form { 7 | display: inline-block; 8 | } 9 | #bat-event-ui-event-type-form .form-item-event-types, 10 | #bat-event-ui-event-type-form #unit-type-wrapper { 11 | float: left; 12 | margin-right: 10px; 13 | } 14 | 15 | #bat-event-ui-event-type-form input[type="submit"] { 16 | margin-top: 1.6em; 17 | } 18 | 19 | #bat-event-ui-bulk-update-form .bat-date-range, 20 | #bat-event-ui-bulk-update-form .form-type-select { 21 | float: left; 22 | margin: 0 20px 0 0; 23 | clear: none; 24 | padding: 0; 25 | } 26 | 27 | #bat-event-ui-bulk-update-form input[type="submit"] { 28 | margin-top: 1.1em; 29 | } 30 | -------------------------------------------------------------------------------- /modules/bat_facets/README.md: -------------------------------------------------------------------------------- 1 | # BAT Facet 2 | 3 | This module allows you to incorporate availability search for Units managed by BAT into any a view using faceted search. 4 | 5 | (Yup - that's right - this *is* awesome *and* a game-changer. We thought you'd like it too...) 6 | 7 | We provide documentation on how to use this module here: http://docs.roomify.us/bat/drupal/search_availability.html 8 | -------------------------------------------------------------------------------- /modules/bat_facets/bat_facets.facetapi.inc: -------------------------------------------------------------------------------- 1 | 'bat_state', 19 | 'label' => t('Bat State'), 20 | 'description' => t('Bat Availability State facet'), 21 | 'field' => 'bat_state', 22 | 'field alias' => 'bat_state', 23 | 'field api name' => FALSE, 24 | 'field api bundles' => array(), 25 | 'query types' => array('term'), 26 | 'dependency plugins' => array('role'), 27 | 'default widget' => 'bat_state', 28 | 'allowed operators' => array(FACETAPI_OPERATOR_AND => TRUE, FACETAPI_OPERATOR_OR => FALSE), 29 | 'facet missing allowed' => FALSE, 30 | 'facet mincount allowed' => FALSE, 31 | 'weight' => 0, 32 | 'map callback' => FALSE, 33 | 'map options' => array(), 34 | 'hierarchy callback' => FALSE, 35 | 'values callback' => FALSE, 36 | 'min callback' => FALSE, 37 | 'max callback' => FALSE, 38 | ); 39 | } 40 | 41 | return $facets; 42 | } 43 | 44 | /** 45 | * Implements hook_facetapi_widgets(). 46 | */ 47 | function bat_facets_facetapi_widgets() { 48 | return array( 49 | 'bat_state' => array( 50 | 'handler' => array( 51 | 'label' => t('Bat State'), 52 | 'class' => 'BatStateWidget', 53 | 'query types' => array('term'), 54 | ), 55 | ), 56 | ); 57 | } 58 | -------------------------------------------------------------------------------- /modules/bat_facets/bat_facets.info: -------------------------------------------------------------------------------- 1 | name = BAT Facets 2 | description = Facet API facets for BAT. 3 | core = 7.x 4 | 5 | package = BAT 6 | 7 | dependencies[] = bat_event 8 | dependencies[] = facetapi 9 | dependencies[] = search_api 10 | dependencies[] = search_api_facetapi 11 | 12 | files[] = src/BatStateSearchAPIQuery.php 13 | files[] = src/BatStateWidget.php 14 | -------------------------------------------------------------------------------- /modules/bat_facets/bat_facets.install: -------------------------------------------------------------------------------- 1 | '1'); 18 | } 19 | } 20 | 21 | /** 22 | * Implements hook_facetapi_facet_info_alter(). 23 | */ 24 | function bat_facets_facetapi_facet_info_alter(array &$facet_info, array $searcher_info) { 25 | switch ($searcher_info['adapter']) { 26 | case 'search_api': 27 | foreach ($facet_info as $name => $info) { 28 | if ($name == 'type_id') { 29 | $facet_info[$name]['query types'][] = 'bat_state'; 30 | } 31 | } 32 | break; 33 | } 34 | } 35 | 36 | /** 37 | * Callback for facet availability form. 38 | */ 39 | function bat_facets_availability($form, &$form_state, $elements) { 40 | $params = drupal_get_query_parameters(); 41 | $now = date_create(); 42 | 43 | // Year defaults to current year, although we are not filtering yet. 44 | $default_year = $now->format('Y'); 45 | 46 | // Month doesn't have a default selection. 47 | $default_month = ''; 48 | 49 | $form['container'] = array( 50 | '#type' => 'container', 51 | '#attributes' => array( 52 | 'class' => array('container-inline'), 53 | ), 54 | ); 55 | 56 | if (isset($params['bat_start_date']) && !empty($params['bat_start_date'])) { 57 | $start_date = new DateTime($params['bat_start_date']); 58 | $arrival = $start_date->format('Y-m-d H:i'); 59 | } 60 | if (isset($params['bat_end_date']) && !empty($params['bat_end_date'])) { 61 | $end_date = new DateTime($params['bat_end_date']); 62 | $departure = $end_date->format('Y-m-d H:i'); 63 | } 64 | 65 | // Create unique ids and selectors for each picker. 66 | $start_date_id = drupal_html_id('datepicker-start-date'); 67 | $start_date_selector = '#' . $start_date_id . ' .form-text'; 68 | 69 | $end_date_id = drupal_html_id('datepicker-end-date'); 70 | $end_date_selector = '#' . $start_date_id . ' .form-text'; 71 | 72 | // Specify the default datepicker parameters (see date_popup_element_info()) 73 | $datepicker_options = array( 74 | // Limit bookings to X days in advance, depending on the 75 | // chosen configuration in your BAT installation, defaults 76 | // to the current day. 77 | 'minDate' => '+' . variable_get('bat_event_start_date', 0) . 'd', 78 | ); 79 | 80 | $form['container']['arrival'] = array( 81 | '#type' => 'date_popup', 82 | '#description' => '', 83 | '#date_format' => variable_get('bat_date_format', 'Y-m-d H:i'), 84 | '#default_value' => isset($arrival) ? $arrival : '', 85 | '#datepicker_options' => array_merge($datepicker_options, array('endDateSelector' => $end_date_selector)), 86 | '#required' => TRUE, 87 | ); 88 | 89 | $form['container']['departure'] = array( 90 | '#type' => 'date_popup', 91 | '#description' => '', 92 | '#date_format' => variable_get('bat_date_format', 'Y-m-d H:i'), 93 | '#default_value' => isset($departure) ? $departure : '', 94 | '#datepicker_options' => array_merge($datepicker_options, array('startDateSelector' => $start_date_selector)), 95 | '#required' => TRUE, 96 | '#attached' => array( 97 | 'js' => array( 98 | drupal_get_path('module', 'bat') . '/js/bat_date_popup.js', 99 | array( 100 | 'data' => array( 101 | 'bat' => array( 102 | 'batBookingStartDay' => variable_get('bat_event_start_date', 0), 103 | 'batDateFormat' => 'dd/mm/yy', 104 | 105 | // Here we create a listing of all datepickers registered on the 106 | // current page. This is available for use in your own custom 107 | // jQuery scripts as Drupal.settings.bat.datepickers. 108 | 'datepickers' => array( 109 | $start_date_selector => array( 110 | 'endDateSelector' => $end_date_selector, 111 | ), 112 | ), 113 | ), 114 | ), 115 | 'type' => 'setting', 116 | ), 117 | ), 118 | ), 119 | ); 120 | 121 | $form['container']['submit'] = array( 122 | '#type' => 'submit', 123 | '#value' => 'Search', 124 | ); 125 | 126 | return $form; 127 | } 128 | 129 | /** 130 | * Submit handler. 131 | */ 132 | function bat_facets_availability_submit($form, &$form_state) { 133 | $form_state['redirect'] = array( 134 | $_GET['q'], 135 | array( 136 | 'query' => array( 137 | 'bat_start_date' => $form_state['values']['arrival'], 138 | 'bat_end_date' => $form_state['values']['departure'] 139 | ) 140 | ) 141 | ); 142 | } 143 | 144 | /** 145 | * Implements hook_search_api_query_alter(). 146 | * 147 | * @param SearchApiQueryInterface $query 148 | * The search query being executed. 149 | */ 150 | function bat_facets_search_api_query_alter($query) { 151 | if ($query->getIndex()->getEntityType()) { 152 | $info = entity_get_info($query->getIndex()->getEntityType()); 153 | 154 | // Only modify the query if this query is against bat units. 155 | if ($info['base table'] == 'bat_types') { 156 | // Get this widget's settings. 157 | $index = $query->getIndex(); 158 | $facets = facetapi_get_enabled_facets('search_api@' . $index->machine_name); 159 | $adapter = facetapi_adapter_load('search_api@' . $index->machine_name); 160 | $realm = facetapi_realm_load('block'); 161 | if (isset($facets['type_id'])) { 162 | $settings = $adapter->getFacetSettings($facets['type_id'], $realm); 163 | 164 | // Get URL parameters. 165 | $params = drupal_get_query_parameters(); 166 | 167 | // See if we have dates to search. 168 | if (isset($params['bat_start_date']) && 169 | !empty($params['bat_start_date']) && 170 | isset($params['bat_end_date']) && 171 | !empty($params['bat_end_date'])) { 172 | $start_date = new DateTime($params['bat_start_date']); 173 | $end_date = new DateTime($params['bat_end_date']); 174 | // Remove a minute because BAT considers as included. 175 | $end_date->sub(new DateInterval('PT1M')); 176 | 177 | $event_type = $settings->settings['event_type']; 178 | 179 | $state_store = new DrupalDBStore($event_type, DrupalDBStore::BAT_STATE, bat_get_db_prefix()); 180 | 181 | $valid_states = $settings->settings['states']; 182 | 183 | $valid_type_ids = array(); 184 | 185 | // We need to narrow the query to all Types with Units that have the 186 | // requested state over the requested dates. 187 | // First, we retrieve all types. 188 | // TODO: narrow this to only the types already being searched for. 189 | $type_ids = bat_type_ids(); 190 | 191 | $units = array(); 192 | foreach ($type_ids as $type_id => $name) { 193 | // Get the units of this type. 194 | $drupal_units = bat_unit_load_multiple(FALSE, array('type_id' => $type_id)); 195 | $bat_units = array(); 196 | foreach ($drupal_units as $unit_id => $unit) { 197 | $bat_units[] = new Unit($unit_id, $unit->getEventDefaultValue($event_type)); 198 | } 199 | 200 | // If this type has associated units, see if any of its units are 201 | // in the states being searched for over the search period. 202 | if (count($bat_units)) { 203 | $calendar = new Calendar($bat_units, $state_store); 204 | 205 | $constraints = array(); 206 | foreach (bat_event_constraints_get_info() as $constraint) { 207 | $constraints[] = $constraint['constraint']; 208 | } 209 | 210 | $response = $calendar->getMatchingUnits($start_date, $end_date, $valid_states, $constraints, TRUE); 211 | $valid_unit_ids = array_keys($response->getIncluded()); 212 | 213 | // If there are available units, mark this type as valid. 214 | if (count($valid_unit_ids)) { 215 | $valid_type_ids[] = $type_id; 216 | } 217 | 218 | } 219 | } 220 | 221 | $context = array( 222 | 'types_before_search' => $type_ids, 223 | 'start_date' => $start_date, 224 | 'end_date' => $end_date, 225 | 'event_type' => $event_type, 226 | 'valid_states' => $valid_states, 227 | ); 228 | 229 | drupal_alter('bat_facets_search_results', $valid_type_ids, $context); 230 | 231 | // If no types are available, zero out results. 232 | if (empty($valid_type_ids)) { 233 | $query->condition($info['entity keys']['id'], 1, '<'); 234 | } 235 | else { 236 | // Limit the search API query to entity ids with availability. 237 | $query->condition($info['entity keys']['id'], $valid_type_ids, 'IN'); 238 | } 239 | } 240 | } 241 | } 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /modules/bat_facets/src/BatStateSearchAPIQuery.php: -------------------------------------------------------------------------------- 1 | build[$this->facet['field alias']]; 17 | $elements = drupal_get_form('bat_facets_availability', $elements); 18 | } 19 | 20 | /** 21 | * Overrides FacetapiWidget::settingsForm(). 22 | */ 23 | public function settingsForm(&$form, &$form_state) { 24 | parent::settingsForm($form, $form_state); 25 | $settings = $this->settings->settings; 26 | 27 | unset($form['widget']['widget_settings']['links'][$this->id]['soft_limit']); 28 | unset($form['widget']['widget_settings']['links'][$this->id]['show_expanded']); 29 | unset($form['widget']['widget_settings'][$this->id]['facet_more_text']); 30 | 31 | $event_types_options = array(); 32 | $event_types = bat_event_get_types(); 33 | foreach ($event_types as $event_type) { 34 | $event_types_options[$event_type->type] = $event_type->label; 35 | } 36 | 37 | $form['widget']['widget_settings']['bat_facets']['#prefix'] = '
'; 38 | $form['widget']['widget_settings']['bat_facets']['#suffix'] = '
'; 39 | 40 | $form['widget']['widget_settings']['bat_facets'][$this->id]['event_type'] = array( 41 | '#type' => 'select', 42 | '#title' => t('Event type'), 43 | '#options' => $event_types_options, 44 | '#default_value' => isset($settings['event_type']) ? $settings['event_type'] : array(), 45 | '#ajax' => array( 46 | 'callback' => 'bat_facets_event_type_change', 47 | 'wrapper' => 'bat-facet', 48 | ), 49 | '#states' => array( 50 | 'visible' => array( 51 | 'select[name="widget"]' => array('value' => $this->id), 52 | ), 53 | ), 54 | ); 55 | 56 | if (isset($form_state['values']['event_type'])) { 57 | $ev_type = $form_state['values']['event_type']; 58 | } 59 | else { 60 | $ev_types = array_keys($event_types_options); 61 | $ev_type = reset($ev_types); 62 | } 63 | 64 | if ($event_types[$ev_type]->fixed_event_states) { 65 | $state_options = bat_unit_state_options($ev_type); 66 | 67 | $form['widget']['widget_settings']['bat_facets'][$this->id]['states'] = array( 68 | '#type' => 'select', 69 | '#title' => t('Event States'), 70 | '#options' => $state_options, 71 | '#multiple' => TRUE, 72 | '#default_value' => isset($settings['states']) ? $settings['states'] : array(), 73 | '#states' => array( 74 | 'visible' => array( 75 | 'select[name="widget"]' => array('value' => $this->id), 76 | ), 77 | ), 78 | ); 79 | } 80 | else { 81 | $form['widget']['widget_settings']['bat_facets'][$this->id]['first_state'] = array( 82 | '#type' => 'textfield', 83 | '#title' => t('First state'), 84 | '#size' => 10, 85 | '#prefix' => '
', 86 | '#default_value' => isset($settings['states']) ? $settings['first_state'] : '', 87 | ); 88 | 89 | $form['widget']['widget_settings']['bat_facets'][$this->id]['second_state'] = array( 90 | '#type' => 'textfield', 91 | '#title' => t('Second state'), 92 | '#size' => 10, 93 | '#suffix' => '
', 94 | '#default_value' => isset($settings['states']) ? $settings['second_state'] : '', 95 | ); 96 | } 97 | } 98 | 99 | } 100 | 101 | /** 102 | * Ajax callback when change 'Event type'. 103 | */ 104 | function bat_facets_event_type_change($form, &$form_state) { 105 | return $form['widget']['widget_settings']['bat_facets']; 106 | } 107 | -------------------------------------------------------------------------------- /modules/bat_fullcalendar/bat_fullcalendar.api.php: -------------------------------------------------------------------------------- 1 | $t('FullCalendar'), 27 | 'description' => implode('
', $description), 28 | 'value' => $t('FullCalendar Scheduler Libraries Missing'), 29 | 'severity' => REQUIREMENT_ERROR, 30 | ); 31 | } 32 | else { 33 | $requirements['fullcalendar'] = array( 34 | 'title' => $t('FullCalendar'), 35 | 'description' => $t('The FullCalendar, FullCalendar Scheduler and the Moment Library are installed'), 36 | 'value' => $t('FullCalendar, Scheduler and Moment Installed'), 37 | 'severity' => REQUIREMENT_OK, 38 | ); 39 | } 40 | 41 | $jquery_version = variable_get('jquery_update_jquery_version', '1.10'); 42 | 43 | $admin_theme = variable_get('admin_theme', FALSE); 44 | if (theme_get_setting('jquery_update_jquery_version', $admin_theme) != '') { 45 | $jquery_version = theme_get_setting('jquery_update_jquery_version', $admin_theme); 46 | } 47 | 48 | if (function_exists('jquery_update_get_versions')) { 49 | $jquery_versions = array_keys(jquery_update_get_versions()); 50 | } 51 | else { 52 | $jquery_versions = array('1.5', '1.6', '1.7', '1.8', '1.9', '1.10'); 53 | } 54 | 55 | if ($jquery_version == 'default' || array_search($jquery_version, $jquery_versions) < array_search('1.8', $jquery_versions)) { 56 | $requirements['bat_jquery'] = array( 57 | 'title' => $t('BAT jQuery Requirements'), 58 | 'description' => $t('Please ensure that you are using version 1.8 or greater of the jQuery library (configure)', array('@link' => url('admin/config/development/jquery_update'))), 59 | 'value' => ($jquery_version == 'default') ? '1.4' : $jquery_version, 60 | 'severity' => REQUIREMENT_ERROR, 61 | ); 62 | } 63 | else { 64 | $requirements['bat_jquery'] = array( 65 | 'title' => $t('BAT jQuery Requirements'), 66 | 'value' => $jquery_version, 67 | 'severity' => REQUIREMENT_OK, 68 | ); 69 | } 70 | } 71 | 72 | return $requirements; 73 | } 74 | -------------------------------------------------------------------------------- /modules/bat_fullcalendar/css/bat_fullcalendar_timeline.css: -------------------------------------------------------------------------------- 1 | .calendar-set { 2 | margin-bottom: 15px; 3 | } 4 | 5 | .fc-timeline-event { 6 | height: 120%; 7 | } 8 | 9 | .open_event_states .fc-bgevent { 10 | opacity: 0.8; 11 | } 12 | 13 | .fc-ltr .fc-timeline-event .fc-title { 14 | display: inline-block; 15 | } 16 | -------------------------------------------------------------------------------- /modules/bat_fullcalendar/css/bat_modal.css: -------------------------------------------------------------------------------- 1 | /* When modals are enabled, add hover effect to calendar. */ 2 | .fc-event:hover { 3 | cursor: pointer; 4 | } 5 | .fc-widget-content:hover { 6 | cursor: default; 7 | background: rgba(230,230,230, 0.2); 8 | } 9 | 10 | /* Make modals responsive. */ 11 | .page-admin-bat #modalContent, 12 | .page-admin-bat #modalContent .ctools-modal-content, 13 | .page-admin-bat #modalContent .ctools-modal-content .modal-content { 14 | max-width: 100% !important; 15 | } 16 | 17 | /* Account for the extra div coming from ctools_modal_form_render() */ 18 | .page-admin-bat .messages div.messages { 19 | background: none; 20 | border: none; 21 | margin: 0; 22 | padding: 0; 23 | -webkit-border-radius: 0; 24 | -moz-border-radius: 0; 25 | border-radius: 0; 26 | } 27 | .page-admin-bat .ctools-modal-content { 28 | font-size: 12px; 29 | border: solid 1px #ddd; 30 | -webkit-border-radius: 0.5em; 31 | -moz-border-radius: 0.5em; 32 | border-radius: 0.5em; 33 | -webkit-box-shadow: -1em 1em 1em rgba(0, 0, 0, 0.5); 34 | -moz-box-shadow: -1em 1em 1em rgba(0, 0, 0, 0.5); 35 | box-shadow: -1em 1em 1em rgba(0, 0, 0, 0.5); 36 | background: #fff; 37 | height: 100% !important; 38 | } 39 | .page-admin-bat .ctools-modal-content .modal-header { 40 | background: #fff url('../images/bg-shade-light.png') repeat-x bottom left; 41 | color: #777; 42 | display: block; 43 | font-weight: 700; 44 | letter-spacing: normal; 45 | padding: 0.25em 1em; 46 | -webkit-border-radius: 0.5em 0.5em 0 0; 47 | -moz-border-radius: 0.5em 0.5em 0 0; 48 | border-radius: 0.5em 0.5em 0 0; 49 | } 50 | .page-admin-bat .ctools-modal-content .modal-title { 51 | font-size: 120%; 52 | font-weight: bold; 53 | text-shadow: #fff 1px 1px 1px; 54 | color: #555; 55 | } 56 | .page-admin-bat .ctools-modal-content .modal-content { 57 | width: 92% !important; 58 | padding: 20px 4%; 59 | -webkit-box-sizing: content-box; 60 | -moz-box-sizing: content-box; 61 | box-sizing: content-box; 62 | height: 100% !important; 63 | min-height: 475px !important; 64 | } 65 | .page-admin-bat .ctools-modal-content a.close { 66 | color: #666; 67 | font-weight: normal; 68 | padding-left: 1.6em; 69 | background: url('../images/close.png') no-repeat 0 50%; 70 | } 71 | .page-admin-bat .ctools-modal-content a.close img { 72 | display: none; 73 | } 74 | 75 | /** modal forms CSS **/ 76 | .page-admin-bat .ctools-modal-content .form-item label { 77 | width: 100%; 78 | float: none; 79 | clear: both; 80 | } 81 | .page-admin-bat .ctools-modal-content .resizable-textarea { 82 | width: 100%; 83 | margin-left: 0; 84 | margin-right: 0; 85 | } 86 | 87 | /* Override unit form layouts when they appear inside CTools modals. */ 88 | .page-admin-bat .modal-content .bat-management-form fieldset, 89 | .page-admin-bat .modal-content .bat-management-form .form-wrapper { 90 | float: none !important; 91 | width: 100% !important; 92 | max-width: 100% !important; 93 | margin-right: 0 !important; 94 | } 95 | .page-admin-bat .modal-content .bat-management-form .form-item label { 96 | float: none; 97 | width: auto; 98 | } 99 | .page-admin-bat .modal-content .bat-management-form .form-type-select, 100 | .page-admin-bat .modal-content .bat-management-form .form-item-operation, 101 | .page-admin-bat .modal-content .bat-management-form .form-item-amount, 102 | .page-admin-bat .modal-content .bat-management-form .form-actions { 103 | float: none; 104 | margin: 0; 105 | clear: both; 106 | } 107 | .page-admin-bat .modal-content .bat-management-form .bat-date-range { 108 | float: left !important; 109 | margin-right: 4% !important; 110 | width: 45% !important; 111 | max-width: 45% !important; 112 | min-width: 125px !important; 113 | clear: none; 114 | } 115 | -------------------------------------------------------------------------------- /modules/bat_fullcalendar/css/fullcalendar.theme.css: -------------------------------------------------------------------------------- 1 | /* Header styles */ 2 | .fc-header-title { 3 | text-align: center; 4 | } 5 | .fc-header-title h2 { 6 | font-size: 18px; 7 | font-weight: normal; 8 | margin: 0; 9 | } 10 | .fc-header { 11 | border: none; 12 | } 13 | .fc-header tbody, 14 | .fc-header tr, 15 | .fc-header th, 16 | .fc-header td { 17 | background-color: transparent; 18 | border: none !important; 19 | } 20 | .fc-header td { 21 | padding: 8px 0; 22 | } 23 | .fc-header .fc-state-default, 24 | .fc-header .ui-state-default { 25 | margin-bottom: 0; 26 | } 27 | -------------------------------------------------------------------------------- /modules/bat_fullcalendar/images/bg-shade-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Roomify/bat_drupal/734563116cdc551aecfb99acffc45a92b8c6120a/modules/bat_fullcalendar/images/bg-shade-light.png -------------------------------------------------------------------------------- /modules/bat_fullcalendar/images/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Roomify/bat_drupal/734563116cdc551aecfb99acffc45a92b8c6120a/modules/bat_fullcalendar/images/close.png -------------------------------------------------------------------------------- /modules/bat_fullcalendar/src/FullCalendarFixedStateEventFormatter.php: -------------------------------------------------------------------------------- 1 | event_type = $event_type; 35 | $this->background = $background; 36 | } 37 | 38 | /** 39 | * {@inheritdoc} 40 | */ 41 | public function format(EventInterface $event) { 42 | $editable = FALSE; 43 | $context = array(); 44 | 45 | // Load the unit entity from Drupal. 46 | $bat_unit = bat_unit_load($event->getUnitId()); 47 | 48 | // Get the unit entity default value. 49 | $default_value = $bat_unit->getEventDefaultValue($this->event_type->type); 50 | 51 | // Get the default state info which will provide the default value for formatting. 52 | $state_info = bat_event_load_state($default_value); 53 | 54 | // However if the event is in the database, then load the actual event and get its value. 55 | if ($event->getValue()) { 56 | // Load the event from the database to get the actual state and load that info. 57 | $bat_event = bat_event_load($event->getValue()); 58 | $temp_value = $bat_event->getEventValue(); 59 | $state_info = bat_event_load_state($bat_event->getEventValue()); 60 | 61 | // Set calendar label from event. 62 | $state_info['calendar_label'] = $bat_event->label(); 63 | 64 | if (bat_event_access('update', $bat_event)) { 65 | $editable = TRUE; 66 | } 67 | 68 | $context['bat_event'] = $bat_event; 69 | $context['state_info'] = $state_info; 70 | } 71 | 72 | $formatted_event = array( 73 | 'start' => $event->startYear() . '-' . $event->startMonth('m') . '-' . $event->startDay('d') . 'T' . $event->startHour('H') . ':' . $event->startMinute() . ':00', 74 | 'end' => $event->endYear() . '-' . $event->endMonth('m') . '-' . $event->endDay('d') . 'T' . $event->endHour('H') . ':' . $event->endMinute() . ':00', 75 | 'title' => $state_info['calendar_label'], 76 | 'color' => $state_info['color'], 77 | 'blocking' => 1, 78 | 'fixed' => 1, 79 | 'editable' => $editable, 80 | ); 81 | 82 | // Render non blocking events in the background. 83 | if ($state_info['blocking'] == 0) { 84 | if ($this->background) { 85 | $formatted_event['rendering'] = 'background'; 86 | } 87 | $formatted_event['blocking'] = 0; 88 | } 89 | 90 | $formatted_event['type'] = $this->event_type->type; 91 | 92 | // Allow other modules to alter the event data. 93 | drupal_alter('bat_fullcalendar_formatted_event', $formatted_event, $context); 94 | 95 | return $formatted_event; 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /modules/bat_fullcalendar/src/FullCalendarOpenStateEventFormatter.php: -------------------------------------------------------------------------------- 1 | event_type = $event_type; 35 | $this->background = $background; 36 | } 37 | 38 | /** 39 | * {@inheritdoc} 40 | */ 41 | public function format(EventInterface $event) { 42 | $editable = FALSE; 43 | $context = array(); 44 | 45 | // Load the target entity from Drupal. 46 | $target_entity = entity_load_single($this->event_type->target_entity_type, $event->getUnitId()); 47 | 48 | // Get the target entity default value. 49 | $default_value = $target_entity->getEventDefaultValue($this->event_type->type); 50 | 51 | if ($event->getValue()) { 52 | $bat_event = bat_event_load($event->getValue()); 53 | 54 | // Change the default value to the one that the event actually stores in the entity. 55 | $default_value = $bat_event->getEventValue(); 56 | 57 | if (bat_event_access('update', $bat_event)) { 58 | $editable = TRUE; 59 | } 60 | 61 | $context['bat_event'] = $bat_event; 62 | } 63 | 64 | $formatted_event = array( 65 | 'start' => $event->startYear() . '-' . $event->startMonth('m') . '-' . $event->startDay('d') . 'T' . $event->startHour('H') . ':' . $event->startMinute() . ':00', 66 | 'end' => $event->endYear() . '-' . $event->endMonth('m') . '-' . $event->endDay('d') . 'T' . $event->endHour('H') . ':' . $event->endMinute() . ':00', 67 | 'title' => $target_entity->formatEventValue($this->event_type->type, $default_value), 68 | 'blocking' => 0, 69 | 'fixed' => 0, 70 | 'editable' => $editable, 71 | ); 72 | 73 | if ($event->getValue() == 0) { 74 | $formatted_event['color'] = variable_get('bat_open_state_default_zero_color', '#F3C776'); 75 | } 76 | else { 77 | $formatted_event['color'] = variable_get('bat_open_state_default_color', '#9DDC9D'); 78 | } 79 | 80 | if ($this->background) { 81 | $formatted_event['rendering'] = 'background'; 82 | } 83 | 84 | $formatted_event['type'] = $this->event_type->type; 85 | 86 | // Allow other modules to alter the event data. 87 | drupal_alter('bat_fullcalendar_formatted_event', $formatted_event, $context); 88 | 89 | return $formatted_event; 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /modules/bat_options/bat_options.api.php: -------------------------------------------------------------------------------- 1 | array( 15 | 'name' => array( 16 | 'type' => 'varchar', 17 | 'length' => 255, 18 | 'not null' => TRUE, 19 | ), 20 | 'quantity' => array( 21 | 'type' => 'int', 22 | 'not null' => FALSE, 23 | ), 24 | 'operation' => array( 25 | 'type' => 'varchar', 26 | 'length' => 255, 27 | 'not null' => FALSE, 28 | ), 29 | 'value' => array( 30 | 'type' => 'float', 31 | 'not null' => FALSE, 32 | ), 33 | 'type' => array( 34 | 'type' => 'varchar', 35 | 'length' => 255, 36 | 'not null' => FALSE, 37 | ), 38 | ), 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /modules/bat_options/css/bat_options_widget.css: -------------------------------------------------------------------------------- 1 | .field-widget-bat-options-combined .field-multiple-table .form-item { 2 | float: left; 3 | margin-right: 20px; 4 | } 5 | 6 | .field-widget-bat-options-combined .bat_options-option--remove-button { 7 | clear: both; 8 | float: right; 9 | } 10 | 11 | .field-widget-bat-options-combined .ajax-progress { 12 | float: right; 13 | margin: 5px 10px 0 0; 14 | } 15 | -------------------------------------------------------------------------------- /modules/bat_unit/bat_type.diff.inc: -------------------------------------------------------------------------------- 1 | revision_uid); 31 | $new_account = user_load($type_revisions[$new_revision_id]->revision_uid); 32 | 33 | // Generate table header (date, username, log message). 34 | $old_header = t('!date by !username', array( 35 | '!date' => l(format_date($old_type->revision_timestamp), "admin/bat/config/types/$type->type_id/revision/$old_type->revision_id/view", array('absolute' => 1)), 36 | '!username' => theme('username', array('account' => $old_account)), 37 | )); 38 | $new_header = t('!date by !username', array( 39 | '!date' => l(format_date($new_type->revision_timestamp), "admin/bat/config/types/$type->type_id/revision/$new_type->revision_id/view", array('absolute' => 1)), 40 | '!username' => theme('username', array('account' => $new_account)), 41 | )); 42 | 43 | $old_log = $old_type->log != '' ? '

' . filter_xss($old_type->log) . '

' : ''; 44 | $new_log = $new_type->log != '' ? '

' . filter_xss($new_type->log) . '

' : ''; 45 | 46 | // Generate previous diff/next diff links. 47 | $next_vid = bat_type_diff_get_next_vid($type_revisions, $new_revision_id); 48 | if ($next_vid) { 49 | $next_link = l(t('Next difference >'), 'admin/bat/config/types/' . $type->type_id . '/revisions/view/' . $new_revision_id . '/' . $next_vid, array('absolute' => 1)); 50 | } 51 | else { 52 | $next_link = ''; 53 | } 54 | $prev_vid = bat_type_diff_get_previous_vid($type_revisions, $old_revision_id); 55 | if ($prev_vid) { 56 | $prev_link = l(t('< Previous difference'), 'admin/bat/config/types/' . $type->type_id . '/revisions/view/' . $prev_vid . '/' . $old_revision_id, array('absolute' => 1)); 57 | } 58 | else { 59 | $prev_link = ''; 60 | } 61 | 62 | $header = _diff_default_header($old_header, $new_header); 63 | $rows = array(); 64 | if ($old_log || $new_log) { 65 | $rows['logs'] = array( 66 | array( 67 | 'data' => $old_log, 68 | 'colspan' => 2, 69 | ), 70 | array( 71 | 'data' => $new_log, 72 | 'colspan' => 2, 73 | ), 74 | ); 75 | } 76 | $rows['navigation'] = array( 77 | array( 78 | 'data' => $prev_link, 79 | 'class' => array('diff-prevlink'), 80 | 'colspan' => 2, 81 | ), 82 | array( 83 | 'data' => $next_link, 84 | 'class' => array('diff-nextlink'), 85 | 'colspan' => 2, 86 | ), 87 | ); 88 | 89 | $rows = array_merge($rows, bat_type_diff_body_rows($old_type, $new_type, $state)); 90 | 91 | $build['diff_table'] = array( 92 | '#theme' => 'table__diff__standard', 93 | '#header' => $header, 94 | '#rows' => $rows, 95 | '#attributes' => array('class' => array('diff')), 96 | '#colgroups' => _diff_default_cols(), 97 | '#sticky' => FALSE, 98 | ); 99 | 100 | return $build; 101 | } 102 | 103 | /** 104 | * Get the entry in the revisions list after $vid. 105 | * 106 | * @param array $type_revisions 107 | * Array of type revision IDs in descending order. 108 | * @param int $vid 109 | * Version ID to look for. 110 | * 111 | * @return bool|int 112 | * Returns FALSE if $vid is the last entry. 113 | */ 114 | function bat_type_diff_get_next_vid($type_revisions, $vid) { 115 | $previous = NULL; 116 | foreach ($type_revisions as $revision) { 117 | if ($revision->revision_id == $vid) { 118 | return ($previous ? $previous->revision_id : FALSE); 119 | } 120 | $previous = $revision; 121 | } 122 | return FALSE; 123 | } 124 | 125 | /** 126 | * Get the entry in the revision list before $vid. 127 | * 128 | * @param array $type_revisions 129 | * Array of type revision IDs in descending order. 130 | * @param int $vid 131 | * Version ID to look for. 132 | * 133 | * @return bool|int 134 | * Returns FALSE if $vid is the first entry. 135 | */ 136 | function bat_type_diff_get_previous_vid($type_revisions, $vid) { 137 | $previous = NULL; 138 | foreach ($type_revisions as $revision) { 139 | if ($previous && $previous->revision_id == $vid) { 140 | return $revision->revision_id; 141 | } 142 | $previous = $revision; 143 | } 144 | return FALSE; 145 | } 146 | 147 | /** 148 | * Creates an array of rows which represent the difference between types. 149 | * 150 | * @param object $old_type 151 | * BatType for comparison which will be displayed on the left side. 152 | * @param object $new_type 153 | * BatType for comparison which will be displayed on the right side. 154 | * @param bool $state 155 | * The state to render for the diff. 156 | */ 157 | function bat_type_diff_body_rows($old_type, $new_type, $state = 'raw') { 158 | $context = array( 159 | 'states' => array($state), 160 | 'view_mode' => 'diff_standard', 161 | ); 162 | return diff_entity_body_rows('bat_type', $old_type, $new_type, $context); 163 | } 164 | -------------------------------------------------------------------------------- /modules/bat_unit/bat_type.tpl.php: -------------------------------------------------------------------------------- 1 | 31 |
> 32 | 33 | > 34 | 35 | 36 | 37 | 38 |
> 39 | 42 |
43 |
44 | -------------------------------------------------------------------------------- /modules/bat_unit/bat_type_bundle.admin.inc: -------------------------------------------------------------------------------- 1 | path]['description'] = 'Manage type bundles, including adding and removing fields and the display of fields.'; 24 | $items[$this->path]['weight'] = '3'; 25 | 26 | return $items; 27 | } 28 | 29 | } 30 | 31 | /** 32 | * Generates the unit bundle editing form. 33 | */ 34 | function bat_type_bundle_form($form, &$form_state, $type_bundle, $op = 'edit') { 35 | 36 | $form['#attributes']['class'][] = 'bat-management-form bat-unit-bundle-edit-form'; 37 | $form['#attached']['css'] = array( 38 | drupal_get_path('module', 'bat') . '/css/bat_ui.css', 39 | ); 40 | 41 | if ($op == 'clone') { 42 | $type_bundle->label .= ' (cloned)'; 43 | $type_bundle->type = ''; 44 | } 45 | 46 | $form['label'] = array( 47 | '#title' => t('Type bundle name'), 48 | '#type' => 'textfield', 49 | '#default_value' => $type_bundle->label, 50 | '#description' => t('The human-readable name of this type bundle.'), 51 | '#required' => TRUE, 52 | '#size' => 30, 53 | '#weight' => -100, 54 | ); 55 | 56 | // Machine-readable type name. 57 | $form['type'] = array( 58 | '#type' => 'machine_name', 59 | '#default_value' => isset($type_bundle->type) ? $type_bundle->type : '', 60 | '#maxlength' => 32, 61 | '#machine_name' => array( 62 | 'exists' => 'bat_unit_get_type_bundles', 63 | 'source' => array('label'), 64 | ), 65 | '#description' => t('A unique machine-readable name for this type bundle. It must only contain lowercase letters, numbers, and underscores.'), 66 | '#weight' => -99, 67 | ); 68 | 69 | if ($op == 'edit') { 70 | $form['type']['#disabled'] = TRUE; 71 | } 72 | 73 | // Add the field related form elements. 74 | $form_state['bat_type_bundle'] = $type_bundle; 75 | field_attach_form('bat_type_bundle', $type_bundle, $form, $form_state); 76 | 77 | $form['additional_settings'] = array( 78 | '#type' => 'vertical_tabs', 79 | '#weight' => 99, 80 | ); 81 | 82 | $form['publishing_options'] = array( 83 | '#type' => 'fieldset', 84 | '#title' => t('Publishing options'), 85 | '#collapsible' => TRUE, 86 | '#collapsed' => TRUE, 87 | '#group' => 'additional_settings', 88 | ); 89 | 90 | $form['publishing_options']['revision'] = array( 91 | '#type' => 'checkbox', 92 | '#title' => t('Create new revision'), 93 | '#default_value' => (isset($type_bundle->data['revision'])) ? $type_bundle->data['revision'] : 0, 94 | ); 95 | 96 | if (module_exists('revisioning')) { 97 | $form['publishing_options']['revision_moderation'] = array( 98 | '#type' => 'checkbox', 99 | '#title' => t('New revision in draft, pending moderation (requires "Create new revision")'), 100 | '#default_value' => (isset($type_bundle->data['revision_moderation'])) ? $type_bundle->data['revision_moderation'] : 0, 101 | ); 102 | 103 | $form['publishing_options']['revisioning'] = array( 104 | '#type' => 'fieldset', 105 | '#title' => t('New revision in draft'), 106 | '#collapsible' => TRUE, 107 | '#collapsed' => FALSE, 108 | ); 109 | 110 | $form['publishing_options']['revisioning']['new_revisions'] = array( 111 | '#title' => t('Create new revision:'), 112 | '#type' => 'radios', 113 | '#options' => array( 114 | REVISIONING_NEW_REVISION_WHEN_NOT_PENDING => t('Only when saving %type type that is not already in draft/pending moderation', array('%type' => $type_bundle->label)), 115 | REVISIONING_NEW_REVISION_EVERY_SAVE => t('Every time %type type is updated, even when saving type in draft/pending moderation', array('%type' => $type_bundle->label)), 116 | ), 117 | '#default_value' => (isset($type_bundle->data['new_revisions'])) ? $type_bundle->data['new_revisions'] : REVISIONING_NEW_REVISION_WHEN_NOT_PENDING, 118 | ); 119 | } 120 | 121 | $form['actions'] = array( 122 | '#type' => 'actions', 123 | '#tree' => FALSE, 124 | ); 125 | 126 | $form['actions']['submit'] = array( 127 | '#type' => 'submit', 128 | '#value' => t('Save Bat Type bundle'), 129 | '#weight' => 100, 130 | '#submit' => array('bat_type_bundle_form_submit'), 131 | ); 132 | 133 | return $form; 134 | } 135 | 136 | /** 137 | * Validate callback for bat_type_bundle_form form. 138 | * 139 | * @see bat_type_bundle_form() 140 | */ 141 | function bat_type_bundle_form_validate(&$form, &$form_state) { 142 | // Notify field widgets to validate their data. 143 | entity_form_field_validate('bat_type_bundle', $form, $form_state); 144 | } 145 | 146 | /** 147 | * Form API submit callback for the unit bundle form. 148 | */ 149 | function bat_type_bundle_form_submit($form, &$form_state) { 150 | $type_bundle = entity_ui_form_submit_build_entity($form, $form_state); 151 | 152 | if ($type_bundle->data === '') { 153 | $type_bundle->data = array(); 154 | } 155 | 156 | $type_bundle->data['revision'] = $form_state['values']['revision']; 157 | if (isset($form_state['values']['revision_moderation'])) { 158 | $type_bundle->data['revision_moderation'] = $form_state['values']['revision_moderation']; 159 | } 160 | if (isset($form_state['values']['new_revisions'])) { 161 | $type_bundle->data['new_revisions'] = $form_state['values']['new_revisions']; 162 | } 163 | 164 | // Save and go back. 165 | $type_bundle->save(); 166 | 167 | $form_state['type_bundle'] = $type_bundle; 168 | 169 | $form_state['redirect'] = 'admin/bat/config/type-bundles'; 170 | } 171 | 172 | /** 173 | * Form API submit callback for the delete button. 174 | */ 175 | function bat_type_bundle_form_submit_delete(&$form, &$form_state) { 176 | $destination = array(); 177 | if (isset($_GET['destination'])) { 178 | $destination = drupal_get_destination(); 179 | unset($_GET['destination']); 180 | } 181 | 182 | $form_state['redirect'] = array('admin/bat/types/type_bundles/manage/' . $form_state['bat_type_bundle']->type . '/delete', array('query' => $destination)); 183 | } 184 | -------------------------------------------------------------------------------- /modules/bat_unit/bat_unit.info: -------------------------------------------------------------------------------- 1 | name = BAT Unit 2 | description = Create and manage units (e.g. rooms). 3 | core = 7.x 4 | 5 | package = BAT 6 | 7 | dependencies[] = bat 8 | dependencies[] = ctools 9 | dependencies[] = entity 10 | dependencies[] = views 11 | dependencies[] = views_bulk_operations 12 | dependencies[] = views_megarow 13 | 14 | files[] = bat_unit_bundle.admin.inc 15 | files[] = bat_unit.admin.inc 16 | files[] = bat_type.admin.inc 17 | files[] = bat_type_bundle.admin.inc 18 | files[] = views/bat_unit.views.inc 19 | files[] = views/bat_unit.views_default.inc 20 | files[] = views/bat_unit_handler_link_field.inc 21 | files[] = views/bat_unit_handler_delete_link_field.inc 22 | files[] = views/bat_unit_handler_edit_link_field.inc 23 | files[] = views/bat_unit_handler_type_id_filter.inc 24 | files[] = views/bat_unit_handler_type_id_field.inc 25 | files[] = views/bat_type_handler_delete_link_field.inc 26 | files[] = views/bat_type_handler_edit_link_field.inc 27 | files[] = views/bat_type_handler_link_field.inc 28 | files[] = views/bat_type_handler_type_calendars_field.inc 29 | files[] = views/bat_type_handler_type_operations_field.inc 30 | files[] = views/bat_unit_handler_field_megarow_links.inc 31 | files[] = views/bat_type_handler_type_revision_operations_field.inc 32 | files[] = views/bat_type_handler_type_revision_status_field.inc 33 | -------------------------------------------------------------------------------- /modules/bat_unit/bat_unit.rules.inc: -------------------------------------------------------------------------------- 1 | t('Type Revisioning'), 13 | 'variables' => _bat_unit_rules_event_variables(), 14 | ); 15 | $events = array( 16 | 'bat_type_revisioning_post_update' => $default + array( 17 | 'label' => t('Type revision has been updated'), 18 | ), 19 | 'bat_type_revisioning_pre_publish' => $default + array( 20 | 'label' => t('Type revision is going to be published'), 21 | ), 22 | 'bat_type_revisioning_post_publish' => $default + array( 23 | 'label' => t('Type revision has been published'), 24 | ), 25 | 'bat_type_revisioning_pre_revert' => $default + array( 26 | 'label' => t('Type is going to be reverted to revision'), 27 | ), 28 | 'bat_type_revisioning_post_revert' => $default + array( 29 | 'label' => t('Type has been reverted to revision'), 30 | ), 31 | 'bat_type_revisioning_post_unpublish' => $default + array( 32 | 'label' => t('Type has been unpublished'), 33 | ), 34 | 'bat_type_revisioning_pre_delete' => $default + array( 35 | 'label' => t('Type revision is going to be deleted'), 36 | ), 37 | 'bat_type_revisioning_post_delete' => $default + array( 38 | 'label' => t('Type revision has been deleted'), 39 | ), 40 | ); 41 | return $events; 42 | } 43 | 44 | /** 45 | * Returns event variables suitable for use with a type revision event. 46 | */ 47 | function _bat_unit_rules_event_variables() { 48 | $vars = array( 49 | 'user' => array( 50 | 'type' => 'user', 51 | 'label' => t('acting user'), 52 | 'description' => t('The acting user.'), 53 | 'handler' => 'bat_type_revisioning_events_argument_global_user', 54 | ), 55 | 'bat_type' => array( 56 | 'type' => 'bat_type', 57 | 'label' => t('target type.'), 58 | ), 59 | 'revision' => array( 60 | 'type' => 'bat_type', 61 | 'label' => t('current revision of target content.'), 62 | 'description' => t('The current content revision'), 63 | 'handler' => 'bat_type_revisioning_events_argument_current_revision', 64 | ), 65 | ); 66 | return $vars; 67 | } 68 | 69 | /** 70 | * Get global user argument. 71 | */ 72 | function bat_type_revisioning_events_argument_global_user($arguments, $name, $info) { 73 | global $user; 74 | return user_load($user->uid); 75 | } 76 | 77 | /** 78 | * Evaluate revision argument. 79 | */ 80 | function bat_type_revisioning_events_argument_current_revision($arguments, $name, $info) { 81 | if (empty($arguments['bat_type'])) { 82 | drupal_set_message(t('Revisioning: could not evaluate rule condition -- type variable missing.'), 'warning'); 83 | return FALSE; 84 | } 85 | $type = $arguments['bat_type']; 86 | $current_vid = $type->current_revision_id; 87 | if ($type->revision_id != $current_vid) { 88 | $current = bat_type_load($type->type_id, $current_vid); 89 | return $current; 90 | } 91 | return $type; 92 | } 93 | 94 | /** 95 | * Implements hook_rules_action_info(). 96 | */ 97 | function bat_unit_rules_action_info() { 98 | $default = array( 99 | 'group' => t('Type Revisioning'), 100 | ); 101 | return array( 102 | 'bat_type_revisioning_rules_action_publish_latest' => $default + array( 103 | 'label' => t('Publish the most recent pending revision'), 104 | 'parameter' => array( 105 | 'bat_type' => array('type' => 'bat_type', 'label' => t('type')), 106 | ), 107 | ), 108 | 'bat_type_revisioning_rules_action_load_current' => $default + array( 109 | 'label' => t('Load current revision of type'), 110 | 'parameter' => array( 111 | 'bat_type' => array('type' => 'bat_type', 'label' => t('type')), 112 | ), 113 | 'new variables' => array( 114 | 'loaded_current_revision' => array( 115 | 'type' => 'bat_type', 116 | 'label' => t('Loaded current revision of type'), 117 | 'save' => FALSE, 118 | 'label callback' => 'revisioning_rules_loaded_current_label', 119 | ), 120 | ), 121 | ), 122 | ); 123 | } 124 | 125 | /** 126 | * Action: load current revision of provided type. 127 | */ 128 | function bat_type_revisioning_rules_action_load_current($type) { 129 | $current_vid = $type->current_revision_id; 130 | if ($type->revision_id != $current_vid) { 131 | $current = bat_type_load_revision($current_vid); 132 | return array('loaded_current_revision' => $current); 133 | } 134 | return array('loaded_current_revision' => $type); 135 | } 136 | 137 | /** 138 | * Action: publish most recent pending revision. 139 | */ 140 | function bat_type_revisioning_rules_action_publish_latest($type) { 141 | // Get the latest pending revision. 142 | $pending_revisions = bat_type_get_pending_revisions($type->type_id); 143 | $latest_pending = array_shift($pending_revisions); 144 | if ($latest_pending) { 145 | $type_revision = bat_type_load_revision($latest_pending->revision_id); 146 | 147 | bat_type_revisioning_event('pre publish', $type_revision); 148 | 149 | $type_revision->default_revision = TRUE; 150 | $type_revision->save(); 151 | 152 | bat_type_revisioning_event('post publish', $type_revision); 153 | 154 | return TRUE; 155 | } 156 | // If there is no pending revision, take the current revision, provided it is 157 | // NOT published. 158 | if (!$type->status) { 159 | if (!isset($type->is_current)) { 160 | $type->current_revision_id = bat_type_get_current_type_revision_id($type->type_id); 161 | $type->is_current = revisioning_revision_is_current($type); 162 | } 163 | if ($type->is_current) { 164 | bat_type_revisioning_event('pre publish', $type_revision); 165 | 166 | $type_revision->default_revision = TRUE; 167 | $type_revision->save(); 168 | 169 | bat_type_revisioning_event('post publish', $type_revision); 170 | 171 | return TRUE; 172 | } 173 | } 174 | return FALSE; 175 | } 176 | -------------------------------------------------------------------------------- /modules/bat_unit/bat_unit.tokens.inc: -------------------------------------------------------------------------------- 1 | t('BAT Type', array(), array('context' => 'a bat type')), 14 | 'description' => t('Tokens related to bat type.'), 15 | 'needs-data' => 'bat-type', 16 | ); 17 | 18 | $bat_unit = array( 19 | 'name' => t('BAT Unit', array(), array('context' => 'a bat unit')), 20 | 'description' => t('Tokens related to bat unit.'), 21 | 'needs-data' => 'bat-unit', 22 | ); 23 | 24 | $info['author'] = array( 25 | 'name' => t('Author'), 26 | 'description' => t('The author.'), 27 | 'type' => 'user', 28 | ); 29 | 30 | return array( 31 | 'types' => array('bat_type' => $bat_type, 'bat_unit' => $bat_unit), 32 | 'tokens' => array('bat_type' => $info, 'bat_unit' => $info), 33 | ); 34 | } 35 | 36 | /** 37 | * Implements hook_tokens(). 38 | */ 39 | function bat_unit_tokens($type, $tokens, array $data = array(), array $options = array()) { 40 | $replacements = array(); 41 | 42 | if ($type == 'bat_type' && !empty($data['bat_type'])) { 43 | $bat_type = $data['bat_type']; 44 | 45 | foreach ($tokens as $name => $original) { 46 | switch ($name) { 47 | case 'author': 48 | $account = user_load($bat_type->uid); 49 | $name = format_username($account); 50 | $replacements[$original] = $sanitize ? check_plain($name) : $name; 51 | break; 52 | } 53 | } 54 | 55 | if ($author_tokens = token_find_with_prefix($tokens, 'author')) { 56 | $author = user_load($bat_type->uid); 57 | $replacements += token_generate('user', $author_tokens, array('user' => $author), $options); 58 | } 59 | } 60 | 61 | if ($type == 'bat_unit' && !empty($data['bat_unit'])) { 62 | $bat_unit = $data['bat_unit']; 63 | 64 | foreach ($tokens as $name => $original) { 65 | switch ($name) { 66 | case 'author': 67 | $account = user_load($bat_unit->uid); 68 | $name = format_username($account); 69 | $replacements[$original] = $sanitize ? check_plain($name) : $name; 70 | break; 71 | } 72 | } 73 | 74 | if ($author_tokens = token_find_with_prefix($tokens, 'author')) { 75 | $author = user_load($bat_unit->uid); 76 | $replacements += token_generate('user', $author_tokens, array('user' => $author), $options); 77 | } 78 | } 79 | 80 | return $replacements; 81 | } 82 | -------------------------------------------------------------------------------- /modules/bat_unit/bat_unit.tpl.php: -------------------------------------------------------------------------------- 1 | 31 |
> 32 | 33 | > 34 | 35 | 36 | 37 | 38 |
> 39 | 42 |
43 |
44 | -------------------------------------------------------------------------------- /modules/bat_unit/bat_unit_bundle.admin.inc: -------------------------------------------------------------------------------- 1 | path]['description'] = 'Manage unit bundles, including adding and removing fields and the display of fields.'; 24 | $items[$this->path]['weight'] = '3'; 25 | 26 | return $items; 27 | } 28 | 29 | } 30 | 31 | /** 32 | * Generates the unit bundle editing form. 33 | */ 34 | function bat_unit_bundle_form($form, &$form_state, $unit_bundle, $op = 'edit') { 35 | $form['#attributes']['class'][] = 'bat-management-form bat-unit-bundle-edit-form'; 36 | 37 | if ($op == 'clone') { 38 | $unit_bundle->label .= ' (cloned)'; 39 | $unit_bundle->type = ''; 40 | } 41 | 42 | $form['label'] = array( 43 | '#title' => t('Unit bundle name'), 44 | '#type' => 'textfield', 45 | '#default_value' => $unit_bundle->label, 46 | '#description' => t('The human-readable name of this unit bundle.'), 47 | '#required' => TRUE, 48 | '#size' => 30, 49 | '#weight' => -100, 50 | ); 51 | 52 | // Machine-readable type name. 53 | $form['type'] = array( 54 | '#type' => 'machine_name', 55 | '#default_value' => isset($unit_bundle->type) ? $unit_bundle->type : '', 56 | '#maxlength' => 32, 57 | '#machine_name' => array( 58 | 'exists' => 'bat_unit_get_bundles', 59 | 'source' => array('label'), 60 | ), 61 | '#description' => t('A unique machine-readable name for this unit bundle. It must only contain lowercase letters, numbers, and underscores.'), 62 | '#weight' => -99, 63 | ); 64 | 65 | if ($op == 'edit') { 66 | $form['type']['#disabled'] = TRUE; 67 | } 68 | 69 | // Add the field related form elements. 70 | $form_state['bat_unit_bundle'] = $unit_bundle; 71 | field_attach_form('bat_unit_bundle', $unit_bundle, $form, $form_state); 72 | 73 | $form['additional_settings'] = array( 74 | '#type' => 'vertical_tabs', 75 | '#weight' => 99, 76 | ); 77 | 78 | $form['actions'] = array( 79 | '#type' => 'actions', 80 | '#tree' => FALSE, 81 | ); 82 | 83 | $form['actions']['submit'] = array( 84 | '#type' => 'submit', 85 | '#value' => t('Save unit bundle'), 86 | '#weight' => 100, 87 | '#submit' => array('bat_unit_bundle_form_submit'), 88 | ); 89 | 90 | return $form; 91 | } 92 | 93 | /** 94 | * Validate callback for bat_unit_bundle_form form. 95 | * 96 | * @see bat_unit_bundle_form() 97 | */ 98 | function bat_unit_bundle_form_validate(&$form, &$form_state) { 99 | // Notify field widgets to validate their data. 100 | entity_form_field_validate('bat_unit_bundle', $form, $form_state); 101 | } 102 | 103 | /** 104 | * Form API submit callback for the unit bundle form. 105 | */ 106 | function bat_unit_bundle_form_submit($form, &$form_state) { 107 | $unit_bundle = entity_ui_form_submit_build_entity($form, $form_state); 108 | // Save and go back. 109 | $unit_bundle->save(); 110 | 111 | $form_state['unit_bundle'] = $unit_bundle; 112 | 113 | $form_state['redirect'] = 'admin/bat/config/unit-bundles'; 114 | } 115 | 116 | /** 117 | * Form API submit callback for the delete button. 118 | */ 119 | function bat_unit_bundle_form_submit_delete(&$form, &$form_state) { 120 | $destination = array(); 121 | if (isset($_GET['destination'])) { 122 | $destination = drupal_get_destination(); 123 | unset($_GET['destination']); 124 | } 125 | 126 | $form_state['redirect'] = array('admin/bat/units/unit_bundles/manage/' . $form_state['bat_unit_bundle']->type . '/delete', array('query' => $destination)); 127 | } 128 | -------------------------------------------------------------------------------- /modules/bat_unit/css/bat_unit.css: -------------------------------------------------------------------------------- 1 | /* Unit edit form */ 2 | .bat-unit-edit-form .form-wrapper { 3 | margin: 0 20px 0.4em 0; 4 | } 5 | 6 | .bat-unit-edit-form .form-item { 7 | margin-bottom: 1em; 8 | } 9 | 10 | .bat-unit-edit-form .form-item label, 11 | .bat-unit-edit-form .form-wrapper legend { 12 | margin-bottom: 0.2em; 13 | } 14 | 15 | .bat-unit-edit-form .form-item label, 16 | .bat-unit-edit-form .form-wrapper .fieldset-legend { 17 | font-size: 1em; 18 | font-weight: bold; 19 | } 20 | 21 | .bat-unit-edit-form .form-checkbox + label { 22 | font-weight: normal; 23 | } 24 | 25 | .bat-unit-edit-form .form-checkbox:checked + label { 26 | font-weight: bold; 27 | } 28 | 29 | .bat-unit-edit-form .form-type-select { 30 | float: none; 31 | } 32 | 33 | .bat-unit-edit-form .form-item-name { 34 | width: 15em; 35 | } 36 | 37 | .bat-unit-edit-form .form-actions { 38 | clear: both; 39 | float: none; 40 | } 41 | -------------------------------------------------------------------------------- /modules/bat_unit/views/bat_type_handler_delete_link_field.inc: -------------------------------------------------------------------------------- 1 | additional_fields['type'] = 'type'; 20 | } 21 | 22 | /** 23 | * {@inheritdoc} 24 | */ 25 | public function render($values) { 26 | $type = $values->{$this->aliases['type']}; 27 | 28 | // Creating a dummy type to check access against. 29 | $dummy_type = bat_type_create(array('type' => $type)); 30 | if (!bat_type_access('delete', $dummy_type)) { 31 | return; 32 | } 33 | 34 | $text = !empty($this->options['text']) ? $this->options['text'] : t('delete'); 35 | $type_id = $values->{$this->aliases['type_id']}; 36 | 37 | $options = array(); 38 | if (!empty($this->options['destination'])) { 39 | $options = array('query' => drupal_get_destination()); 40 | } 41 | 42 | return l($text, 'admin/bat/config/types/' . $type_id . '/delete', $options); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /modules/bat_unit/views/bat_type_handler_edit_link_field.inc: -------------------------------------------------------------------------------- 1 | additional_fields['type'] = 'type'; 20 | } 21 | 22 | /** 23 | * {@inheritdoc} 24 | */ 25 | public function render($values) { 26 | $type = $values->{$this->aliases['type']}; 27 | 28 | // Creating a dummy type to check access against. 29 | $dummy_type = bat_type_create(array('type' => $type)); 30 | if (!bat_type_access('update', $dummy_type)) { 31 | return; 32 | } 33 | 34 | $text = !empty($this->options['text']) ? $this->options['text'] : t('edit'); 35 | $type_id = $values->{$this->aliases['type_id']}; 36 | 37 | $options = array(); 38 | if (!empty($this->options['destination'])) { 39 | $options = array('query' => drupal_get_destination()); 40 | } 41 | 42 | return l($text, 'admin/bat/config/types/' . $type_id . '/edit', $options); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /modules/bat_unit/views/bat_type_handler_link_field.inc: -------------------------------------------------------------------------------- 1 | additional_fields['type_id'] = 'type_id'; 21 | $this->additional_fields['type'] = 'type'; 22 | } 23 | 24 | /** 25 | * {@inheritdoc} 26 | */ 27 | public function option_definition() { 28 | $options = parent::option_definition(); 29 | 30 | $options['text'] = array('default' => '', 'translatable' => TRUE); 31 | $options['destination'] = array('default' => TRUE, 'bool' => TRUE); 32 | 33 | return $options; 34 | } 35 | 36 | /** 37 | * {@inheritdoc} 38 | */ 39 | public function options_form(&$form, &$form_state) { 40 | parent::options_form($form, $form_state); 41 | 42 | $form['text'] = array( 43 | '#type' => 'textfield', 44 | '#title' => t('Text to display'), 45 | '#default_value' => $this->options['text'], 46 | ); 47 | 48 | $form['destination'] = array( 49 | '#type' => 'checkbox', 50 | '#title' => t('Include destination'), 51 | '#description' => t('Include a "destination" parameter in the link to return the user to the original view upon completing the link action.'), 52 | '#default_value' => $this->options['destination'], 53 | ); 54 | } 55 | 56 | /** 57 | * {@inheritdoc} 58 | */ 59 | public function query() { 60 | $this->ensure_my_table(); 61 | $this->add_additional_fields(); 62 | } 63 | 64 | /** 65 | * {@inheritdoc} 66 | */ 67 | public function render($values) { 68 | $text = !empty($this->options['text']) ? $this->options['text'] : t('view'); 69 | $type_id = $values->{$this->aliases['type_id']}; 70 | 71 | $options = array(); 72 | if (!empty($this->options['destination'])) { 73 | $options = array('query' => drupal_get_destination()); 74 | } 75 | 76 | return l($text, 'type/' . $type_id, $options); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /modules/bat_unit/views/bat_type_handler_type_calendars_field.inc: -------------------------------------------------------------------------------- 1 | additional_fields['type_id'] = 'type_id'; 21 | } 22 | 23 | /** 24 | * {@inheritdoc} 25 | */ 26 | public function query() { 27 | $this->ensure_my_table(); 28 | $this->add_additional_fields(); 29 | } 30 | 31 | /** 32 | * {@inheritdoc} 33 | */ 34 | public function render($values) { 35 | $links = array(); 36 | 37 | $type = bat_type_load($this->get_value($values, 'type_id')); 38 | $type_bundle = bat_type_bundle_load($type->type); 39 | if (is_array($type_bundle->default_event_value_field_ids)) { 40 | foreach ($type_bundle->default_event_value_field_ids as $event_type => $field) { 41 | if (!empty($field)) { 42 | $event_type_path = 'admin/bat/calendar/' . $type->type_id . '/' . $event_type; 43 | 44 | // Check if user has permission to access $event_type_path. 45 | if (drupal_valid_path($event_type_path)) { 46 | $event_type_label = bat_event_get_types($event_type)->label; 47 | $links[$field] = array( 48 | 'title' => 'Manage ' . $event_type_label, 49 | 'href' => $event_type_path, 50 | ); 51 | } 52 | } 53 | } 54 | } 55 | 56 | if (!empty($links)) { 57 | return theme('links', array( 58 | 'links' => $links, 59 | 'attributes' => array( 60 | 'class' => array( 61 | 'links', 62 | 'inline', 63 | 'calendars', 64 | ), 65 | ), 66 | )); 67 | } 68 | else { 69 | // Hide this field. 70 | $this->options['exclude'] = TRUE; 71 | } 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /modules/bat_unit/views/bat_type_handler_type_operations_field.inc: -------------------------------------------------------------------------------- 1 | additional_fields['type_id'] = 'type_id'; 21 | } 22 | 23 | /** 24 | * {@inheritdoc} 25 | */ 26 | public function query() { 27 | $this->ensure_my_table(); 28 | $this->add_additional_fields(); 29 | } 30 | 31 | /** 32 | * {@inheritdoc} 33 | */ 34 | public function render($values) { 35 | $links = menu_contextual_links('bat_unit', 'admin/bat/config/types', array($this->get_value($values, 'type_id'))); 36 | 37 | // Unset the "view" link, as this is provided separately. 38 | if (array_key_exists('bat_unit-view', $links)) { 39 | unset($links['bat_unit-view']); 40 | } 41 | 42 | if (!empty($links)) { 43 | return theme('links', array( 44 | 'links' => $links, 45 | 'attributes' => array( 46 | 'class' => array( 47 | 'links', 48 | 'inline', 49 | 'operations', 50 | ), 51 | ), 52 | )); 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /modules/bat_unit/views/bat_type_handler_type_revision_operations_field.inc: -------------------------------------------------------------------------------- 1 | additional_fields['type_id'] = 'type_id'; 21 | $this->additional_fields['revision_id'] = 'revision_id'; 22 | } 23 | 24 | /** 25 | * {@inheritdoc} 26 | */ 27 | public function query() { 28 | $this->ensure_my_table(); 29 | $this->add_additional_fields(); 30 | } 31 | 32 | /** 33 | * {@inheritdoc} 34 | */ 35 | public function render($values) { 36 | $type_id = $this->get_value($values, 'type_id'); 37 | $revision_id = $this->get_value($values, 'revision_id'); 38 | 39 | $type = bat_type_load_revision($revision_id); 40 | if (entity_revision_is_default('bat_type', $type)) { 41 | return '' . t('This is the published revision.') . ''; 42 | } 43 | else { 44 | $links = array(); 45 | 46 | if (bat_type_access_revision('view', $type, $revision_id)) { 47 | $links[] = array( 48 | 'href' => 'admin/bat/config/types/' . $type_id . '/revision/' . $revision_id . '/view', 49 | 'title' => t('View'), 50 | ); 51 | 52 | $current_revision = bat_type_load($type_id); 53 | $current_revision_id = $current_revision->revision_id; 54 | 55 | $links[] = array( 56 | 'href' => 'admin/bat/config/types/' . $type_id . '/revisions/view/' . $revision_id . '/' . $current_revision_id, 57 | 'title' => t('Compare'), 58 | ); 59 | } 60 | 61 | if (bat_type_access_revision('revert', $type, $revision_id)) { 62 | $links[] = array( 63 | 'href' => 'admin/bat/config/types/' . $type_id . '/revision/' . $revision_id . '/revert', 64 | 'title' => t('Revert'), 65 | ); 66 | } 67 | 68 | if (bat_type_access_revision('delete', $type, $revision_id)) { 69 | $links[] = array( 70 | 'href' => 'admin/bat/config/types/' . $type_id . '/revision/' . $revision_id . '/delete', 71 | 'title' => t('Delete'), 72 | ); 73 | } 74 | 75 | if (!empty($links)) { 76 | return theme('links', array( 77 | 'links' => $links, 78 | 'attributes' => array( 79 | 'class' => array( 80 | 'links', 81 | 'inline', 82 | 'operations', 83 | ), 84 | ), 85 | )); 86 | } 87 | } 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /modules/bat_unit/views/bat_type_handler_type_revision_status_field.inc: -------------------------------------------------------------------------------- 1 | additional_fields['type_id'] = 'type_id'; 21 | $this->additional_fields['revision_id'] = 'revision_id'; 22 | } 23 | 24 | /** 25 | * {@inheritdoc} 26 | */ 27 | public function query() { 28 | $this->ensure_my_table(); 29 | $this->add_additional_fields(); 30 | } 31 | 32 | /** 33 | * {@inheritdoc} 34 | */ 35 | public function render($values) { 36 | $type_id = $this->get_value($values, 'type_id'); 37 | $revision_id = $this->get_value($values, 'revision_id'); 38 | 39 | $type = bat_type_load($type_id); 40 | $type_revision = bat_type_load_revision($revision_id); 41 | 42 | $is_current = ($revision_id == $type->revision_id); 43 | $is_pending = ($revision_id > $type->revision_id); 44 | 45 | if ($is_pending) { 46 | return t('in draft/pending publication'); 47 | } 48 | elseif ($is_current) { 49 | return t('current revision (published)'); 50 | } 51 | 52 | return t('archived'); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /modules/bat_unit/views/bat_unit.views.inc: -------------------------------------------------------------------------------- 1 | t('Booking Unit Bundle'), 16 | 'help' => t('Booking Unit Bundle Label.'), 17 | 'handler' => 'bat_unit_handler_unit_bundle_field', 18 | ); 19 | 20 | $data['bat_units']['link_unit'] = array( 21 | 'field' => array( 22 | 'title' => t('Link'), 23 | 'help' => t('Provide a link to the unit.'), 24 | 'handler' => 'bat_unit_handler_link_field', 25 | ), 26 | ); 27 | $data['bat_units']['edit_unit'] = array( 28 | 'field' => array( 29 | 'title' => t('Edit Link'), 30 | 'help' => t('Provide a link to the edit form for the unit.'), 31 | 'handler' => 'bat_unit_handler_edit_link_field', 32 | ), 33 | ); 34 | $data['bat_units']['delete_unit'] = array( 35 | 'field' => array( 36 | 'title' => t('Delete Link'), 37 | 'help' => t('Provide a link to delete the unit.'), 38 | 'handler' => 'bat_unit_handler_delete_link_field', 39 | ), 40 | ); 41 | // The content of this field is decided based on the menu structure 42 | // under bat/unit/%unit_id/op. 43 | $data['bat_units']['operations'] = array( 44 | 'field' => array( 45 | 'title' => t('Operations links'), 46 | 'help' => t('Display all operations available for this unit.'), 47 | 'handler' => 'bat_unit_handler_unit_operations_field', 48 | ), 49 | ); 50 | 51 | // Expose the uid as a relationship to users. 52 | $data['bat_units']['uid'] = array( 53 | 'title' => t('Uid'), 54 | 'help' => t("The owner's user ID."), 55 | 'field' => array( 56 | 'handler' => 'views_handler_field_user', 57 | 'click sortable' => TRUE, 58 | ), 59 | 'argument' => array( 60 | 'handler' => 'views_handler_argument_user_uid', 61 | 'name field' => 'name', 62 | ), 63 | 'filter' => array( 64 | 'title' => t('Name'), 65 | 'handler' => 'views_handler_filter_user_name', 66 | ), 67 | 'sort' => array( 68 | 'handler' => 'views_handler_sort', 69 | ), 70 | 'relationship' => array( 71 | 'title' => t('Owner'), 72 | 'help' => t("Relate this unit to its owner's user account"), 73 | 'handler' => 'views_handler_relationship', 74 | 'base' => 'users', 75 | 'base field' => 'uid', 76 | 'field' => 'uid', 77 | 'label' => t('Unit owner'), 78 | ), 79 | ); 80 | 81 | $data['bat_units']['type_id']['filter']['handler'] = 'bat_unit_handler_type_id_filter'; 82 | $data['bat_units']['type_id']['field']['handler'] = 'bat_unit_handler_type_id_field'; 83 | 84 | $data['bat_units']['type_id']['relationship'] = array( 85 | 'title' => t('Type'), 86 | 'help' => t('Relate this unit its type'), 87 | 'handler' => 'views_handler_relationship', 88 | 'base' => 'bat_types', 89 | 'base field' => 'type_id', 90 | 'field' => 'type_id', 91 | 'label' => t('Type'), 92 | ); 93 | 94 | // Views alterations for Bat Types. 95 | $data['bat_types']['link_type'] = array( 96 | 'field' => array( 97 | 'title' => t('Link'), 98 | 'help' => t('Provide a link to the Type.'), 99 | 'handler' => 'bat_type_handler_link_field', 100 | ), 101 | ); 102 | $data['bat_types']['edit_type'] = array( 103 | 'field' => array( 104 | 'title' => t('Edit Link'), 105 | 'help' => t('Provide a link to the edit form for the type.'), 106 | 'handler' => 'bat_type_handler_edit_link_field', 107 | ), 108 | ); 109 | $data['bat_types']['delete_type'] = array( 110 | 'field' => array( 111 | 'title' => t('Delete Link'), 112 | 'help' => t('Provide a link to delete the type.'), 113 | 'handler' => 'bat_type_handler_delete_link_field', 114 | ), 115 | ); 116 | 117 | $data['bat_types']['calendars'] = array( 118 | 'field' => array( 119 | 'title' => t('Event Management'), 120 | 'help' => t('Display links to manage all calendars for this Type.'), 121 | 'handler' => 'bat_type_handler_type_calendars_field', 122 | ), 123 | ); 124 | 125 | // The content of this field is decided based on the menu structure 126 | // under bat/config/type/%type_id/op. 127 | $data['bat_types']['operations'] = array( 128 | 'field' => array( 129 | 'title' => t('Operations links'), 130 | 'help' => t('Display all operations available for this type.'), 131 | 'handler' => 'bat_type_handler_type_operations_field', 132 | ), 133 | ); 134 | 135 | $data['views_entity_bat_unit']['megarow_links']['field']['handler'] = 'bat_unit_handler_field_megarow_links'; 136 | 137 | $data['bat_types_revision']['table']['entity type'] = 'bat_type'; 138 | $data['bat_types_revision']['table']['group'] = t('Type revision'); 139 | 140 | $data['bat_types_revision']['table']['base'] = array( 141 | 'field' => 'revision_id', 142 | 'title' => t('Type revision'), 143 | 'help' => t('Type revision is a history of changes to a type.'), 144 | 'defaults' => array( 145 | 'field' => 'name', 146 | ), 147 | ); 148 | 149 | $data['bat_types_revision']['table']['join'] = array( 150 | 'bat_types' => array( 151 | 'left_field' => 'revision_id', 152 | 'field' => 'revision_id', 153 | ), 154 | ); 155 | 156 | $data['bat_types_revision']['table']['default_relationship'] = array( 157 | 'bat_types' => array( 158 | 'table' => 'bat_types', 159 | 'field' => 'revision_id', 160 | ), 161 | ); 162 | 163 | $data['bat_types_revision']['type_id'] = array( 164 | 'title' => t('Type ID'), 165 | 'help' => t('The unique internal identifier of the type.'), 166 | 'field' => array( 167 | 'handler' => 'views_handler_field', 168 | 'click sortable' => TRUE, 169 | ), 170 | 'filter' => array( 171 | 'handler' => 'views_handler_filter_numeric', 172 | ), 173 | 'sort' => array( 174 | 'handler' => 'views_handler_sort', 175 | ), 176 | 'argument' => array( 177 | 'handler' => 'views_handler_argument_numeric', 178 | ), 179 | ); 180 | 181 | $data['bat_types_revision']['revision_id'] = array( 182 | 'title' => t('Revision ID'), 183 | 'help' => t('The revision ID of the type revision.'), 184 | 'field' => array( 185 | 'click sortable' => TRUE, 186 | ), 187 | 'filter' => array( 188 | 'handler' => 'views_handler_filter_numeric', 189 | ), 190 | 'sort' => array( 191 | 'handler' => 'views_handler_sort', 192 | ), 193 | 'relationship' => array( 194 | 'handler' => 'views_handler_relationship', 195 | 'base' => 'bat_types', 196 | 'base field' => 'revision_id', 197 | 'title' => t('Type'), 198 | 'label' => t('Latest type revision'), 199 | ), 200 | ); 201 | 202 | $data['bat_types_revision']['name'] = array( 203 | 'title' => t('Name'), 204 | 'help' => t('The name of the type revision used for administrative display.'), 205 | 'field' => array( 206 | 'handler' => 'views_handler_field', 207 | 'click sortable' => TRUE, 208 | ), 209 | 'filter' => array( 210 | 'handler' => 'views_handler_filter_string', 211 | ), 212 | 'sort' => array( 213 | 'handler' => 'views_handler_sort', 214 | ), 215 | 'argument' => array( 216 | 'handler' => 'views_handler_argument_string', 217 | ), 218 | ); 219 | 220 | $data['bat_types_revision']['revision_uid'] = array( 221 | 'title' => t('User'), 222 | 'help' => t('Relate a type revision to the user who created the revision.'), 223 | 'relationship' => array( 224 | 'handler' => 'views_handler_relationship', 225 | 'base' => 'users', 226 | 'base field' => 'uid', 227 | 'field' => 'revision_uid', 228 | 'field_name' => 'revision_uid', 229 | 'label' => t('Revision user'), 230 | ), 231 | ); 232 | 233 | $data['bat_types_revision']['log'] = array( 234 | 'title' => t('Log message'), 235 | 'help' => t('The log message entered when the revision was created.'), 236 | 'field' => array( 237 | 'handler' => 'views_handler_field_xss', 238 | ), 239 | 'filter' => array( 240 | 'handler' => 'views_handler_filter_string', 241 | ), 242 | ); 243 | 244 | $data['bat_types_revision']['revision_timestamp'] = array( 245 | 'title' => t('Revision date'), 246 | 'help' => t('The date the type revision was created.'), 247 | 'field' => array( 248 | 'handler' => 'views_handler_field_date', 249 | 'click sortable' => TRUE, 250 | ), 251 | 'sort' => array( 252 | 'handler' => 'views_handler_sort_date', 253 | ), 254 | 'filter' => array( 255 | 'handler' => 'views_handler_filter_date', 256 | ), 257 | ); 258 | 259 | $data['bat_types_revision']['status'] = array( 260 | 'field' => array( 261 | 'title' => t('Revision status'), 262 | 'help' => t(''), 263 | 'handler' => 'bat_type_handler_type_revision_status_field', 264 | ), 265 | ); 266 | 267 | $data['bat_types_revision']['operations'] = array( 268 | 'field' => array( 269 | 'title' => t('Operations links'), 270 | 'help' => t('Display all operations available for this type revision.'), 271 | 'handler' => 'bat_type_handler_type_revision_operations_field', 272 | ), 273 | ); 274 | } 275 | -------------------------------------------------------------------------------- /modules/bat_unit/views/bat_unit_handler_delete_link_field.inc: -------------------------------------------------------------------------------- 1 | additional_fields['type'] = 'type'; 20 | } 21 | 22 | /** 23 | * {@inheritdoc} 24 | */ 25 | public function render($values) { 26 | $type = $values->{$this->aliases['type']}; 27 | 28 | // Creating a dummy unit to check access against. 29 | $dummy_unit = bat_unit_create(array('type' => $type)); 30 | if (!bat_unit_access('delete', $dummy_unit)) { 31 | return; 32 | } 33 | 34 | $text = !empty($this->options['text']) ? $this->options['text'] : t('delete'); 35 | $unit_id = $values->{$this->aliases['unit_id']}; 36 | 37 | $options = array(); 38 | if (!empty($this->options['destination'])) { 39 | $options = array('query' => drupal_get_destination()); 40 | } 41 | 42 | return l($text, 'admin/bat/units/unit/' . $unit_id . '/delete', $options); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /modules/bat_unit/views/bat_unit_handler_edit_link_field.inc: -------------------------------------------------------------------------------- 1 | additional_fields['type'] = 'type'; 20 | } 21 | 22 | /** 23 | * {@inheritdoc} 24 | */ 25 | public function render($values) { 26 | $type = $values->{$this->aliases['type']}; 27 | 28 | // Creating a dummy unit to check access against. 29 | $dummy_unit = bat_unit_create(array('type' => $type)); 30 | if (!bat_unit_access('update', $dummy_unit)) { 31 | return; 32 | } 33 | $text = !empty($this->options['text']) ? $this->options['text'] : t('edit'); 34 | $unit_id = $values->{$this->aliases['unit_id']}; 35 | 36 | $options = array(); 37 | if (!empty($this->options['destination'])) { 38 | $options = array('query' => drupal_get_destination()); 39 | } 40 | 41 | return l($text, 'admin/bat/units/unit/' . $unit_id . '/edit', $options); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /modules/bat_unit/views/bat_unit_handler_field_megarow_links.inc: -------------------------------------------------------------------------------- 1 | query->get_result_entities($results); 19 | $entity = reset($entities[1]); 20 | $table_data = views_fetch_data($this->table); 21 | $entity_type = $table_data['table']['entity type']; 22 | list($entity_id) = entity_extract_ids($entity_type, $entity); 23 | 24 | // Create an array of links. 25 | $provided_links = explode("\n", $this->options['megarow']['links']); 26 | $provided_links = array_map('trim', $provided_links); 27 | $provided_links = array_filter($provided_links, 'strlen'); 28 | 29 | $links = array(); 30 | $tokens = $this->get_render_tokens(array()); 31 | foreach ($provided_links as $link) { 32 | $link_parts = explode('|', $link); 33 | 34 | $path = $this->render_altered(array('text' => $this->replaceTokens($link_parts[1], $entity)), $tokens); 35 | 36 | if (drupal_valid_path($path)) { 37 | // Replace tokens if necessary in the url. 38 | $url = 'display_megarow/' . $entity_id . '/' . $path; 39 | 40 | // Do the same for the label. 41 | $label = $this->replaceTokens($link_parts[0], $entity); 42 | $label = $this->render_altered(array('text' => $label), $tokens); 43 | $label = decode_entities($label); 44 | 45 | // Add the link for rendering. 46 | $links[] = $this->getLink($label, $url, array('class' => array('views-megarow-open'))); 47 | } 48 | } 49 | 50 | $nb_links = count($links); 51 | if ($nb_links == 0) { 52 | $element = array(); 53 | 54 | // Hide this field. 55 | $this->options['exclude'] = TRUE; 56 | } 57 | elseif ($nb_links > 1) { 58 | $element = array( 59 | '#prefix' => $this->getElementPrefix($values), 60 | '#markup' => theme('links__ctools_dropbutton', array( 61 | 'links' => $links, 62 | 'attributes' => array( 63 | 'class' => array('links', 'inline'), 64 | ), 65 | )), 66 | '#suffix' => $this->getElementSuffix($values), 67 | ); 68 | } 69 | else { 70 | $element = array( 71 | '#type' => 'link', 72 | '#title' => $links[0]['title'], 73 | '#href' => $links[0]['href'], 74 | '#options' => array( 75 | 'attributes' => $links[0]['attributes'], 76 | ), 77 | ); 78 | } 79 | 80 | return $element; 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /modules/bat_unit/views/bat_unit_handler_link_field.inc: -------------------------------------------------------------------------------- 1 | additional_fields['unit_id'] = 'unit_id'; 21 | $this->additional_fields['type'] = 'type'; 22 | } 23 | 24 | /** 25 | * {@inheritdoc} 26 | */ 27 | public function option_definition() { 28 | $options = parent::option_definition(); 29 | 30 | $options['text'] = array('default' => '', 'translatable' => TRUE); 31 | $options['destination'] = array('default' => TRUE, 'bool' => TRUE); 32 | 33 | return $options; 34 | } 35 | 36 | /** 37 | * {@inheritdoc} 38 | */ 39 | public function options_form(&$form, &$form_state) { 40 | parent::options_form($form, $form_state); 41 | 42 | $form['text'] = array( 43 | '#type' => 'textfield', 44 | '#title' => t('Text to display'), 45 | '#default_value' => $this->options['text'], 46 | ); 47 | 48 | $form['destination'] = array( 49 | '#type' => 'checkbox', 50 | '#title' => t('Include destination'), 51 | '#description' => t('Include a "destination" parameter in the link to return the user to the original view upon completing the link action.'), 52 | '#default_value' => $this->options['destination'], 53 | ); 54 | } 55 | 56 | /** 57 | * {@inheritdoc} 58 | */ 59 | public function query() { 60 | $this->ensure_my_table(); 61 | $this->add_additional_fields(); 62 | } 63 | 64 | /** 65 | * {@inheritdoc} 66 | */ 67 | public function render($values) { 68 | $text = !empty($this->options['text']) ? $this->options['text'] : t('view'); 69 | $unit_id = $values->{$this->aliases['unit_id']}; 70 | 71 | $options = array(); 72 | if (!empty($this->options['destination'])) { 73 | $options = array('query' => drupal_get_destination()); 74 | } 75 | 76 | return l($text, 'unit/' . $unit_id, $options); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /modules/bat_unit/views/bat_unit_handler_type_id_field.inc: -------------------------------------------------------------------------------- 1 | get_value($values))) { 26 | return $type->name; 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /modules/bat_unit/views/bat_unit_handler_type_id_filter.inc: -------------------------------------------------------------------------------- 1 | type_id] = $type->name; 30 | } 31 | 32 | $this->value_options = $options; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /modules/bat_unit/views/bat_unit_handler_unit_type_field.inc: -------------------------------------------------------------------------------- 1 | get_value($values)); 26 | return $unit_bundle->label; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /test/behat/behat.yml: -------------------------------------------------------------------------------- 1 | default: 2 | suites: 3 | default: 4 | contexts: 5 | - FeatureContext 6 | - Drupal\DrupalExtension\Context\MinkContext 7 | - Drupal\DrupalExtension\Context\MessageContext 8 | - Drupal\DrupalExtension\Context\DrushContext 9 | - Roomify\RoomifyExtension\Context\RoomifyContext 10 | extensions: 11 | Behat\MinkExtension: 12 | base_url: 'http://127.0.0.1:8888' 13 | files_path: '%paths.base%/testing_files' 14 | selenium2: 15 | browser: chrome 16 | javascript_session: 'selenium2' 17 | Drupal\DrupalExtension: 18 | blackbox: ~ 19 | api_driver: 'drupal' 20 | drush_driver: 'drush' 21 | drush: 22 | root: ../.. 23 | 24 | imports: 25 | - behat.local.yml 26 | -------------------------------------------------------------------------------- /test/behat/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "behat/behat": "3.4.3", 4 | "behat/mink": "1.7.1", 5 | "behat/mink-goutte-driver": "*", 6 | "behat/mink-selenium2-driver": "*", 7 | "drupal/drupal-extension": "3.4.1", 8 | "symfony/process": "*", 9 | "symfony/dependency-injection": "2.8.52", 10 | "behat/symfony2-extension": "*", 11 | "symfony/form": "*", 12 | "symfony/validator": "*", 13 | "behat/mink-extension": "*", 14 | "symfony/http-kernel": "*", 15 | "fabpot/goutte": "2.0.4", 16 | "instaclick/php-webdriver": "1.4.5", 17 | "roomify/roomify-extension": "~1.0", 18 | "php": ">=5.5" 19 | }, 20 | "minimum-stability": "dev", 21 | "config": { 22 | "bin-dir": "bin" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/behat/features/bootstrap/FeatureContext.php: -------------------------------------------------------------------------------- 1 | getEnvironment(); 89 | $this->minkContext = $environment->getContext('Drupal\DrupalExtension\Context\MinkContext'); 90 | } 91 | 92 | /** 93 | * @AfterScenario 94 | */ 95 | public function after(AfterScenarioScope $scope) { 96 | foreach ($this->getUserManager()->getUsers() as $user) { 97 | $query2 = new EntityFieldQuery(); 98 | $query2->entityCondition('entity_type', 'bat_event') 99 | ->propertyCondition('uid', $user->uid); 100 | $result = $query2->execute(); 101 | if (isset($result['bat_event'])) { 102 | $event_ids = array_keys($result['bat_event']); 103 | bat_event_delete_multiple($event_ids); 104 | } 105 | } 106 | 107 | if (!empty($this->units)) { 108 | foreach ($this->units as $unit) { 109 | $unit->delete(); 110 | } 111 | } 112 | 113 | if (!empty($this->Types)) { 114 | foreach ($this->Types as $type) { 115 | $type->delete(); 116 | } 117 | } 118 | 119 | if (!empty($this->typeBundles)) { 120 | foreach ($this->typeBundles as $type_bundle) { 121 | $type_bundle->delete(); 122 | } 123 | } 124 | 125 | if (!empty($this->eventTypes)) { 126 | foreach ($this->eventTypes as $event_type) { 127 | $event_type->delete(); 128 | } 129 | } 130 | 131 | if (!empty($this->events)) { 132 | bat_event_delete_multiple($this->events); 133 | } 134 | 135 | foreach ($this->content_types as $content_type) { 136 | node_type_delete($content_type); 137 | } 138 | 139 | foreach ($this->fields as $field) { 140 | field_delete_field($field); 141 | } 142 | 143 | } 144 | 145 | /** 146 | * @When /^I am on the "([^"]*)" type$/ 147 | */ 148 | public function iAmOnTheType($type_name) { 149 | $this->iAmDoingOnTheType('view', $type_name); 150 | } 151 | 152 | /** 153 | * @When /^I am editing the "([^"]*)" type$/ 154 | */ 155 | public function iAmEditingTheType($type_name) { 156 | $this->iAmDoingOnTheType('edit', $type_name); 157 | } 158 | 159 | /** 160 | * Asserts that a given node type is editable. 161 | */ 162 | public function assertEditNodeOfType($type) { 163 | $node = (object) array('type' => $type); 164 | $saved = $this->getDriver()->createNode($node); 165 | $this->nodes[] = $saved; 166 | 167 | // Set internal browser on the node edit page. 168 | $this->getSession()->visit($this->locatePath('/node/' . $saved->nid . '/edit')); 169 | } 170 | 171 | /** 172 | * Fills a field using JS to avoid event firing. 173 | * @param string $field 174 | * @param string$value 175 | * 176 | */ 177 | protected function fillFieldByJS($field, $value) { 178 | $field = str_replace('\\"', '"', $field); 179 | $value = str_replace('\\"', '"', $value); 180 | $xpath = $this->getSession()->getPage()->findField($field)->getXpath(); 181 | 182 | $element = $this->getSession()->getDriver()->getWebDriverSession()->element('xpath', $xpath); 183 | $elementID = $element->getID(); 184 | $subscript = "arguments[0]"; 185 | $script = str_replace('{{ELEMENT}}', $subscript, '{{ELEMENT}}.value = "' . $value . '"'); 186 | return $this->getSession()->getDriver()->getWebDriverSession()->execute(array( 187 | 'script' => $script, 188 | 'args' => array(array('ELEMENT' => $elementID)) 189 | )); 190 | } 191 | 192 | /** 193 | * Redirects user to the action page for the given unit. 194 | * 195 | * @param $action 196 | * @param $unit_name 197 | */ 198 | protected function iAmDoingOnTheType($action, $type_name) { 199 | $unit_id = $this->findTypeByName($type_name); 200 | $url = "admin/bat/config/types/$type_id/$action"; 201 | $this->getSession()->visit($this->locatePath($url)); 202 | } 203 | 204 | /** 205 | * Returns a type_id from its name. 206 | * 207 | * @param $type_name 208 | * @return int 209 | * @throws RuntimeException 210 | */ 211 | protected function findTypeByName($type_name) { 212 | $efq = new EntityFieldQuery(); 213 | $efq->entityCondition('entity_type', 'bat_type') 214 | ->propertyCondition('name', $type_name); 215 | $results = $efq->execute(); 216 | if ($results && isset($results['bat_type'])) { 217 | return key($results['bat_type']); 218 | } 219 | else { 220 | throw new RuntimeException('Unable to find that type'); 221 | } 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /test/behat/features/event.feature: -------------------------------------------------------------------------------- 1 | Feature: Once bat_event is installed 2 | In order to create Events 3 | As a site administrator 4 | I should be able to access the event type page 5 | 6 | @api @javascript 7 | Scenario: Type manager can access the Event Types page and create, edit and delete Event types 8 | Given I am logged in as a user with the "administer bat_event_type entities,administer fields" permission 9 | When I am on "admin/bat/events/event-types" 10 | Then I should see the link "Add event type" 11 | When I click "Add event type" 12 | Then I am on "admin/bat/events/event-types/add" 13 | When I fill in "label" with "Availability" 14 | When I check the box fixed_event_states 15 | When I press the "Save Event type" button 16 | Then I should be on "admin/bat/events/event-types" 17 | And I should see text matching "Availability" 18 | And I should see the text "(Machine name: availability)" 19 | When I click "manage fields" 20 | Then I should be on "admin/bat/events/event-types/manage/availability/fields" 21 | When I fill in "fields[_add_new_field][label]" with "Custom Label" 22 | When I select "Text" from "fields[_add_new_field][type]" 23 | When I press the "Save" button 24 | Then the url should match "admin/bat/events/event-types/manage/availability/fields/field_.*$" 25 | When I press the "Save field settings" button 26 | Then the url should match "admin/bat/events/event-types/manage/availability/fields/field_.*$" 27 | When I press the "Save settings" button 28 | Then the url should match "admin/bat/events/event-types/manage/availability/fields" 29 | When I click "Edit" 30 | When I select "field_custom_label" from "event_label[default_event_label_field_name]" 31 | When I press the "Save Event type" button 32 | Then I should be on "admin/bat/events/event-types" 33 | And I should see text matching "Availability" 34 | And I should see the text "(Machine name: availability)" 35 | -------------------------------------------------------------------------------- /test/behat/features/installation.feature: -------------------------------------------------------------------------------- 1 | Feature: Have Bat correctly installed 2 | In order to use Bat 3 | As a site administrator 4 | I need to be able to access all the Bat configuration screens 5 | 6 | @api 7 | Scenario: I can access the Types interface 8 | Given I am logged in as a user with the "administrator" role 9 | When I am on "admin/bat" 10 | Then I should see the link "Unit Management" 11 | And I should not see the text "Unitss" 12 | -------------------------------------------------------------------------------- /test/behat/features/type.feature: -------------------------------------------------------------------------------- 1 | Feature: Once bat_unit is installed 2 | In order to create Types 3 | As a site administrator 4 | I should be able to access the unit type page 5 | 6 | @api @javascript 7 | Scenario: Type manager can access the Types page and create, edit and delete Unit types 8 | Given I am logged in as a user with the "administer bat_type_bundle entities" permission 9 | When I am on "admin/bat/config/type-bundles" 10 | Then I should see the link "Add type bundle" 11 | When I click "Add type bundle" 12 | Then I am on "admin/bat/config/type-bundles/add" 13 | When I fill in "label" with "Room" 14 | When I press the "Save Bat Type bundle" button 15 | Then I should be on "admin/bat/config/type-bundles" 16 | And I should see the text "Room" 17 | And I should see the text "(Machine name: room)" 18 | Then I am on "admin/bat/config/type-bundles/manage/room" 19 | And the "label" field should contain "Room" 20 | Then I fill in "label" with "Hotel Room" 21 | When I press the "Save Bat Type bundle" button 22 | Then I should be on "admin/bat/config/type-bundles" 23 | When I am on "admin/bat/config/type-bundles/manage/room" 24 | And the "label" field should contain "Hotel Room" 25 | When I am on "admin/bat/config/type-bundles/manage/room/delete" 26 | And I press the "Confirm" button 27 | Then I should see the text "Deleted Type Bundle Hotel Room." 28 | 29 | @api @javascript 30 | Scenario: Create Type bundle, Type and Units 31 | Given I am logged in as a user with the "administer bat_type_bundle entities,bypass bat_type entities access,bypass bat_unit entities access,update any bat_type entity,create bat_unit entities" permissions 32 | When I am on "admin/bat/config/type-bundles" 33 | Then I should see the link "Add type bundle" 34 | When I click "Add type bundle" 35 | Then I am on "admin/bat/config/type-bundles/add" 36 | When I fill in "label" with "Room" 37 | When I press the "Save Bat Type bundle" button 38 | Then I should be on "admin/bat/config/type-bundles" 39 | And I should see the text "Room" 40 | And I should see the text "(Machine name: room)" 41 | Then I am on "admin/bat/config/type-bundles/manage/room" 42 | And the "label" field should contain "Room" 43 | Then I am on "admin/bat/config/types" 44 | Then I should see the link "Add a Type" 45 | When I click "Add a Type" 46 | Then I am on "admin/bat/config/types/add/room" 47 | When I fill in "name" with "Single" 48 | When I press the "Save Type" button 49 | Then I should be on "admin/bat/config/types" 50 | And I should see the text "Single" 51 | Then I am on "admin/bat/unit-management" 52 | When I click "Units" 53 | Then the url should match "admin/bat/config/types/\d/units" 54 | Then I should see the link "Add Units" 55 | When I click "Add Units" 56 | And I should see the text "Number of Units to create" 57 | When I fill in "units" with "5" 58 | When I press the "Add" button 59 | Then the url should match "admin/bat/config/types/\d/units" 60 | And I should see the text "Single 1" 61 | -------------------------------------------------------------------------------- /test/project.make: -------------------------------------------------------------------------------- 1 | ; bat testing makefile 2 | 3 | api = 2 4 | core = 7.x 5 | projects[drupal][version] = 7.73 6 | 7 | defaults[projects][subdir] = contrib 8 | 9 | ; Pull the latest version of bat_api 10 | projects[bat_api][type] = module 11 | projects[bat_api][download][type] = git 12 | projects[bat_api][download][url] = https://github.com/Roomify/bat_api.git 13 | projects[bat_api][download][branch] = 7.x-2.x 14 | projects[bat_api][subdir] = bat 15 | 16 | ; +++++ Contrib Modules +++++ 17 | 18 | projects[composer_manager][version] = 1.8 19 | 20 | projects[ctools][version] = 1.15 21 | 22 | projects[date][version] = 2.10 23 | 24 | projects[entity][version] = 1.9 25 | 26 | projects[entityreference][version] = 1.5 27 | 28 | projects[facetapi][version] = 1.6 29 | 30 | projects[jquery_update][version] = 3.0-alpha5 31 | 32 | projects[libraries][version] = 2.5 33 | 34 | projects[search_api][version] = 1.26 35 | 36 | projects[services][version] = 3.27 37 | 38 | projects[variable][version] = 2.5 39 | 40 | projects[views][version] = 3.24 41 | 42 | projects[views_bulk_operations][version] = 3.6 43 | 44 | projects[views_megarow][version] = 1.7 45 | 46 | projects[xautoload][version] = 5.8 47 | 48 | 49 | ; +++++ Libraries +++++ 50 | 51 | ; colorpicker 52 | libraries[colorpicker][directory_name] = colorpicker 53 | libraries[colorpicker][type] = library 54 | libraries[colorpicker][destination] = libraries 55 | libraries[colorpicker][download][type] = get 56 | libraries[colorpicker][download][url] = http://www.eyecon.ro/colorpicker/colorpicker.zip 57 | 58 | ; fullcalendar 59 | libraries[fullcalendar][directory_name] = fullcalendar 60 | libraries[fullcalendar][type] = library 61 | libraries[fullcalendar][destination] = libraries 62 | libraries[fullcalendar][download][type] = get 63 | libraries[fullcalendar][download][url] = https://github.com/arshaw/fullcalendar/releases/download/v3.9.0/fullcalendar-3.9.0.zip 64 | 65 | ; scheduler 66 | libraries[scheduler][directory_name] = fullcalendar-scheduler 67 | libraries[scheduler][type] = library 68 | libraries[scheduler][destination] = libraries 69 | libraries[scheduler][download][type] = get 70 | libraries[scheduler][download][url] = https://github.com/fullcalendar/fullcalendar-scheduler/releases/download/v1.9.4/fullcalendar-scheduler-1.9.4.zip 71 | 72 | ; jquery.timepicker 73 | libraries[jquery.timepicker][directory_name] = jquery.timepicker 74 | libraries[jquery.timepicker][type] = library 75 | libraries[jquery.timepicker][destination] = libraries 76 | libraries[jquery.timepicker][download][type] = get 77 | libraries[jquery.timepicker][download][url] = https://github.com/fgelinas/timepicker/archive/24f88f08a9bbf80efd081e99874eea38cb79feba.zip 78 | -------------------------------------------------------------------------------- /test/upload.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | cd /tmp 4 | git clone https://github.com/Roomify/bat_drupal.git 5 | cd bat_drupal 6 | 7 | git config user.email "hello@roomify.us" 8 | git config user.name "Travis CI" 9 | git config credential.helper "store --file=.git/credentials" 10 | echo "https://${GH_TOKEN}:@github.com" > .git/credentials 11 | 12 | git checkout gh-pages 13 | cp /tmp/screenshots/* . 14 | 15 | git add . 16 | 17 | git commit -m "Travis CI build ${TRAVIS_BUILD_NUMBER}" 18 | git push origin gh-pages 19 | --------------------------------------------------------------------------------