From e598ab0c7b002e979bf37fc2b6b3f2948a0ca91d Mon Sep 17 00:00:00 2001 From: Thomas Patrick Levy Date: Fri, 4 May 2018 21:31:08 -0700 Subject: [PATCH] Deploy v3.17.8 --- .codeclimate.yml | 29 - .editorconfig | 23 - .github/CONTRIBUTING.md | 44 - .github/issue_template.md | 26 - .github/sponsors/browserstack-logo.png | Bin 20848 -> 0 bytes .gitignore | 48 - .jscsrc | 35 - .jshintrc | 87 - .llmsconfig | 50 - .travis.yml | 38 - CHANGELOG.md | 3039 ------- LICENSE | 674 -- README.md | 92 - _private/svg/llms-icon-calendar.svg | 40 - _private/svg/llms-icon-checkmark.svg | 11 - _private/svg/llms-icon-circle-empty.svg | 10 - _private/svg/llms-icon-circle.svg | 7 - _private/svg/llms-icon-close.svg | 11 - _private/svg/llms-icon-course-section.svg | 23 - _private/svg/llms-icon-existing-lesson.svg | 16 - _private/svg/llms-icon-facebook.svg | 12 - _private/svg/llms-icon-folder.svg | 16 - _private/svg/llms-icon-free.svg | 6 - _private/svg/llms-icon-gear.svg | 17 - _private/svg/llms-icon-google.svg | 21 - _private/svg/llms-icon-graph.svg | 31 - _private/svg/llms-icon-instagram.svg | 22 - _private/svg/llms-icon-lightbulb.svg | 16 - _private/svg/llms-icon-linkedin.svg | 14 - _private/svg/llms-icon-lock.svg | 15 - _private/svg/llms-icon-media.svg | 17 - _private/svg/llms-icon-member.svg | 11 - _private/svg/llms-icon-new-lesson.svg | 9 - _private/svg/llms-icon-paper.svg | 16 - _private/svg/llms-icon-papers.svg | 29 - _private/svg/llms-icon-play.svg | 17 - _private/svg/llms-icon-plus.svg | 12 - _private/svg/llms-icon-question.svg | 18 - _private/svg/llms-icon-rightarrow.svg | 9 - _private/svg/llms-icon-search.svg | 13 - _private/svg/llms-icon-target.svg | 19 - _private/svg/llms-icon-twitter.svg | 16 - _private/svg/llms-icon-users.svg | 18 - _private/svg/llms-icon-view.svg | 18 - _private/svg/llms-icon-youtube.svg | 38 - _readme/changelog.md | 203 - _readme/description.md | 227 - _readme/faqs.md | 41 - _readme/header.md | 12 - _readme/installation.md | 34 - _readme/readme.txt | 13 - _readme/screenshots.md | 26 - assets/scss/_includes/_buttons.scss | 111 - assets/scss/_includes/_extends.scss | 30 - assets/scss/_includes/_grid.scss | 23 - assets/scss/_includes/_llms-donut.scss | 67 - assets/scss/_includes/_llms-form-field.scss | 180 - assets/scss/_includes/_mixins.scss | 71 - .../_includes/_quiz-result-question-list.scss | 124 - assets/scss/_includes/_spinner.scss | 43 - assets/scss/_includes/_tooltip.scss | 128 - assets/scss/_includes/_vars.scss | 69 - .../scss/_includes/vendor/_font-awesome.scss | 2337 ----- assets/scss/admin-add-ons.scss | 70 - assets/scss/admin-setup.scss | 144 - assets/scss/admin.scss | 88 - assets/scss/admin/_course-builder.scss | 1704 ---- assets/scss/admin/_fonts.scss | 8 - assets/scss/admin/_llms-table.scss | 191 - assets/scss/admin/_main.scss | 450 - assets/scss/admin/_quiz-attempt-review.scss | 23 - assets/scss/admin/_reporting.scss | 319 - assets/scss/admin/_tabs.scss | 105 - assets/scss/admin/breakpoints/_1030up.scss | 76 - assets/scss/admin/breakpoints/_1240up.scss | 11 - assets/scss/admin/breakpoints/_481up.scss | 15 - assets/scss/admin/breakpoints/_768up.scss | 73 - assets/scss/admin/breakpoints/_base.scss | 93 - .../admin/metaboxes/_builder-launcher.scss | 5 - .../scss/admin/metaboxes/_llms-metabox.scss | 176 - .../metaboxes/_metabox-field-repeater.scss | 37 - .../admin/metaboxes/_metabox-instructors.scss | 9 - .../scss/admin/metaboxes/_metabox-orders.scss | 45 - .../admin/metaboxes/_metabox-product.scss | 48 - .../admin/metaboxes/_metabox-students.scss | 15 - .../scss/admin/modules/_course-outline.scss | 361 - assets/scss/admin/modules/_forms.scss | 171 - assets/scss/admin/modules/_icons.scss | 92 - .../scss/admin/modules/_llms-order-note.scss | 35 - assets/scss/admin/modules/_mb-tabs.scss | 58 - assets/scss/admin/modules/_merge-codes.scss | 58 - assets/scss/admin/modules/_top-modal.scss | 203 - assets/scss/admin/modules/_voucher.scss | 118 - assets/scss/admin/modules/_widgets.scss | 186 - assets/scss/admin/partials/_grid.scss | 276 - .../scss/admin/post-tables/_llms_orders.scss | 18 - .../scss/admin/post-tables/_post-tables.scss | 6 - assets/scss/builder.scss | 5 - assets/scss/certificates.scss | 110 - assets/scss/frontend/_checkout.scss | 181 - assets/scss/frontend/_course.scss | 21 - assets/scss/frontend/_llms-access-plans.scss | 192 - .../frontend/_llms-achievements-certs.scss | 106 - assets/scss/frontend/_llms-author.scss | 165 - assets/scss/frontend/_llms-notifications.scss | 177 - .../scss/frontend/_llms-outline-collapse.scss | 39 - assets/scss/frontend/_llms-pagination.scss | 29 - assets/scss/frontend/_llms-progress.scss | 32 - assets/scss/frontend/_llms-quizzes.scss | 342 - assets/scss/frontend/_loop.scss | 263 - assets/scss/frontend/_main.scss | 452 - assets/scss/frontend/_notices.scss | 41 - assets/scss/frontend/_student-dashboard.scss | 221 - assets/scss/frontend/_syllabus.scss | 147 - assets/scss/frontend/_tooltip.scss | 63 - assets/scss/frontend/_voucher.scss | 3 - assets/scss/lifterlms.scss | 39 - assets/vendor/quill/LICENSE | 30 - composer.json | 62 - composer.lock | 2277 ----- gulpfile.js/index.js | 15 - gulpfile.js/tasks/js:additional.js | 41 - gulpfile.js/tasks/js:builder.js | 63 - gulpfile.js/tasks/readme.js | 74 - gulpfile.js/tasks/versioner:readme.js | 33 - package-lock.json | 7883 ----------------- package.json | 29 - phpcs.xml | 41 - phpmd.xml | 52 - phpunit.xml | 39 - readme.txt | 2 +- tests/bin/install.sh | 128 - tests/bin/teardown.sh | 42 - tests/bin/travis.sh | 23 - tests/bootstrap.php | 146 - .../class.llms.notification.test.case.php | 23 - .../class.llms.post.model.unit.test.case.php | 196 - ...class.llms.test.time.threshold.listner.php | 38 - tests/framework/class.llms.unit.test.case.php | 213 - tests/framework/llms.test.functions.php | 61 - .../class.llms.test.abstract.integration.php | 110 - .../class.llms.test.abstract.options.data.php | 81 - ...lms.test.controller.lesson.progression.php | 144 - .../class.llms.test.frontend.assets.php | 30 - .../class.llms.test.functions.access.php | 256 - .../class.llms.test.functions.core.php | 419 - .../class.llms.test.functions.quiz.php | 86 - .../unit-tests/class.llms.test.generator.php | 84 - tests/unit-tests/class.llms.test.hasher.php | 40 - tests/unit-tests/class.llms.test.install.php | 286 - .../class.llms.test.integrations.php | 74 - .../unit-tests/class.llms.test.main.class.php | 65 - ...lass.llms.test.model.llms.quiz.attempt.php | 328 - .../class.llms.test.payment.gateways.php | 121 - .../class.llms.test.post.instructors.php | 97 - .../class.llms.test.post.relationships.php | 111 - .../unit-tests/class.llms.test.post.types.php | 87 - tests/unit-tests/class.llms.test.roles.php | 88 - .../unit-tests/class.llms.test.shortcodes.php | 100 - tests/unit-tests/class.llms.test.site.php | 142 - .../class.llms.test.student.query.php | 198 - .../class.llms.test.template.functions.php | 86 - .../class.llms.test.model.llms.coupon.php | 144 - .../class.llms.test.model.llms.course.php | 357 - .../class.llms.test.model.llms.lesson.php | 377 - .../class.llms.test.model.llms.order.php | 815 -- .../class.llms.test.model.llms.questions.php | 103 - .../class.llms.test.model.llms.quiz.php | 138 - ...s.test.notification.achievement.earned.php | 10 - .../class.llms.test.notifications.php | 96 - .../class.llms.test.abstract.student.data.php | 94 - .../user/class.llms.test.functions.person.php | 57 - .../user/class.llms.test.student.php | 396 - .../user/class.llms.test.student.quizzes.php | 45 - vendor/autoload.php | 7 + vendor/composer/ClassLoader.php | 445 + vendor/composer/autoload_classmap.php | 9 + vendor/composer/autoload_namespaces.php | 9 + vendor/composer/autoload_psr4.php | 10 + vendor/composer/autoload_real.php | 52 + vendor/composer/autoload_static.php | 31 + vendor/composer/installed.json | 70 + .../includes/class-recursive-arrayaccess.php | 213 + .../includes/class-wp-session-utils.php | 139 + .../includes/class-wp-session.php | 225 + .../wp-session-manager/includes/wp-cli.php | 158 + .../includes/wp-session.php | 159 + vendor/ericmann/wp-session-manager/readme.txt | 95 + .../wp-session-manager/wp-session-manager.php | 35 + .../action-scheduler/action-scheduler.php | 30 + .../classes/ActionScheduler.php | 120 + .../classes/ActionScheduler_Action.php | 77 + .../classes/ActionScheduler_ActionClaim.php | 23 + .../classes/ActionScheduler_ActionFactory.php | 72 + .../classes/ActionScheduler_AdminView.php | 479 + .../classes/ActionScheduler_CronSchedule.php | 50 + .../ActionScheduler_FatalErrorMonitor.php | 54 + .../ActionScheduler_FinishedAction.php | 16 + .../ActionScheduler_IntervalSchedule.php | 63 + .../classes/ActionScheduler_LogEntry.php | 23 + .../classes/ActionScheduler_Logger.php | 47 + .../classes/ActionScheduler_NullAction.php | 16 + .../classes/ActionScheduler_NullLogEntry.php | 11 + .../classes/ActionScheduler_NullSchedule.php | 19 + .../classes/ActionScheduler_QueueCleaner.php | 72 + .../classes/ActionScheduler_QueueRunner.php | 142 + .../classes/ActionScheduler_Schedule.php | 18 + .../ActionScheduler_SimpleSchedule.php | 45 + .../classes/ActionScheduler_Store.php | 128 + .../ActionScheduler_TimezoneHelper.php | 44 + .../classes/ActionScheduler_Versions.php | 62 + .../ActionScheduler_wpCommentLogger.php | 279 + .../classes/ActionScheduler_wpPostStore.php | 514 ++ ...eduler_wpPostStore_PostStatusRegistrar.php | 57 + ...cheduler_wpPostStore_PostTypeRegistrar.php | 50 + ...cheduler_wpPostStore_TaxonomyRegistrar.php | 26 + .../gocodebox/action-scheduler/functions.php | 188 + .../lib/cron-expression/CronExpression.php | 318 + .../CronExpression_AbstractField.php | 100 + .../CronExpression_DayOfMonthField.php | 110 + .../CronExpression_DayOfWeekField.php | 124 + .../CronExpression_FieldFactory.php | 55 + .../CronExpression_FieldInterface.php | 39 + .../CronExpression_HoursField.php | 47 + .../CronExpression_MinutesField.php | 39 + .../CronExpression_MonthField.php | 55 + .../CronExpression_YearField.php | 43 + .../tests/ActionScheduler_UnitTestCase.php | 36 + .../action-scheduler/tests/bootstrap.php | 31 + .../action-scheduler/tests/phpunit.xml.dist | 32 + .../jobs/ActionScheduler_Action_Test.php | 55 + .../jobs/ActionScheduler_NullAction_Test.php | 16 + .../ActionScheduler_wpPostStore_Test.php | 199 + .../ActionScheduler_wpCommentLogger_Test.php | 154 + .../procedural_api/procedural_api_Test.php | 133 + .../wc_get_scheduled_actions_Test.php | 100 + .../ActionScheduler_QueueCleaner_Test.php | 122 + .../ActionScheduler_QueueRunner_Test.php | 210 + .../ActionScheduler_CronSchedule_Test.php | 45 + .../ActionScheduler_IntervalSchedule_Test.php | 29 + .../ActionScheduler_NullSchedule_Test.php | 18 + .../ActionScheduler_SimpleSchedule_Test.php | 37 + .../ActionScheduler_Versions_Test.php | 43 + .../action-scheduler/tests/travis/setup.sh | 31 + .../tests/travis/wp-tests-config.php | 38 + 245 files changed, 6642 insertions(+), 33562 deletions(-) delete mode 100644 .codeclimate.yml delete mode 100644 .editorconfig delete mode 100644 .github/CONTRIBUTING.md delete mode 100644 .github/issue_template.md delete mode 100644 .github/sponsors/browserstack-logo.png delete mode 100644 .gitignore delete mode 100644 .jscsrc delete mode 100644 .jshintrc delete mode 100644 .llmsconfig delete mode 100644 .travis.yml delete mode 100644 CHANGELOG.md delete mode 100644 LICENSE delete mode 100644 README.md delete mode 100644 _private/svg/llms-icon-calendar.svg delete mode 100644 _private/svg/llms-icon-checkmark.svg delete mode 100644 _private/svg/llms-icon-circle-empty.svg delete mode 100644 _private/svg/llms-icon-circle.svg delete mode 100644 _private/svg/llms-icon-close.svg delete mode 100644 _private/svg/llms-icon-course-section.svg delete mode 100644 _private/svg/llms-icon-existing-lesson.svg delete mode 100644 _private/svg/llms-icon-facebook.svg delete mode 100644 _private/svg/llms-icon-folder.svg delete mode 100644 _private/svg/llms-icon-free.svg delete mode 100644 _private/svg/llms-icon-gear.svg delete mode 100644 _private/svg/llms-icon-google.svg delete mode 100644 _private/svg/llms-icon-graph.svg delete mode 100644 _private/svg/llms-icon-instagram.svg delete mode 100644 _private/svg/llms-icon-lightbulb.svg delete mode 100644 _private/svg/llms-icon-linkedin.svg delete mode 100644 _private/svg/llms-icon-lock.svg delete mode 100644 _private/svg/llms-icon-media.svg delete mode 100644 _private/svg/llms-icon-member.svg delete mode 100644 _private/svg/llms-icon-new-lesson.svg delete mode 100644 _private/svg/llms-icon-paper.svg delete mode 100644 _private/svg/llms-icon-papers.svg delete mode 100644 _private/svg/llms-icon-play.svg delete mode 100644 _private/svg/llms-icon-plus.svg delete mode 100644 _private/svg/llms-icon-question.svg delete mode 100644 _private/svg/llms-icon-rightarrow.svg delete mode 100644 _private/svg/llms-icon-search.svg delete mode 100644 _private/svg/llms-icon-target.svg delete mode 100644 _private/svg/llms-icon-twitter.svg delete mode 100644 _private/svg/llms-icon-users.svg delete mode 100644 _private/svg/llms-icon-view.svg delete mode 100644 _private/svg/llms-icon-youtube.svg delete mode 100644 _readme/changelog.md delete mode 100644 _readme/description.md delete mode 100644 _readme/faqs.md delete mode 100644 _readme/header.md delete mode 100644 _readme/installation.md delete mode 100644 _readme/readme.txt delete mode 100644 _readme/screenshots.md delete mode 100644 assets/scss/_includes/_buttons.scss delete mode 100644 assets/scss/_includes/_extends.scss delete mode 100644 assets/scss/_includes/_grid.scss delete mode 100644 assets/scss/_includes/_llms-donut.scss delete mode 100644 assets/scss/_includes/_llms-form-field.scss delete mode 100644 assets/scss/_includes/_mixins.scss delete mode 100644 assets/scss/_includes/_quiz-result-question-list.scss delete mode 100644 assets/scss/_includes/_spinner.scss delete mode 100644 assets/scss/_includes/_tooltip.scss delete mode 100644 assets/scss/_includes/_vars.scss delete mode 100644 assets/scss/_includes/vendor/_font-awesome.scss delete mode 100644 assets/scss/admin-add-ons.scss delete mode 100644 assets/scss/admin-setup.scss delete mode 100644 assets/scss/admin.scss delete mode 100644 assets/scss/admin/_course-builder.scss delete mode 100644 assets/scss/admin/_fonts.scss delete mode 100644 assets/scss/admin/_llms-table.scss delete mode 100644 assets/scss/admin/_main.scss delete mode 100644 assets/scss/admin/_quiz-attempt-review.scss delete mode 100644 assets/scss/admin/_reporting.scss delete mode 100644 assets/scss/admin/_tabs.scss delete mode 100644 assets/scss/admin/breakpoints/_1030up.scss delete mode 100644 assets/scss/admin/breakpoints/_1240up.scss delete mode 100644 assets/scss/admin/breakpoints/_481up.scss delete mode 100644 assets/scss/admin/breakpoints/_768up.scss delete mode 100644 assets/scss/admin/breakpoints/_base.scss delete mode 100644 assets/scss/admin/metaboxes/_builder-launcher.scss delete mode 100644 assets/scss/admin/metaboxes/_llms-metabox.scss delete mode 100644 assets/scss/admin/metaboxes/_metabox-field-repeater.scss delete mode 100644 assets/scss/admin/metaboxes/_metabox-instructors.scss delete mode 100644 assets/scss/admin/metaboxes/_metabox-orders.scss delete mode 100644 assets/scss/admin/metaboxes/_metabox-product.scss delete mode 100644 assets/scss/admin/metaboxes/_metabox-students.scss delete mode 100644 assets/scss/admin/modules/_course-outline.scss delete mode 100644 assets/scss/admin/modules/_forms.scss delete mode 100644 assets/scss/admin/modules/_icons.scss delete mode 100644 assets/scss/admin/modules/_llms-order-note.scss delete mode 100644 assets/scss/admin/modules/_mb-tabs.scss delete mode 100644 assets/scss/admin/modules/_merge-codes.scss delete mode 100644 assets/scss/admin/modules/_top-modal.scss delete mode 100644 assets/scss/admin/modules/_voucher.scss delete mode 100644 assets/scss/admin/modules/_widgets.scss delete mode 100644 assets/scss/admin/partials/_grid.scss delete mode 100644 assets/scss/admin/post-tables/_llms_orders.scss delete mode 100644 assets/scss/admin/post-tables/_post-tables.scss delete mode 100644 assets/scss/builder.scss delete mode 100644 assets/scss/certificates.scss delete mode 100644 assets/scss/frontend/_checkout.scss delete mode 100644 assets/scss/frontend/_course.scss delete mode 100644 assets/scss/frontend/_llms-access-plans.scss delete mode 100644 assets/scss/frontend/_llms-achievements-certs.scss delete mode 100644 assets/scss/frontend/_llms-author.scss delete mode 100644 assets/scss/frontend/_llms-notifications.scss delete mode 100644 assets/scss/frontend/_llms-outline-collapse.scss delete mode 100644 assets/scss/frontend/_llms-pagination.scss delete mode 100644 assets/scss/frontend/_llms-progress.scss delete mode 100644 assets/scss/frontend/_llms-quizzes.scss delete mode 100644 assets/scss/frontend/_loop.scss delete mode 100644 assets/scss/frontend/_main.scss delete mode 100644 assets/scss/frontend/_notices.scss delete mode 100644 assets/scss/frontend/_student-dashboard.scss delete mode 100644 assets/scss/frontend/_syllabus.scss delete mode 100644 assets/scss/frontend/_tooltip.scss delete mode 100644 assets/scss/frontend/_voucher.scss delete mode 100644 assets/scss/lifterlms.scss delete mode 100644 assets/vendor/quill/LICENSE delete mode 100644 composer.json delete mode 100644 composer.lock delete mode 100644 gulpfile.js/index.js delete mode 100644 gulpfile.js/tasks/js:additional.js delete mode 100644 gulpfile.js/tasks/js:builder.js delete mode 100644 gulpfile.js/tasks/readme.js delete mode 100644 gulpfile.js/tasks/versioner:readme.js delete mode 100644 package-lock.json delete mode 100644 package.json delete mode 100644 phpcs.xml delete mode 100644 phpmd.xml delete mode 100644 phpunit.xml delete mode 100755 tests/bin/install.sh delete mode 100755 tests/bin/teardown.sh delete mode 100755 tests/bin/travis.sh delete mode 100644 tests/bootstrap.php delete mode 100644 tests/framework/class.llms.notification.test.case.php delete mode 100644 tests/framework/class.llms.post.model.unit.test.case.php delete mode 100644 tests/framework/class.llms.test.time.threshold.listner.php delete mode 100644 tests/framework/class.llms.unit.test.case.php delete mode 100644 tests/framework/llms.test.functions.php delete mode 100644 tests/unit-tests/abstracts/class.llms.test.abstract.integration.php delete mode 100644 tests/unit-tests/abstracts/class.llms.test.abstract.options.data.php delete mode 100644 tests/unit-tests/class.llms.test.controller.lesson.progression.php delete mode 100644 tests/unit-tests/class.llms.test.frontend.assets.php delete mode 100644 tests/unit-tests/class.llms.test.functions.access.php delete mode 100644 tests/unit-tests/class.llms.test.functions.core.php delete mode 100644 tests/unit-tests/class.llms.test.functions.quiz.php delete mode 100644 tests/unit-tests/class.llms.test.generator.php delete mode 100644 tests/unit-tests/class.llms.test.hasher.php delete mode 100644 tests/unit-tests/class.llms.test.install.php delete mode 100644 tests/unit-tests/class.llms.test.integrations.php delete mode 100644 tests/unit-tests/class.llms.test.main.class.php delete mode 100644 tests/unit-tests/class.llms.test.model.llms.quiz.attempt.php delete mode 100644 tests/unit-tests/class.llms.test.payment.gateways.php delete mode 100644 tests/unit-tests/class.llms.test.post.instructors.php delete mode 100644 tests/unit-tests/class.llms.test.post.relationships.php delete mode 100644 tests/unit-tests/class.llms.test.post.types.php delete mode 100644 tests/unit-tests/class.llms.test.roles.php delete mode 100644 tests/unit-tests/class.llms.test.shortcodes.php delete mode 100644 tests/unit-tests/class.llms.test.site.php delete mode 100644 tests/unit-tests/class.llms.test.student.query.php delete mode 100644 tests/unit-tests/class.llms.test.template.functions.php delete mode 100644 tests/unit-tests/models/class.llms.test.model.llms.coupon.php delete mode 100644 tests/unit-tests/models/class.llms.test.model.llms.course.php delete mode 100644 tests/unit-tests/models/class.llms.test.model.llms.lesson.php delete mode 100644 tests/unit-tests/models/class.llms.test.model.llms.order.php delete mode 100644 tests/unit-tests/models/class.llms.test.model.llms.questions.php delete mode 100644 tests/unit-tests/models/class.llms.test.model.llms.quiz.php delete mode 100644 tests/unit-tests/notifications/class.llms.test.notification.achievement.earned.php delete mode 100644 tests/unit-tests/notifications/class.llms.test.notifications.php delete mode 100644 tests/unit-tests/user/class.llms.test.abstract.student.data.php delete mode 100644 tests/unit-tests/user/class.llms.test.functions.person.php delete mode 100644 tests/unit-tests/user/class.llms.test.student.php delete mode 100644 tests/unit-tests/user/class.llms.test.student.quizzes.php create mode 100644 vendor/autoload.php create mode 100644 vendor/composer/ClassLoader.php create mode 100644 vendor/composer/autoload_classmap.php create mode 100644 vendor/composer/autoload_namespaces.php create mode 100644 vendor/composer/autoload_psr4.php create mode 100644 vendor/composer/autoload_real.php create mode 100644 vendor/composer/autoload_static.php create mode 100644 vendor/composer/installed.json create mode 100644 vendor/ericmann/wp-session-manager/includes/class-recursive-arrayaccess.php create mode 100644 vendor/ericmann/wp-session-manager/includes/class-wp-session-utils.php create mode 100644 vendor/ericmann/wp-session-manager/includes/class-wp-session.php create mode 100644 vendor/ericmann/wp-session-manager/includes/wp-cli.php create mode 100644 vendor/ericmann/wp-session-manager/includes/wp-session.php create mode 100644 vendor/ericmann/wp-session-manager/readme.txt create mode 100644 vendor/ericmann/wp-session-manager/wp-session-manager.php create mode 100644 vendor/gocodebox/action-scheduler/action-scheduler.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_Action.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_ActionClaim.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_ActionFactory.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_AdminView.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_CronSchedule.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_FatalErrorMonitor.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_FinishedAction.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_IntervalSchedule.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_LogEntry.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_Logger.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_NullAction.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_NullLogEntry.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_NullSchedule.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_QueueCleaner.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_QueueRunner.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_Schedule.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_SimpleSchedule.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_Store.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_TimezoneHelper.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_Versions.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_wpCommentLogger.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_wpPostStore.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_wpPostStore_PostStatusRegistrar.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_wpPostStore_PostTypeRegistrar.php create mode 100644 vendor/gocodebox/action-scheduler/classes/ActionScheduler_wpPostStore_TaxonomyRegistrar.php create mode 100644 vendor/gocodebox/action-scheduler/functions.php create mode 100755 vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression.php create mode 100755 vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_AbstractField.php create mode 100755 vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_DayOfMonthField.php create mode 100755 vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_DayOfWeekField.php create mode 100755 vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_FieldFactory.php create mode 100755 vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_FieldInterface.php create mode 100755 vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_HoursField.php create mode 100755 vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_MinutesField.php create mode 100755 vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_MonthField.php create mode 100755 vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_YearField.php create mode 100644 vendor/gocodebox/action-scheduler/tests/ActionScheduler_UnitTestCase.php create mode 100644 vendor/gocodebox/action-scheduler/tests/bootstrap.php create mode 100644 vendor/gocodebox/action-scheduler/tests/phpunit.xml.dist create mode 100644 vendor/gocodebox/action-scheduler/tests/phpunit/jobs/ActionScheduler_Action_Test.php create mode 100644 vendor/gocodebox/action-scheduler/tests/phpunit/jobs/ActionScheduler_NullAction_Test.php create mode 100644 vendor/gocodebox/action-scheduler/tests/phpunit/jobstore/ActionScheduler_wpPostStore_Test.php create mode 100644 vendor/gocodebox/action-scheduler/tests/phpunit/logging/ActionScheduler_wpCommentLogger_Test.php create mode 100644 vendor/gocodebox/action-scheduler/tests/phpunit/procedural_api/procedural_api_Test.php create mode 100644 vendor/gocodebox/action-scheduler/tests/phpunit/procedural_api/wc_get_scheduled_actions_Test.php create mode 100644 vendor/gocodebox/action-scheduler/tests/phpunit/runner/ActionScheduler_QueueCleaner_Test.php create mode 100644 vendor/gocodebox/action-scheduler/tests/phpunit/runner/ActionScheduler_QueueRunner_Test.php create mode 100644 vendor/gocodebox/action-scheduler/tests/phpunit/schedules/ActionScheduler_CronSchedule_Test.php create mode 100644 vendor/gocodebox/action-scheduler/tests/phpunit/schedules/ActionScheduler_IntervalSchedule_Test.php create mode 100644 vendor/gocodebox/action-scheduler/tests/phpunit/schedules/ActionScheduler_NullSchedule_Test.php create mode 100644 vendor/gocodebox/action-scheduler/tests/phpunit/schedules/ActionScheduler_SimpleSchedule_Test.php create mode 100644 vendor/gocodebox/action-scheduler/tests/phpunit/versioning/ActionScheduler_Versions_Test.php create mode 100755 vendor/gocodebox/action-scheduler/tests/travis/setup.sh create mode 100644 vendor/gocodebox/action-scheduler/tests/travis/wp-tests-config.php diff --git a/.codeclimate.yml b/.codeclimate.yml deleted file mode 100644 index efce23532f..0000000000 --- a/.codeclimate.yml +++ /dev/null @@ -1,29 +0,0 @@ -engines: - phpcodesniffer: - enabled: true - config: - file_extensions: "php" - standard: "phpcs.xml" - phpmd: - enabled: true - config: - rulesets: "phpmd.xml" - eslint: - enabled: true - scss-lint: - enabled: false - duplication: - enabled: true - config: - languages: - - php - - javascript -ratings: - paths: - - "includes/*" -exclude_paths: - - tests/* - - includes/updates/* - - templates/* - - includes/admin/views/* - - assets/* diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 11adcfeb61..0000000000 --- a/.editorconfig +++ /dev/null @@ -1,23 +0,0 @@ -# This file is for unifying the coding style for different editors and IDEs -# editorconfig.org - -# WordPress Coding Standards -# http://make.wordpress.org/core/handbook/coding-standards/ - -root = true - -[*] -charset = utf-8 -end_of_line = lf -indent_size = 4 -tab_width = 4 -indent_style = tab -insert_final_newline = true -trim_trailing_whitespace = true - -[*.txt] -trim_trailing_whitespace = false - -[*.{md,json,yml}] -indent_style = space -indent_size = 2 diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md deleted file mode 100644 index f99f376505..0000000000 --- a/.github/CONTRIBUTING.md +++ /dev/null @@ -1,44 +0,0 @@ -Contributing to LifterLMS -========================= - -We welcome and encourage contributions from the community. If you'd like to contribute to LifterLMS there are a few ways to do so. Here's our guidelines for contributions: - -*Please Note GitHub is for bug reports and contributions only! If you have a support question or a request for a customization this is not the right place to post it. Please refer to [LifterLMS Support](https://lifterlms.com/my-account/my-tickets) or the [community forums](https://wordpress.org/support/plugin/lifterlms). If you're looking for help customizing LifterLMS, please consider hiring a [LifterLMS Expert](https://lifterlms.com/docs/do-you-have-any-recommended-developers-who-can-modifycustomize-lifterlms/).* - - -### Ways to Contribute - -+ [Submit bug and issues reports](#reporting-a-bug-or-issue) -+ [Contribute new code or bug fixes / patches](#contributing-code) -+ [Translate and localize LifterLMS](#contribute-translations) - - -### Reporting a Bug or Issue - -Bugs and issues can be reported at [https://github.com/gocodebox/lifterlms/issues/new](https://github.com/gocodebox/lifterlms/issues/new). - -Before reporting a bug, [search existing issues](https://github.com/gocodebox/lifterlms/issues) and ensure you're not creating a duplicate. If the issue already exists you can add your information to the existing report. - -Also check our [known issues and conflicts](https://lifterlms.com/doc-category/lifterlms/known-conflicts/) for possible resolutions. - - -### Contributing Code - -+ Fork the repository on GitHub. -+ Create a new branch from the 'master' branch. -+ Make the changes to your forked repository. -+ Ensure you stick to the WordPress Coding Standards and have properly documented any new functions, actions and filters following the documentation standards. -+ When committing, reference your issue (if present) and include a note about the fix. -+ Run PHPCS and ensure the output has no errors. We **will** reject pull requests if they fail codesniffing. -+ Push the changes to your fork -+ Submit a pull request to the 'master' branch of the LifterLMS repo. -+ At this point you're waiting on us to merge your pull request. We'll review all pull requests, and make suggestions and changes if necessary. We're newly open source and supporting users and customers and our own internal pull requests and releases will take priority over pull requests from the community. Please be patient! - - -### Contribute Translations - -All translations to LifterLMS can be made via our GlotPress project at [translate.wordpress.org](https://translate.wordpress.org/projects/wp-plugins/lifterlms). - -Anyone can contribute translations. All you need is to login to your wordpress.org account. If you have questions about how to submit translations please refer to the [Translator's Handbook](https://make.wordpress.org/polyglots/handbook/). - -We're always seeking Translation Editors who can manage and approve translations for their locale. If you're interested in becoming a translation editor for your locale please submit an application at [translate.lifterlms.com](https://translate.lifterlms.com/become-a-translator/). diff --git a/.github/issue_template.md b/.github/issue_template.md deleted file mode 100644 index 2279531d2e..0000000000 --- a/.github/issue_template.md +++ /dev/null @@ -1,26 +0,0 @@ -### 1. Reproduction Steps - -+ Include clear and detailed step by step instructions on how the issue can be reliably reproduced -+ Include screenshots where applicable -+ Record a video if possible - -### 2. Expected Behavior - -+ Include a concise description of what you expected to happen (but didn't) - -### 3. Actual Behavior - -+ Include a concise description of what actually happens (but isn't supposed to) - -### 4. Error Messages / Logs - -+ Include any relevant error messages or log files - -### 5. System Report - -Many issues are the result of theme or plugin conflicts. Including information about your WordPress version, your plugins (and their versions), and your theme (and its version) will help us resolve conflicts. -We've created the [LifterLMS System Report](https://lifterlms.com/docs/how-to-use-the-lifterlms-system-report/) to help with this - -### 6. Browser, Device, and Operating System - -+ If the bug occurs in a specific browser, it is very useful in helping us track down the specifics using this information (as well as version numbers). diff --git a/.github/sponsors/browserstack-logo.png b/.github/sponsors/browserstack-logo.png deleted file mode 100644 index d420b929841e7aa26d4dba4845059e12a7e7e640..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20848 zcmXV01yoyIvkh(qg1dWhD_SV-P=dP`cXuf6?hXZtySux)ySqC)zWy&O$<4}I=gzq^ zvq$!ske{+*i14`Z0000{LR=UG0Dy~p{`P`}{`~%`X%zT*fwK`;vj+eW(Ej^?0aDYk z0RZ@BQz4txF$Z*8Ib{HNsI}h^6WkqA)1&Nhdr|5()wuLF!<2|1e(5G zSi6!HsD}NCb?4bbSX zCX)fWR4Ae305*QWCA#5d0H9V7kQ|edK?a#k01XI>_r8|+z?wkMr^?DI-wkQ`)a8&| zJT1meQul{@bzkU^Gd382UI-H%3ZM=U*HV@Zj-{a4LW!e81(&u9B&BwWg=%V-h@;zm z36QQPrA_1+@>rTxi%G{~9jZ>J&i6Je_pY7hPrxc3B}P)QOQrVV7<$5CzKTny3Ps4; zT`fI~E+Wv$XHXEPVJ#d2k9Qs&&lslMlrxGp?uC>wlKS}zSn&Kr>nKrbr}One-c7PE zX829fHXAfC7N(q;FrpvtM#;}+#*`XqZT7Ez^77NAvGSVlLqF;b75^j8-V^9 zP>ff|Rzm`))Agw-go0OF_YZ^sbV5KW`ob+|BlqiqecJ?#Zz8R4B6k77n4@74egJTy z5m{8fjOekW3&2?fp8W)K*JYgTBH;w5w?Q567HNd%*ka)I=fn0-Vge`9{UQJ)6%@k` z{-*DfOgbM7(JjD>;!TboB8VDeNKOz#3~$I)jY%UQ83X?Zw@A!OM3&e%W<;FBj_61% zFs5M;3th;R8f{K!Y%+x!W-ph-G%w#%-pTnPEVvLbcD8M~9V%&!Knur8gi{2q}Z z!F@%Ts2YL4VMF|-yIH!SyBP%0axx}mu!+M_Lxe4J*{A%l1$NQ)dP%osw*|Iww&}Nt zuh2pyS%|r!!Nn!W;Y<;W!X11ZQXRr>)7eCo$x@PEARzz}2zLSI=LDt0SzFcMNQ9bMtqre}=w;I8K@iVhhIoh5L>x z7$F$ZhI_yUjg8%tyfp%3nrFFZW?+I&fh^#P8yGcAWI|?cNhV9hO|4XvMV=rFfgxmmt>#Npvsdxl_cW&vR~ z?)Yq$r|>~CEB~S_tEfZfqxQWLtfzD4hhgQ|W_TAuJ!RSmX3fab!4g?ubD%&Ve2-ZV zLk}~VeV%F_yQqw4R0K^w{tnxYWj{eb86`BO9_5G(t~6nCtPEEHP63ZJj|_imN?Ko9 z8LK%n9?JsDLCQfIM>2nPwuXxuUG?9pMgxh;UDaP|=hdyI0qR_8Myg8cYn7s98D%2# zEu}5So5qdf(W8G;rVNB?ww8C7*cNYBsx5>p7Z&Rm+cQmBSWWj6Q!-dPR=Acz&hD4K z*Dh2d*XtN;{Q8*h8W!06d1NyXbB?{)I9xS%HAZ)$R#f9OaqOti8NgL$e{A!-f4WU) zZ{B>1k5`bUM5A z@(bAo+x7B$@%LxmrOcsBe)oG<9Ji}Bv(`*EJa>dP^R_H|`lggsztsgkCq9;}9X=w@ zH4l}?`WHPfU#~tdt#{n_s&|ZcIq-1sX$V|!QSc1#B&d3rEkD8E^^kX$w=Uq?->u0P zDO^M@pMdJ(4&ow%Ge1jys+nkD<6`31v!BX0nl_TRQh<}XplFa0ilvG%guYrL>B;V< z4|7fAp5`TrIf}C8Vu=z3zXNyBYH0TLN<~UZ>&ax4W z8`e-p*2-7o;rwfJc!WOW(0AU6*5OvUupLYyt=x9u>fL2fN&ZO^-vsjDhY^ldimuv# zUC&-g(nG~&`CsjjQfalNs$mzUt>UiVoxhvs;^)*#Dk`cp6q@(nmLKaZ1Ka|j0wDMy z-zR_m0g=-ls~xmkO++;kiSRp>Ics*33ZasUu4_IML8vD9Z<5w+Il~=)A+v-?2 zG(N`Dp=_wQT6SAxQ9NCyu5)LbWV2AVw%&sGaCk5{rXuOe#%Gokjgw9ZjP}4l?V|#NL|c zJ?+f;MGiN!lsDhiY{qo>sC#C|_}@U2|}WzYa41GQx22djSAZCJA8yMVIB% z4A*1=k){v+HP8AKt{Mu~rKDkS@=`rSCSsm1Jfx(=zp;eVjk$AHg$QX(Kc8fT&arFD?T2S7`UwE(V1e^&I+>R876+i2ut-Q~L@ByeIJtY47fCI2X2r=;f zXu&sJ_?WE`= zF-1txt;18L2P-A?RIKG;qKN%6PUA`A@uLsNzkTSN(I%=T_z8!?3x5k6&&0 z{F3_W<7S!CAXLYo$;AqNrD&O9iBzWuw0~aV<#9jOn0WRCnFZ7QCo4xdhKSjL?owv6 zH#`7@`%3{}Ztg=eK9yIe;Kv;kpyZESJVb zl(IR%UO{(OJ&>2DVK)0V+14LRvGsSk7EzhCYHncqKP5_{Pc=4L;a&=Df;ZSHXGPxW z0ZW`+JOWFJRlyKP0Me6mliQf;zPx_maXs-Fd|(Fpj})8BpWC!IJN&oJD!kC#{ysSD!T0yG+Z2Cc)FTeTM=Uz{Eh_pw3TO1XWEj?ovJ~qDOgsA#)-W~G{XV1g zRSvsMMBfsPyL?6$tw?Z`OPYE| znacIb5isa-N9m>xmuP=X@PR$=)f=GSg^f{JCu-&!<&5wDl&XVPY4&O%FL# z>cYPC+;smmi9c@WKa-s1=Ki&{&4BiRYYdP^F+!UEMqsZ63wmN7fEQc<6KF<4n&#ox zWeh?TqoO2!cKUt2fEr&W?#9q!ijr|SK!uX71z!o?$g93_8HyYEzdP#Z4i0hLifu~E zk<6fXu40d#c!XSW6AT0{I;lo09u0CE;b~zeNbM+o$D*nnvpaj5Ml%bhD+T8%KZo8F zP1q6t&!eK!gG*j^p({fVW1{K4r9@obfzAj4zR?^?Q3j{M(UoLn zWA;qy3*RY!4gWO^&Mb*YjjZmEVCc)zOm9YbTzI`Fygb+}&^_22Df<$FoBL0X;Ux02 zjg99cofEI|?EGK!>V7c>>nkAEdvFU{JdY2gs?$pt$btGZ|J>qy%Kky7*FE2kF5^k5 z@uJ|+N53Ke4xIs6<_K9<7jIsILv*a`F_=sFMTvyALY7u5!*Dy}4RR%rp(p_PZ}w?8 z9K^?wN@r3+R?I&v82tE8_br$_wW}IHOL%=tIK#E>djrARbb>DUQ=ni-ryexCL5Y8+qBEPfUT;lU_LqV?&o_tah#=_cztHBUC*+vX&LLT86 z3?)aNKY>H8p)2GZia`KZ-&dCFm?(>!zmE{FDm4|Xpx+q|3R5$p+`?bYE6$8kczJjy zA$c__lp*%ml(kZu02ov2{rQI>YIKo^uoDKT_f09_-C=S`x0+FrZ1{|6Yjyl1xu3r+ z;A)fR&#kG@aNTVhow>v$4pIA>zM~s8Ytm2sHfYsDTxrIt#hUIvY*Mz0)!+K!H}3Us zzZ~Lgem0UA)NV*H0@I zq9l{Y@4!dnc|U0;qq>f3thF%Mv;tX%T*UMdC@|tg-!lpdbH$*{p~J5glA%=ao|CFH z3aXqLfl$=sBWSarO30@Z{hzmB{^u=LjGGwQ({ir%maru=9Z!FBuq|FeT%LP{ClKGU#AZ{n$HlQ1OZp-rTHBwG@&I zJ*e*u!RY*92>v}$qQYp(GQ~jylNlja_0T8Bw7r?B;4Ca(1Xj)b)Qx^|xnc@+2Ainf zLoH%7SoFbHAlI6Tf7sZto?uD@=u@LF$wwq0s4FAQ#(8r z8|Xr`v(P0(W9?t$qoyFfnY zNb!W5y;&fkyv0ei*DVA7=Hg51p${~SVv02FU6Yc2hcVgBbsd@!%`)~+{xK;ZyBc*E_`wK=M zdL>PQp}|*)pp-0DC)Jr`eaK`h?0D0oF@C)hg0Exz1}iyEOeLfG8iVo^bO3ep{Q zSZy1apq#eh;7krKt*M$%!5=?+{$DWae}ebHtpP?}!x}3NqwIP*h?T!9uf65+-M67| zMl22`svOLD&6#iYSh`?}$l*#Z+r{D#{hEA%4+0Pd#%fv?To`H!s$tFhyp6D*snk&h4q;w z#SYj8j8>yDIJemMUYR7LYyHwJ`l77~jah58R{RSw$~cJkIo&ib63iTuy_UF3PziEa z473JAh;HJd=j?+A9uE4pN^=q&w>+ZpKjnpzhx*|8eBDU>+vAhmkOumSsyC+e5t1Lk zlDM>*rY{u5?>l3a+KL}GWgelqPKw~dh;z`k8=2pZK6iUKP)OfFpL2Dgyk_rRZW!-Q8Sh8i417FWpp`$7JnZZwuKN`%Ch za5i&R1-h^SUa}9eG`?(yK9=yZlc|+d;(6pNFW5k0^seH+lw79JRZB0EH3#66cj?@U zlyQIP7CB51+O^N9N$IG5%uLn~uxnc{a2ckz4E?>iB*v)drBRE^{n$eiyqPh}I_i|^ z)MqdKmvILP$3)P-1JchlfOp5q7w%%|bwqZ=<`u7@<|%Wse58!^DU=nx215854QQSh zN?$WQqi35F$PM1wdHR^ZAq%7nKZ4^-`CAD`U=7!*>>&j1VHc%BoRZ(Qa7NCxOsmCa z*9_6u4OwpXt(bDQtB)Wl3(w5aIR7g`igB0!g+ugz8H@+0nkgf)|4ghL*5bk>M6&*T zHAXJgZ^U5GMTYl$bazP+s)5Pa|1!g^sM2vuO%b&wRNBUVfdnrq$rQz#vOmMn1s_<= zeea_iOd|@Y#7=5vFRL?ok>M7*_ywF27wYvSpbAK38E z#omW%MQ_JS&8j-h9_kA$xL+Jp1R$McbG3=a=d3BVg&^gJo|UAVj&2UUpNs?`QGVoh zM9t11vt02c{k$7SQzLkhC6$db0>kxup0ZjSFt_B^PFhnZ>SiH+x8h(J7Z=;+IQf5P z9{pG1SZwa7ndVvs9yk#eO|#TzIusjg5jjwNAF&XpF#YDtr*}r?41616?@j%Nm7j;& z_8r^#Bb)|tLs05*BrP6%U9uN&xNt9r7gC?Gj^4U*bUqMYI=|#33`_ef_Az^*>`>+t zssXc?|DZ~WEbo8zH!UHlYVN!(V<7Q4uIh_(R^Iv_5rwRl8Qaxr)s)pO>p%Ii(oauy z$x$DOtP_^JuR!+;8OjY8sIL28I(t0QaS=u2m?Zkk>*YoZcP6!cYk3dLk;uN#R}al= zp<`eS3OySC{QG}kg|(5WPf%T1Wsk>+oOH-_#?6S}6TDpbG6*W8*p_ZLVy>E_4Xm5d zC$OA-?O;S(BKJ(tNs*2Q*I)L^G}<_Kz!C{j&p3Yr?_Idxu3|lR99I8V5r{x-W+6@)VqSB_((TyGj{CCuQgbs1RJIP?O-$CPI_eBC3#R?A)Y*#a zTA#`qYYt?%NT^RVIBD&}m^`g|=nE>^6?31EYkzy`ov)xbJ4kn!mhiYcE=l3ACJYh& z&A;KvvC*~#4U(Ndb&=z!Yw*e#+jxyIUVLv>{GH;98oP`RJ}|>ZOdfn45o%6KP)a*W#%U>+c_E~FTq6jML!bH(^Iw2$@#T#7or9d`kbVQ7Av~+58 zs?+4BKA<;+{nyE$`Rr7ebspPdiBzTHy8SvoDl0?9gqzV~W9L@RJx(H|c;6opIZLk4 zu}9Q-olfF={?KI_q)5^pPNdf`d7P_o($q0$jXQ5l8B1z{Ila@sEc+D-Ux3o7h3-h9 zr;yb@8~bIV7J3cgcf8eUPfuk7kq!8zVGLFIh|dLjqdLMNq??b759B(Sc08zDKB`=> zY6L!q+6K&q*#=#A_oqx4a9gJnt@8~uOgUF$u)WTY0GmYW9Szdvr~9;L5*-=N7 zO4r&umwKxlJvANp3g`S5Y)GeEi zp=>P{3`j^0NPDusPwwO@bR08hI@11^rYP|7)F!wCko`o=}l8*b6_xG&d>(P!V z{<%+4yWR#)p0*8XoY<&@*85H9!w?IeoZSLPcr`Yh*W{pIlf-(k64NSEzqRT-a%$ z|CsRV_Q%B9TH;vgJiXl0s;m6O9!|@nDiXN2ZTsnG7k`K)Yz$}!*F{V02IhU}w%%93 zm+&;1hvqh?N8U4mZbOHlObw%qKyA13pb%ks9)pSRZF#$yF0Zx=8?;%Tp8zs4JzPGm z7RE`lh(5kKvwII&)8$P9bf~<8!}tBg65jD$0iz!g;_jqVmJ?#9mt;Unx_I(r-X#$y3z>o-r<6 znoSf)gn`L0_~9AK`_h*VYp=iK?edxtLrK&>*{`)Pc6av=K#{9svkfJvyHQ7qs!Cj= zDW1HVnwh%?{#7rYv~QMn9sB1D;2CA)v;)SCiKmA$0y^-LETzqNBA(vl1aobM@}{-z zInMt5%WgDA^CPu_!A*>p_0D7ip?vZY-B9Um9S|aoO08*YQslqd)=O!EhW+EOQE2vXI@|sDqWJ*rrB=S(GU#UsH&cWaT&#y1FlD^S zPkq)FvAP)i1~1hrIz~rfj7U!p3yJhQ*B_6_`g}KJ0h-@J5zW-+&+JB2;;AQ!+w%sF zemxKYd(xv}pFIs^Y-cA<`N1PeBbow(hTiBCLqm zC>z=i7+s^XBI+xbMkYG90gRV-=H+@@-2n~`PS;T|M7x>p7ZeG%9hdpewZC5JbB!58 z>zmTKm132Y#KQNwzUEtC2x>;1>1_7VZ9?6BX1BaZKhO9lA(97%I1nEUZ(*}Gb8hZn zZEX7kA`P-Bq~r9tcfr7OV3|;JOH0$c_d8XGr2ZR@cPMV+LG_NVo2Ewth(ax-G~lzy zIQnF$s_<=X8J)DzDstGhzpsBPQxI1EH^GmsKJ(%RbTW!i%1?`l4QIsTkm<(16iY&w zkwK@q1zBmJoL&$qWEA(YhBXf9p;gbic+$A%vt+z7lc^~wg=S1S-l-B)f`-45^or^( z-Y~$Cu<6R_TI-SmyY4e|km(qO*}``Gn>$?@XsbLKpDTr88o;f^X;$RXk24dw8IRx~ ze%11wMxWh*hTHY5sLGzDtTzO}RMDV^6F{vU|}w0zN7n0{5^CIWVg29y?lpRTy4~S16a^3bJD0w%O|2 zaBQbOjgbLToDt+>$CtO|pfk3WRG~KROY^9gIr{w8MPtt$AN$I@IHUmsG6Rxc%uU2i zqtl249fsS$T)|+qMUAWUE!gd7u_w#LBYHx}ce?!5#2r`f-!GV$QQ|b-JlU`K2V9&J zW6Nazs)(y_uOP`KmcxVSiG3NEbpqd{cMqpiz|Ui$-ZL`)N1Z^o#qv1NddyzafgVf` z{_hO^ADsH%(+e#4C%=^Tj4#xF;W6rZCcTxQu)(z9tG7-}%FmO7y~4L4vWbeXw)Yn? zg5_DBqJ`>B0}a1Gn9N3>43~xFQ{zkq=Qq=g~OZKBGOYE0qVxHzu z1#z>6=ALTB-`hiv?7|RiS zFQPpwd*}`>SWabZI}lcngz(3}#_vpU`vm3vz$9-Oaz?-eEpql zoA8^Yx>lG65uDw&%{Sp5T}2lgofEz-*D}&a9zQ%rP|%lJhoyWJ(mRL{NW73%c~LQ~ zj5FW-SQna6dSo|zB1K%sjlcX-R=5J*Ql!=tm(yj-b(p$~&m?DC zju(ypNzof0)kYt~9WfJ!wIzNpO-t#1V9z=z>RX52lrrpKRKU38A?ZbCnf;F8g6nQD z+;)8$+cduWl72&R(XYjK%)>L_+k2A}I74c!i2iYmCe zLq}$0`GzX!v4UcMuz!n=ocztVB;!6^gPgW&rjx@1KG#>+R|5x#y(R4Rgd&=SAvhbc zRU~vTUvbj^uu5r#%ay)WP3IEpz9l!{;pRV@AzzkQF;x3MZn>O#kQ%Fe_Hud6X6*T6`ZvMj0-I>(~M7<6q#mpc8YtQT0O={bUzu#xJl+MOa&5q_dZD zR#9{K#mtaSKfz!;{F5=8+nYO=gFh_3Qu*=7p0~1NC#59LCz{qC=JQJ9;kfb8(03^X z3hL}u79NBqxSsYi2R*#iEYflwQUViLgX=%O_Fo!as~w2!_F1}S9@m1m!e#>6`ToAW z=)Qo<(1Ea&AU@Cq|BT_E)9Jk~iG5%4nwop5?M#o`ds|0yr|FN_0}a>VM1DYDW{D6c zl5C1vcoSEgz;QCB*@rG>S|gBHef_B=#xo(v*LvFe3Ul2!VK7paRF#D#=+Uj#zk;!t zSa{dRh!F`)N$+EIM!Szyo9d^!%+qsG@xbvO$<9gwowHHxQ-szA?>&c1VQ54p8iaA6;jQBa+Va+2mM2{|$Saf5f3+-e$9<6wydv6$X zRWR;)xDc)2r{UTlVsr{UMzs$mpl*VZ2p2@agjM2*<}E?V+B2S_FP}xHt}ipHZQk$u2y9|s3N<^CD-WuT|QA#2izt%#&H`Z z$zNp)H>kmETsq)&XSP{msy!-^wGpUV$HIc(zmdPCJ$mK4VciI%;{m5bGphGRv zZZ^Q9K{hsuFqReZQOb~TgKoVXAW)k~Tu6$12D3hQ{ju!Lucztnk{k0UMZ?Wkx{2Pe zsPv#L_M9S2@{>#KA(-asda|?bi?q8A6^DgTzz-Wc`oi8-NCvG*moJTZg!|1v%)`Rj zPP&1720lH8^7-`F>CgEsU0$c&`4m&iT@1nC2A?;rNPbyZ`6DW`-YT#3tr{&y!Qdf~ zWJjc-RLw{7{8AmOQ6Z#}u)J_%*!>3daj00VBZh2z=M}qrx!zFdTaePh&e_&gu zy2VC1MyJN2dv@8dE#ab1hIZ#*O;jtXhjo{egYyl9G`Ht>CbOF56s#IoXB~3?#(5Nj zl>P(qQ=@$g6UcfoEZOcXs8;01Ck zSLp@S-NJry1`=?lzDe0PItMdcz4XPBd3Hj9h6SlS&3ht&&BnTfqyzCCK%V&LnZ^A} zNSpJ`J$#bhbY&3I}Hlqc$FFM>+%K=PZXS7Xeje#-X)+*t9Kv(F6=b-?%(`w6hQE zjH=+YZHe5-2!ACRwhnIk)Y6s4G9i?6u-Ny#NcQa-C^w|$^n-_TU)SLDZv=s7qi%3c zY-wwHutb3nU0zHFMs0O)42#nx-7@*psF&u*M2Rk z{D}`b(4`NBBf(^y?SABzEk@k5q%q>{2^#b`FtBA_pK1(bwQdZ_Jh?LNTi*?z=#Zpo z_+qx;aC+EQ!dh$k-KIYNI)W4~H%bpi%jL;*jV`~H=4RLUkmj>^6_z=~HS3?G3nr&i zcV9PhyR%hO;i;R|RZr>a&mba8lsA9JebTZ@rlUSOIc?1Ze%JKZnw2&4Rt+J6LnwVLD*k5 zwzkf5=03U$2Jci7{E4!oe00m2uO%Y@I}3!io<=FZ=~oEV7T*6y?-OVk{$gEq@mQ}6$7h)3YrM3IYl z3>>_C{wlLu3*Jl{lFQ@!7D^nv-Klm2DW5u&Eh6dK7Ju!_hHMVEPLiWbwZlW{M~v&j z5R&0?nZ=sr2?}h1@6hR)9Hy+r*nEw z&7MIX2>?2OawUt0MA)gR}$<%D;ZSW|o+-S5+=f*U=R=3pMwnpb1)R z2q{IyGv6h%;zS7l8qG1!>Tx>9+q|Zc7fkJ+x2zC|RAZ51HAF(TltN+p;$+Wqsc;#|cGRW)d~(NyLYZ-L4}URB0G1GuV8nyr@&^$pi0>mNdiceXdmwK; z+knPy2M3D?j(^0J>nxrjzxETEtS~$a*S1mmAF-f!?x1~-F_a7K9Y&(}ulbtFr9mo^ zP3WA1LE?<)Sm4(1B$0%OaY^yjT9QvTd|uJAAmIxCR;!VCFaH~?Y5G0a+7q515%Jey zearVf5?)W_>qijh5PT=bae7+FFgNC2VKhdVRYJUyDob=vc zMl@e~tTCB1?WX2rHP=y$G9rLurZu$1+Q04Luz3v4bGjL-gn-7hk_=v=TD3Mq&ZD4; z56Fp(yb{jZO(V$~vL@%HyZ0+x!~m{pzIHOVhZq6(%tSh#-i}XW6W{O)k!Buw7lXt{ zXw;|GFmI|E@Dq%+lld`Q{P0f>m?P&5&zM%@LORg|gJ+f;U3zvNY@p@kBhS$G@4&8q zMLyKmsbZayFM5s+1TCRjJizO$+#I@@QfFH4)E3_!6kAq*v~jEp+dpVD>3B4C{l1E1 znRM9q*mAp-HzcV#W+eVbeR40bM>1Yir&5&Kyq?WC_4!~JzPG=tYiWFyafPp995=6| zx!kJ%5Uprx!Xn+s@0a7Bcrh*9@C?x>x!}7e4j|0QuzmL<_#PLDmM%S%a>)WiRV7r* zx^|NN z`#WF105?+C%7*Q%CBhzgxF@!|IR!^16kkk4g4BYPkZX{=X~M5%tBh9HfpqGX%)t|U zcO_^(R8fkW2fcZMQ9Xac#tNSwGj%hUFX6ZZ zdY_ZL9(vbzu_&E&`ptqYZMb@F`-uK%P#jb_36>$UJuXI#~k|1G1}*+Ju&t^pib!eePmMbFP`cDDJH;a2#8J`k+AA zKS7l@L&D!n1&%xn%No4O}o9@MJ!#8E=?Z+Srmt zrdIVtae$RnqS>`Wwo} ze*gIFrqRJ z4~>m5Sa)~25`3k)R%R51+kyet(&veP58lv@z06Nc1^Gzo}MkA5D<7I^IA(v9R^ z^=)lPbFny5rnNtl(HRVg^>>E?Rix=Zs6nIEpi)au>WZ6i1PyG{QX7nFqCDPM^Exu- zrLtJide(q&)#Q^t@3h#J94raaIGM40j&NR9o8R@@^PPcFvVR7o)umM71f0@)_(+v; z4BuHt8ufEweDzAv%Lhw5mpm*=0?5hOlp@r?INHfQg);ri;l@yvoL^+LI2C1T0Pq2v z|KTY3g39leLd5Hy^1x;FuN3?N`TOc9@qonv#4h%!aBkN96*EgTt(ZDG90?K_L-)O7 z8b^5H{ms@SS7>0T>ElMo4$~>GEdTgEBzNwNsY(13;YcYIuy(omIAWIoF3$%-IskxS*bt}!qj3x2{zmr|^Qr08>&Bx7) z@Nlk38=fe!kJG&IV(noIky`LQHKNVi=~r3&hMSiPj&_WtdzbZtbWIjT^aM5vSVv0c zV*6!<$^_=nodbIcCrUj=S)%f_;kAzCqe+`z#C@TIsZSe^9^;wRPJ>BxN znHCJzsHE2p%A>}l=)9fJ_q$GOi`024~z5aira5xZgTj>Q>&%O@Y8k8~N2MwlKsOWioul0c1X^N|H@b*tv_ zZc`@(n`2PO-H6*~V?$>n@-0^!x*uz>Ti=Jz_HUg@M}rgQiB?rasa1Q2u1cvXQ_1S) z?NWl~Tj28L8SFYe=yqO}9V;92YxplTxqB|5?Rybc=12>v~hLd;n zZd^~y>RHUxeOA1AVEpfKErRPw8n2X(h=7yYpMbn-e?{YWyh3xd*hzGs-AJta)4GtT z+{yZx#V7EoOY{OoLbb}0d7mO9XoUw1kJEjks+_hY6~acCr)gG;mDU*H)s@&{Jm{P& zH1To%;QE~jAtIHL)@kCK5paAEN&)4eRe;&4M@;`X)=fL6mfw-7u>75Sn+Z+W56f{u zr!`fgHPEo7U@)e|2NH*wXk(F=^uyj0Qi4ZcO8m7ENiU3Hc}$7l$lHHIwBov2X7-Mk^Miuj=mots zNwB#;{mN*x>6NANl_eH)5SjdBp)}XE?N38P(s?@{NEAS;DVXhqny-(9W_%&QhOVnQ zscW~GP5F0cfpBKJ=J%Y8H>3DVVUoH(bldrDqsU!LeI@ej{wss0HCD>SE1guhL*PW& zqFUZsd+oK%g!W!ucoy85)wEcO<$;A5dJ}!d_lz#MXRlL-FGrj`D8d7q=fHME@0Yfw zHez~KhIM_k+78we)T9KuZ1F8iK(OaT@*~%&|mNJqaym zVUHT)9zdR%r;hZ~J8k`wn%zX4wTX96v?>KqxTqIpz9yZ&D%9(2-YJe?a9Hd8K7#NG zUhL;VLmO7QViR$FK@oA;Y(LdhDq?9nf%P5Kh(W7|u)nZPP;Vt&oHNHpmzP3CcC%qr z?!D#@zb1P~`-9-z*^TvvRE#w1fv?ed@9Bq=Zv7R9UBMdI7!-#TTrhR5eb@u8A@k4F z+_~~jAV~$-D#8a|-I@TPDB%!k8)#MI58QxUj}~F>Av%e0Q4saBMxd9A3~UuiPm%@H z{ksK~d+h}Yjgbz@xjY_2nkl!=y$+zf%N>U#W9dbRXe=3qT3(U&b=TC4sGvUmV!pvD*zMGYHgrov)JJvjh+@}u{#Vf-Xbew6_{j;W_1fbH@|&L?>ou-_ zZB4qe!VwjKe6LSducPMgg!xL;iKdtPa8`4iC#@)3Nf37$zbKDv%N$=GnpFS1D1RRMKK6;2Mb^CVBs!glM>*|iXeQ68t zfNdKlmQ+y>O`Zj9{DF@g;`?G8sJvgNdmbSGXzUh}iv{+3rZ~qZMeCLZF8CBEu;mrj zj5V#%NiVJZZLO!cpaX+Wvm-fKIW$4$p}P8L{WpCI*yvY0+(07BaD}RI%ue5ByIb+` zE`XG?@6c`9;)<6`RriGYE7RqlD3-7QAcoq#(Ch)^r48oXJI=#jzJ`z~^O-@c!PAvp zqq`Oz$&^98($P<@oz}mx^~b}sc}PC(n3OTXrV%tUc*iJJMIun&nxt1tF!*MmlU4H| zeB{#SB zJTFi*WK>@+M|;A;w^x6ejDR_86o~t;8)~{oaA6XR=ZkQpY~L9>RfT|Bz0cy`b%*K_YYX>YPpSoz@I0_%S8Km<<`F8_?r z*z1%mXN-{=U|Hs&0(&JwBJ3J@01HRbj_^8uK+@21YJ5P^Ujw)Iu(QKS8+1|z#uqbS zdBw`-P3_M~9rkSuG83#lDr56@5*#t-VU=Z>=Vo+oF{aW=8q8{lI`osPEjo+SQ$_z4 zsz%E^Rd`{NWz|g+b)Vhj5#`kP?fUqcsJi`)hR*!f5WAriov8l%P|1lkjW}U$*Qt&v z3+J}?wA2dh{URxd5e_vyy2gY(Lx3Bk7;?HO1#8;~+_o1C=GS|H(K^1-q_GR@rRE$@ zZOHn0EeGa(UyaSh7~10D1-7wg=)_PA0Lx4OJwJsGiTwR$Ogrlje9_|xMDoz{1Xrc^ zfAj_FOD5joEJmhl%L}F4FTdnXD0t$yD8e#N7`Ghz1Ech)Ht;!_J=Thh@$+C0+Ihnt z=26}Cg48%ZZN=dKSPB$;{Og?x+{RnARIUmvNhDsb8eeRs z6sA^4#$o6=mU7(jF{6pl7@|PwKEeD0RuqGtX@;|*zNrbgz1jGm0*ek5&uk61^U<`Q>(sp7wcM^wD@a#oMrWZ z2bMuU(6BxHBEP%t3&&FxcrAE`lQto31}`nfc-XeXsio|z1xqUUz68yJ;nMt93pB59 zTM;UfG5dRewrz3Chq85RNCU^3C>w7?${ZC_jt3Z&qlaAs;?(RN^e6Ek;B28VH4eh`c`I?k z6ppDUk4rjN{WkMkv|Y+Ls@lDB=m|u~E>5HJd760!i_6$=z{93Vr7ixxH*%Ow>|P0ZbqChhkMyqBMH4(ai? z$%)~J$c|In+}NIPWf5FIM8IRw4X3gN+-y~RLkXSOug@F&z(>f0zt#^tN|i=qj*Jx( zD%>GP;e3U;?zuT{?G*0mitn7QlPJd3(-`u|h1p<)A488x@dw@JTSraXV$tmQCJQuV zMMo?QL=ddQUe>{=GW%FgV2dn&--enK`v}U_@v$#Nz6`#c+ zAvZH$a;^(KZb*>WF<@tUX|uqItGWAKh374T2|-kumZ_e!iYN$rarfSei8IAGxFR-e zb8xJ#D4zEEdpj#^ZcYftg((7BaT&g26aiUb@<%Rp$8O z8|9JX#ZpBQ-A`!_cN406D?giFt6tkO(*Ry|;H zn1_F*dz)_H1iv329b&Lv3|XXqSNlN?6xhbYOy0VWU@Ux*sbGi2iBu6t^Jw`~&N9#u zO1_#cd(_V@Ui6TRr~Kv)`-z$h*M~DolT|6q>G5)42%aAqMHGUb^WmS`;dMi#cr4zE zuWzU(>FI4K#$&)oaNG%xWFe4Wx9SdiQY;^^{^F^tyJ^IinMZynzU!D~kuM=^X+GDl9T;Pxe_?U4ur_B=mUJm{*&cG_2>IUu*S zrz&TT5HA~}Dqoahcym9_7jo`S(txtE*1+EULrZ4LIQgZ*V3mi&$x5n@-ZwmLxn3`R z;_1d2VI5^Sn-&i36~0r@-Sa_I;C5M)T>Dt%(CW9LPcE&f^DGISfYM3nMG3Cdwz zQCWRKHNjEbpr|b=0W0M_FA0+2Tcgn}DEzhinj)LkS0O~CC?++F=dWQtz~*W*NI(hl zbH$k+JBYIuSx$XP2f==)t{ZJ)^IbJLRP_^gKNA^L)PahGgl}v5ll$y;sSN#!%DCro z4We_(*%8lqD$^*mh1Fp@_&j3?>xrRQdt|ZqL{?MMLX*n%Aw%c#&A~f9y z>(N~ijmq|!4dvjj%)3ANgCaYMBkXO-%hP)}FOg+KKe!Y2?UU14_m$!px1cyr>kK|W zN8r)xo+8aA6u5w9UpX>@`r>MaRNGU5M}#J?7%T?M+MEjBn69Vuc-UZ99sKEvn2S^Zm>^(&0Aj-o|65QFcSkTyFza6PR^px{v_o-fnBbY zb)GBEBFihF+QUB>n{BLGhm0fdPhY%cKf`;ALOdHyb~r~)4cb4^5!Obhz_TQUo}(BS zVwskv#De)bg3-y1&+UPw3^?%E`pYj^u@sMwf>F9qQOa+S)gTp449C0`#rw6JJ*%p^ z^_-|d7dmB$^C8J*T4KQ@8lKK`N{r4o)4uim);fB};V+6faPw6;;h=esf9nAu94azN zeaODf-*cBvVISQ(@aGnbf}|A3y#a-1e04Lcf>|F-+ex-{mv30M>Mun&0N`KhyXk=Wb&oAtdNTx5xna5~v%VcYWangb~W z%3tR-a(Z%-uSjN8j5xNTO=4wpAojz}2%lYzvmmjk&iPb)Wrs%;%kH>Qox^;lN>al~ zPIoVWrslrotEaM{YTv}O0Ux&P8+Qfel3k0WK6-=tfjG>kNQ#NURJ8e)E7hk^NyoM= zA4``kgkk%3$qIi=_C~W`ozU{8_w+b_k;|0!FXQwaDH|aVO&!y|sh_H8*m`1@Zv*6<0bx~NX5L4moS|h>f#PT zbj=zJJy7j*)gA&Id4wXL@{_dg;&V(VqSwx@DZDtvgk6DWAE;pCQ=Hydm@~bcL89;H z)>XZnfQci`i#=V$AjVX;X*wuqJ_OlH0e+W4m%my03aa0}^LdsogILrJxO(daf^N zVolTvrTcsfaoZ$wpbqL1jqlD>bO|iYLH0;vnwZy;>b{W!V$}t`D)CEVSO&+1>lR3b znVj)`&DU#*p2Ka3psZoiKK=ZE>~7nu{B=wqXgj6jW5_b2Ef*Dh#joVS_i4JqcCyNv za^$tsh|doXOo9Z}#8wPVxNf8Zq2Tl#)B2JpYXxjJYbhLxYz6s+wAzh=rgLsFth4`+ z9!-WjZEK`k=Bx_CrzZh)X7Z6OtpKP!&hRddyMmL|rW3`JMCb}paD%?;ocW+;*af2O znf%Utu0tcBO+J^J!XZXB_J%26>lvb@V4qqPs(gu-fMW6`w`Rx`g!&|I1Xw2Xn>A^? zUlys9r#cA;Z|37|ZV5?WnVvT@zD|kWgC%DaFC>I%u# ze$vxc5CRCKcmF4lOfJM-L>NdVC@?tPlr`XGg;@uGn8etsTqR& z%Oss7BtXdz#6Ec^CjqJPaqjtSwz+tf4B;t9iaeG@%JGg!z$-bH*pyvjn2C@?zF6Sk zHP?u_MNq5mAU3xo`dP;UX;x30OF6~JZN>Y4kObJC+jJ3!0&JN%X2PsBAIQ*t*ErMD4$BW{hl|>6j3)&UyaisxcqjK#%C)ZG>^tNkz z#8kFTI%1{C6wlImsM|v;9rSIBgtgMw$SL_8Y&%MuI|qj>Cxw56u(paAzAWAUGkijt zn)c5c0AxagIVYwCyQ3!-gSwU#1$Q!N*_fCo%o!nar2QZwZeM#IH6fc_6z~u5oauJP zjspO9Fxqu}?toR`R7XG(4toQ8CcCkf#Qh|4P^5-?8f0Gn-|aRGYFDgCXM6VS{ETiq ziR@FMWc}m|re)?5Fs%mz2Z680--qg|ZL(z=(p(ZaiClN4yZ}ZolSr(6_Obj82dglY ztn6!-UsL^oCVY~^WUABFFQ%7RlJ(O+btqq`<4>qUX!Ao+hmbIPPp0mP=P=in^eRYVAf#P5ftJ}= z{hbWd+MHqU>Qw!b4sI9dZcc6RkMge+_COBf0Zyh=W&G)ZfTs6B(#FR3E#Qi?JNQ-w zb2wn)y7Dd!c`M&$Zdhn%XdddkxJ_Anw-qKG*Q87V`sz@k@p4#j>|=+@%Lf zTM)972T`vX{um@e&q8T0i&RML#-uU+>-C<=k-kyix)xB%<F=$fnp*r zI)=&7<(8t83cN5v^UbHTmk>E#PEx!TR zGA@6ZP=;$N>@N{gp_GVGM3=DZh6nCBj?;`_J{^S2_PEa zxKvTEUF$#T)K$2jqAk(Gn8t)Fp7=T85fND;IDt5UIH&^nHJ^;r{=a(3uy9HndKMkD zrS0TMI9e5)", ">=", "<", "<="], - // "disallowLeftStickedOperators": ["?", "+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<="], - // "requireRightStickedOperators": ["!"], - // "disallowRightStickedOperators": ["?", "+", "/", "*", ":", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<="], - //"requireLeftStickedOperators": [","], - "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"], - "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"], - "requireSpaceBeforeBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="], - "requireSpaceAfterBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="], - "disallowKeywords": ["with"], - "disallowMultipleLineBreaks": true, - "validateLineBreaks": "LF", - "validateQuoteMarks": "'", - // "disallowMixedSpacesAndTabs": true, - // "disallowTrailingWhitespace": false, - "disallowKeywordsOnNewLine": ["else"], - "requireLineFeedAtFileEnd": true, - "maximumLineLength": 120, - // "requireCapitalizedConstructors": true, - "requireDotNotation": true, - "excludeFiles": ["node_modules/**"] -} diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index b7827e5b86..0000000000 --- a/.jshintrc +++ /dev/null @@ -1,87 +0,0 @@ -{ - // JSHint Default Configuration File (as on JSHint website) - // See http://jshint.com/docs/ for more details - - "maxerr" : 5, // {int} Maximum error before stopping - - // Enforcing - "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.) - "camelcase" : false, // true: Identifiers must be in camelCase - "curly" : true, // true: Require {} for every new block or scope - "eqeqeq" : true, // true: Require triple equals (===) for comparison - "freeze" : true, // true: prohibits overwriting prototypes of native objects such as Array, Date etc. - "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty() - "immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());` - "indent" : 4, // {int} Number of spaces to use for indentation - "latedef" : true, // true: Require variables/functions to be defined before being used - "newcap" : true, // true: Require capitalization of all constructor functions e.g. `new F()` - "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee` - "noempty" : true, // true: Prohibit use of empty blocks - "nonbsp" : true, // true: Prohibit "non-breaking whitespace" characters. - "nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment) - "plusplus" : false, // true: Prohibit use of `++` & `--` - "quotmark" : "single", // Quotation mark consistency: - // false : do nothing (default) - // true : ensure whatever is used is consistent - // "single" : require single quotes - // "double" : require double quotes - "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks) - "unused" : true, // true: Require all defined variables be used - "strict" : false, // true: Requires all functions run in ES5 Strict Mode - "maxparams" : false, // {int} Max number of formal params allowed per function - "maxdepth" : false, // {int} Max depth of nested blocks (within functions) - "maxstatements" : false, // {int} Max number statements per function - "maxcomplexity" : false, // {int} Max cyclomatic complexity per function - "maxlen" : false, // {int} Max number of characters per line - - // Relaxing - "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons) - "boss" : false, // true: Tolerate assignments where comparisons would be expected - "debug" : false, // true: Allow debugger statements e.g. browser breakpoints. - "eqnull" : false, // true: Tolerate use of `== null` - "es5" : false, // true: Allow ES5 syntax (ex: getters and setters) - "esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`) - "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features) - // (ex: `for each`, multiple try/catch, function expression…) - "evil" : false, // true: Tolerate use of `eval` and `new Function()` - "expr" : false, // true: Tolerate `ExpressionStatement` as Programs - "funcscope" : false, // true: Tolerate defining variables inside control statements - "globalstrict" : false, // true: Allow global "use strict" (also enables 'strict') - "iterator" : false, // true: Tolerate using the `__iterator__` property - "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block - "laxbreak" : false, // true: Tolerate possibly unsafe line breakings - "laxcomma" : false, // true: Tolerate comma-first style coding - "loopfunc" : false, // true: Tolerate functions being defined in loops - "multistr" : false, // true: Tolerate multi-line strings - "noyield" : false, // true: Tolerate generator functions with no yield statement in them. - "notypeof" : false, // true: Tolerate invalid typeof operator values - "proto" : false, // true: Tolerate using the `__proto__` property - "scripturl" : false, // true: Tolerate script-targeted URLs - "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;` - "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation - "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;` - "validthis" : false, // true: Tolerate using this in a non-constructor function - - // Environments - "browser" : true, // Web Browser (window, document, etc) - "browserify" : false, // Browserify (node.js code in the browser) - "couch" : false, // CouchDB - "devel" : true, // Development/debugging (alert, confirm, etc) - "dojo" : false, // Dojo Toolkit - "jasmine" : false, // Jasmine - "jquery" : true, // jQuery - "mocha" : true, // Mocha - "mootools" : false, // MooTools - "node" : false, // Node.js - "nonstandard" : false, // Widely adopted globals (escape, unescape, etc) - "prototypejs" : false, // Prototype and Scriptaculous - "qunit" : false, // QUnit - "rhino" : false, // Rhino - "shelljs" : false, // ShellJS - "worker" : false, // Web Workers - "wsh" : false, // Windows Scripting Host - "yui" : false, // Yahoo User Interface - - // Custom Globals - "globals" : {} // additional predefined global variables -} diff --git a/.llmsconfig b/.llmsconfig deleted file mode 100644 index f1811bf596..0000000000 --- a/.llmsconfig +++ /dev/null @@ -1,50 +0,0 @@ -{ - "build": { - "custom": [ "js:additional", "js:builder", "readme" ] - }, - "pot": { - "bugReport": "https://github.com/gocodebox/lifterlms/issues", - "domain": "lifterlms", - "dest": "languages/", - "jsClassname": "LLMS_L10n_JS", - "jsFilename": "class.llms.l10n.js.php", - "jsSince": "3.17.8", - "jsSrc": [ "assets/js/**/*.js", "!assets/js/**/*.min.js", "!assets/js/**/*.js.map" ], - "lastTranslator": "Thomas Patrick Levy ", - "team": "LifterLMS ", - "package": "lifterlms" - }, - "publish": { - "title": "LifterLMS", - "lifterlms": { - "pot": false - } - }, - "scripts": { - "src": [ - "assets/js/**/*.js", - "!assets/js/**/*.min.js", - "!assets/js/**/*.js.map", - "!assets/js/app/**/*.js", - "!assets/js/builder/**/*.js", - "!assets/js/partials/**/*.js", - "!assets/js/private/**/*.js" - ], - "dest": "assets/js/" - }, - "versioner": { - "custom": [ "versioner:readme" ] - }, - "watch": { - "custom": [ { - "glob": [ "assets/js/builder/**/*.js" ], - "tasks": [ "js:builder" ] - } ] - }, - "zip": { - "composer": true, - "src": { - "custom": [ "!./**/CHANGELOG.md", "!./**/README.md", "!./_private/**", "!./_readme/**" ] - } - } -} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 203ee892d1..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,38 +0,0 @@ -language: php - -sudo: false - -cache: - directories: - - $HOME/.composer/cache - - $HOME/.npm - -branches: - except: - - trunk - - assets - -php: - - 5.6 - - 7.0 - - 7.1 - - 7.2 - # - hhvm - -env: - - WP_VERSION=latest WP_MULTISITE=0 PHP_LATEST_STABLE=7.2 - -before_script: - - bash tests/bin/install.sh lifterlms_tests root '' localhost $WP_VERSION - - bash tests/bin/travis.sh before - -script: - - bash tests/bin/travis.sh during - -after_success: - - if [[ ${TRAVIS_PHP_VERSION} == ${PHP_LATEST_STABLE} ]]; then vendor/bin/test-reporter; fi - -notifications: - slack: - secure: xhRdeZcRwIvVqcI/tn3Npm8N83SvPkjbpK1wY3x1epi854SGtCd6iZGjKjIZUQ7fl0XnUhjOg23b45ukYZSmm5ktn/hsdrFSzPlFRZo6RQomObq/TZA9Vq8uAL5WiCKz5g+BmWt3kVRiQZvpRMU0VdzmA42jNvWxvgle8g04klxgp3IduAMzo8MOL2ubpF9k8ebEZ/TdeqVb8onUrUdOBP+Xtbu/l7cVPKW4yRGHpikOMrwfL0OTGOhETcBsF6QiCLhifKCXtqXAc2vFRIg6j7/xOx8Kd9ZVkYPAGKbN56Omu8Ejw/RWVrKlC5WUoqjKS5DUQHuBBZw8rgm0PZkzOfEHRjwcQ8gLCROOqeL9LAq/YYNW2PgbOP9NWPyDij2rX5CI8ot24hKcHMpHWw1+uXZJ5S4piOo31DhBaMlju59h+Mrn0A2A6UfBMTmzQ/LBugkn4iINgWCU2QpplqV1plDc6alwP0PXRdHflKJr5kvGsLE2KjJfKlunmXQWeZKlFO/BwG7jAEuA/aJFX+LqRlug+PXU+CBuXc6XYDLgeSiG1TT6SOIpmK2MIBz4dbsxn1F7QyGXklsm7tw78tnHAmg7qIN9r8l3Ptl1Tlmx60zY4bKm1QUW0/VbblDu/pOc5KjEuFQ/UsBGW9XyUZ7LerKhq2/f7Fn/mjK5XewHKgA= - email: false diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 2b15e98de4..0000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,3039 +0,0 @@ -LifterLMS Changelog -=================== - -v3.17.8 - 2018-05-04 --------------------- - -##### Updates and Enchancements - -+ Added admin email notification when student cancels a subscription -+ Quiz results will now display the question's description when reviewing results as a student and on the admin panel during grading -+ Add action hook fired when a student cancels a subscription (`llms_subscription_cancelled_by_student`) -+ Reduce unnecessary DB queries for integrations by checking for dependencies and then calling querying the options table to see if the integration has been enabled. -+ Updated the notifications settings table to be more friendly to the human eye - -##### Bug Fixes - -+ Fix admin scripts enqueue order. Fixes issue preventing manual student enrollment selection from functioning properly in certain scenarios. -+ Shift + Enter when in a question choice field now adds a return as expected instead of exiting the field -+ When pasting into question choice fields HTML from RTF documents will be automatically stripped -+ Ensure certificates print with a white brackground regardless of theme CSS -+ Fix issue causing themes with `overflow:hidden` on divs from cutting certificate background images -+ Upon export completion unlock tables regardless of mail success / failure -+ Resolve issue causing incorrect number of access plans to be returned on systems that have custom defaults set for `WP_Query` `post_per_page` parameter -+ Fix error occurring when all 3rd party integrations are disabled by filter, credit to [@Mte90](https://github.com/Mte90)! -+ Ensure `LLMS()->integrations()->integrations()` returns all integrations regardless of availability. -+ Updated `LLMS_Abstract_Options_Data` to have an option set method - -##### Template Updates - -+ [templates/quiz/results-attempt-questions-list.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/results-attempt-questions-list.php) - - -v3.17.7 - 2018-04-27 --------------------- - -+ Fix issue preventing assignments passing grade requirement from saving properly -+ Fix issue preventing builder toggle switches from properly saving some switch field data -+ Fix with "Launch Builder" button causing it to extend outside the bounds of its container -+ Fix issue with builder radio select fields during view rerenders -+ Course Outline shortcode (and widget) now retrieve parent course of the current page more consistently with other shortcodes -+ Added ability to filter which custom post types which can be children of a course (allows course shortcodes & widgets to be used in assignment sidebars of custom content areas) - - -v3.17.6 - 2018-04-26 --------------------- - -+ Updated language on recurring orders with no expiration settings. Orders no longer say "Lifetime Access" and instead output no expiration information -+ Quiz editor on builder updated to be consistent visually and functionally to the lesson settings editor -+ Improved the builder field API to allow for radio element fields -+ Fix issue causing JS error on admin settings pages -+ Updated CSS for Certificates to be more generally compatible with theme styles when printed -+ Allow system print settings to control print layout for certificates by removing explicit landscape declarations -+ Now passing additional data to filters used to create custom columns on reporting screens -+ Remove unused JS files & Chosen JS library -+ Added filter to allow opting into alternate student dashboard order layout. Use `add_filter( 'llms_sd_stacked_order_layout', '__return_true' )` to stack the payment update sidebar below the main order information. This is disabled by default. -+ Achievement and Certificate basic notifications now auto-dismiss after 10 seconds like all other basic notifications -+ Deprecated Filter `llms_get_quiz_theme_settings` and added backwards compatible methods to transition themes using this filter to the new custom field api. For more information see new methods at https://lifterlms.com/docs/course-builder-custom-fields-for-developers/ -+ Increased default z-index on notifications to prevent notifications from being hidden behind floating / static navigation menus - - -##### Template Updates - -+ [templates/myaccount/my-orders.php](https://github.com/gocodebox/lifterlms/blob/master/templates/myaccount/my-orders.php) -+ [templates/myaccount/view-order.php](https://github.com/gocodebox/lifterlms/blob/master/templates/myaccount/view-order.php) - - -v3.17.5 - 2018-04-23 --------------------- - -##### Admin Settings Interface Improvements - -+ Improved admin settings page interface to allow for section navigation -+ Updated checkout setting pages to utilize a separate section (page) for each available payment gateway -+ Added a table of payment gateways to see at a glance which gateways are enabled and allows drag and drop reordering of gateway display order -+ Moved dashboard endpoints to a separate section on the accounts settings area -+ Updated CSS on settings page to have more regular spacing between subtitles and settings fields -+ Added a "View" button next to any admin setting post/page selection field to allow quick viewing of the selected post -+ Purchase page setting field is now ajax powered like all other page selection settings -+ Renamed dashboard settings section titles to be more consistent with language in other areas of LifterLMS -+ All dashboard endpoints now automatically sanitized to be URL safe - -##### Updates and Enhancements - -+ Dashboard endpoints can now be deregistered by setting the endpoint slug to be blank on account settings - -##### Bug Fixes - -+ Fix issue causing 404s for various script files when SCRIPT_DEBUG is enabled -+ Fix issue with audio & video embeds to prexvent fallback to default post attachments -+ Fix issue causing student selection boxes to malfunction due to missing dependencies when loaded over slow connections - -##### Template Updates - -+ [templates/myaccount/navigation.php](https://github.com/gocodebox/lifterlms/blob/master/templates/myaccount/navigation.php) - - -v3.17.4 - 2018-04-17 --------------------- - -+ Added core RTL language support -+ Fixed fatal error on student management tables resulting from deleted admin users who manually enrolled students -+ Added filter to allow 3rd parties to disable achievement dupchecking (`llms_achievement_has_user_earned`) -+ Added {student_id} merge code which can be utilized on certificates -+ Added merge code insert button to certificates editor -+ Added filter to allow 3rd parties to disable certificate dupchecking (`llms_certificate_has_user_earned`) -+ Added filter to allow 3rd parties to add custom merge codes to certificates (`llms_certificate_merge_codes`) -+ Fix restriction check issue for lessons with drip or prerequisites on course outline widget / shortcode -+ Bumped WP tested to version to 4.9.5 - -##### Template Updates - -+ [templates/course/complete-lesson-link.php](https://github.com/gocodebox/lifterlms/blob/master/templates/course/complete-lesson-link.php) -+ [templates/course/outline-list-small.php](https://github.com/gocodebox/lifterlms/blob/master/templates/course/outline-list-small.php) - - -v3.17.3 - 2018-04-11 --------------------- - -+ Course and Membership instructor metabox search field now correcty states "Select an Instructor" instead of previous "Select a Student" -+ Added missing translation for "Select a Student" on admin panel student selection search fields -+ Fix issue causing reporting export CSVs to throw a SYLK interpretation error when opened in Excel -+ Fix issue causing drafted courses and memberships to be published when the "Update" button is clicked to save changes -+ Remove use of PHP 7.2 deprecated `create_function` -+ Fix errors resulting from quiz questions which have been deleted -+ Fix issue causing current date / time to display as the End Date for incomplete quiz attempts on quiz reporting screens - -##### Template Updates - -+ [templates/admin/reporting/tabs/quizzes/attempt.php](https://github.com/gocodebox/lifterlms/blob/master/templates/admin/reporting/tabs/quizzes/attempt.php) -+ [templates/quiz/results-attempt-questions-list.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/results-attempt-questions-list.php) - - -v3.17.2 - 2018-04-09 --------------------- - -+ Fixed issue preventing lesson video and audio embeds from being *removed* when using the course builder settings editor -+ Fixed issue causing question images to lose the image source -+ Updated student management table for courses and memberships to show the name (and a link to the user profile) of the site user who manually enrolled the student. -+ Add "All Time" reporting to various reporting filters -+ Added API for builder fields to enable multiple select fields -+ Fix memory leak related to assignments rendering on course builder -+ Fix issue causing course progress and enrollment checks to incorrectly display progress data cached for other users -+ Lesson progression actions (Mark Complete & Take Quiz buttons) will now always display to users with edit capabilities regardless of enrollment status - -##### Template Updates - -+ [templates/course/complete-lesson-link.php](https://github.com/gocodebox/lifterlms/blob/master/templates/course/complete-lesson-link.php) -+ [templates/course/outline-list-small.php](https://github.com/gocodebox/lifterlms/blob/master/templates/course/outline-list-small.php) - - -v3.17.1 - 2018-03-30 --------------------- - -+ Refactored lesson completion methods to allow 3rd party customization of lesson completion behavior via filters and hooks. -+ Remove duplicate lesson completion notice implemented. Only popover notifications will display now instead of popovers and inline messages. -+ Object completion will now automatically prevent multiple records of completion from being recorded for a single object. -+ Lesson Mark Complete button and lessons completed by quiz now utilizes a generic trigger to mark lessons as complete: `llms_trigger_lesson_completion`. -+ Removed several unused functions from frontend forms class -+ Moved lesson completion form controllers to their own class - -##### Templates updates - -+ [templates/course/complete-lesson-link.php](https://github.com/gocodebox/lifterlms/blob/master/templates/course/complete-lesson-link.php) - - -v3.17.0 - 2018-03-27 --------------------- - -##### Builder Updates - -+ Moved action buttons for each lesson (for opening quiz and lesson editor) to be static below the lesson title as opposed to only being visible on hover -+ Added new audio and video status indicator icons for each lesson -+ Various status indicator icons will now have different icons in addition to different colors depending on their state -+ Replaced "pencil" icons that open the WordPress post editor with a small "WP" icon -+ Added several actions and filters to backend functions so that 3rd parties can hook into builder saves -+ Added lesson settings editing to the builder. Lesson settings can now be updated from settings metaboxes on the lesson post edit screen AND on the builder. -+ Added prerequisite validation for lessons to prevent accidental impossible prerequisite creating (eg: Lesson 5 can never be a prerequisite for Lesson 4) -+ Added functions and filters to allow 3rd parties to add custom fields to the builder. For more details see [an example](https://lifterlms.com/docs/course-builder-custom-fields-for-developers/). -+ Fixed issue causing changes made in "Text" mode on content editors wouldn't trigger save events -+ Fixed issue causing lesson prerequisites to not properly display on the course builder -+ Fixed CSS z-index issues related to builder field tooltip displays -+ Removed unused Javascript dependencies - -##### Bug Fixes - -+ Fixed typo on filter on quiz question image getter function - -##### Updates - -+ Performance improvements made to database queries and functions related to student enrollment status and student course progress queries. Thanks to [@mte90](https://github.com/Mte90) for raising issues and testing solutions related to these updates and changes! -+ Added PHP Requires plugin header (5.6 minimum) -+ Added HTTP User Agent data to the system report -+ [LifterLMS Assignments Beta](https://lifterlms.com/product/lifterlms-assignments?utm_source=LifterLMS%20Plugin&utm_medium=CHANGELOG&utm_campaign=assignments%20preorder) is imminent and this release adds functionality to the Builder which will be extended by Assignments upon when availability - - -v3.16.16 - 2018-03-19 ---------------------- - -+ Fixed builder issue causing multiple question choices to be incorrectly selected -+ Fixed builder issue with media library uploads causing an error message to prevent new uploads before the quiz or question has been persistend to the database -+ Fixed builder issue preventing quizzes from being deleted before they were persisted to the database -+ Fixed builder issue causing autosaves to interrupt typing and reset lesson and section titles -+ Fixed JS console error related to LifterLMS JS dependency checks - - -v3.16.15 - 2018-03-13 ---------------------- - -##### Quiz Results Improvements and fixes - -+ Improved quiz result user and correct answer handling functions for more consistent HTML output -+ Result answers (correct and user) will display as lists -+ image question types will display without bullets and will "float" next to each other -+ Fixed issue causing quiz results with multiple answers from outputting all HTMLS with no spaces between them - -##### Quiz Grading - -+ Fixed issue causing advanced reorder and reorder question types from being graded incorrectly in some scenarios -+ Advanced fill in the blank questions are now case insensitive. Case sensitivity can be enabled with a filter: `add_filter( 'llms_quiz_grading_case_sensitive', '__return_true' )` - -##### Fixes - -+ Updated spacing and returns found in the email header and footer templates to prevent line breaks from occurring in undesireable places on previews of HTML emails in mobile email clients -+ Added options for themes to add layout support to quizzes where the custom field utilizes an underscore at the beginning of the field key -+ Fixed CSS issue causing blanks of fill in the blanks to not be visible on the course builder when using Chrome on Windows -+ Removed unnecessary `get_option()` call to unused option `lifterlms_permalinks` -+ Updated permissions required to see various LifterLMS post types to rely on `manage_lifterlms` capabilites as opposed to `manage_options` - + This will only affect the LMS Manager core role or any custom role which was provided with the `manage_options` capability. Manages will now be able to access all LMS content and custom roles would now not be able to access LMS content - + Affected content types are: Orders, Coupons, Vouchers, Engagements, Achievements, Certificates, and Emails -+ Several references to an option removed in LifterLMS 3.0 still existed in the codebase and have now been removed. - + Option `lifterlms_course_display_banner` is no longer called or referenced - + Template function `lifterlms_template_single_featured_image()` has been removed - + Actions referencing `lifterlms_template_single_featured_image()` have been removed - + Template function `lifterlms_get_featured_image_banner()` has been removed - + Template `templates/course/featured-image.php` has been removed - -##### Templates updates - -+ [quiz/results-attempt-questions-list.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/results-attempt-questions-list.php) - - -v3.16.14 - 2018-03-07 ---------------------- - -+ Courses reporting table now includes courses with the "Private" status -+ Fixed issue causing some achievment notifications to be blank -+ Added tooltips to question choice add / delete icon buttons -+ Quiz results meta information elements now have unique CSS classes -+ Removed reliance PHP 7.2 deprecated function `create_function()` -+ Fixed invalid PHP 7.2 syntax creating a warning found on the setup wizard -+ Fixed undefined index error related to admin notices -+ Fixed unstanslateable string on Users table ("No Memberships") -+ Fixed discrepancy between membership restrictions as presented to logged out users and loggend in users who cannot access membership -+ Fixed FireFox and Edge issue causing changes to number inputs made via HTML5 input arrows from properly triggering save events - - -v3.16.13 - 2018-02-28 ---------------------- - -+ Hotfix: Only create quizzes on the builder if quizzes exist on the lesson - - -v3.16.12 - 2018-02-27 ---------------------- - -+ Quizzes can now be detached (removed from a lesson) or deleted (deleted from the lesson and the database) via the Course Builder -+ Improved question choice randomization to ensure randomized choices never display in their original order. -+ When a lesson is deleted, any quiz attached to the lesson will become an orphan -+ When a lesson is deleted, any lesson with this lesson as a prerequisite will have it's prerequisite data removed -+ When a quiz is deleted, all questions attached to the quiz will also be deleted -+ When a quiz is deleted, the lesson associated with the quiz will have those associations removed -+ Fixed grammar issue on restricted lesson tooltips when no custom message is stored on the course. -+ Updated functions causing issues in PHP 5.4 to work on PHP 5.4. This has been done to reduce frustration for users still using PHP 5.4 and lower; [This does not mean we advocate using software past the end of its life or that we support PHP 5.4 and lower](https://lifterlms.com/docs/minimum-system-requirements-lifterlms/). - - -v3.16.11 - 2018-02-22 ---------------------- - -+ Course import/exports and lesson duplication now carry custom meta data from 3rd party plugins and themes -+ Added course completion date column to Course reporting students list -+ Restriction checks made against a quiz will now properly cascade to the quiz's parent lesson -+ Fixed issue preventing featured images from being exported with courses and lessons -+ Fixed duplicate lesson issue causing quizzes to be double assigned to the old and new lesson -+ Fixed issue allowing blog archive to be viewed by non-members when sitewide membership is enabled -+ Fixed builder issue causing data to be lost during autosaves if data was edited during an autosave -+ Fixed builder issue preventing lessons from moving between sections when clicking the "Prev" and "Next" section buttons -+ Added actions to `LLMS_Generator` to allow 3rd parties to extend core generator functionality - - -v3.16.10 - 2018-02-19 ---------------------- - -+ Content added to the editor of course & membership catalog pages will now be output *above* the catalog loop -+ Fix issue preventing iframes and some shortcodes from working when added to a Quiz question description -+ Added new columns to the Quizzes reporting table to display Course and Lesson relationships -+ Improved the task handler of background updater to ensure upgrade functions that need to run multiple times can do so -+ Fixed JS Backup confirmation dialog on the background updater. -+ Add support for 32-bit systems in the `LLMS_Hasher` class -+ Fix issue causing HTML template content to be added to lessons when duplicating an existing lesson within the course builder - -##### 3.16.0 migration improvements - -+ Accommodates questions imported by 3rd party Excel to LifterLMS Quiz plugin. Fixes an issue where choices would have no correct answer designated after migration. -+ All migration functions now run on a loop. This improves progress reporting of the migration and prevents timeouts on mature databases with lots of quizzes, questions, and/or attempts. -+ Fix an issue that caused duplicate quizzes or questions to be created when the "Taking too long?" link was clicked - - -v3.16.9 - 2018-02-15 --------------------- - -+ Fix issue causing error on student dashboard when reviewing an order with an access plan that was deleted. -+ Fixed spelling error on course metabox -+ Fixed spelling error on frontend quiz interface -+ Fixed issues with 0 point questions: - + Will no longer prevent quizzes from being automatically graded when a 0 point question is in an otherwise automatically gradeable quiz - + Point value not editable during review - + Visual display on results displays with grey background not as an orange "pending" question -+ Table schema uses default database charset. Fixes an issue with databases that don't support `utf8mb4` charsets. -+ Updated `LLMS_Hasher` class for better compatibility with older versions of PHP - - -v3.16.8 - 2018-02-13 --------------------- - -##### Updates - -+ Added theme compatibility API so theme developers can add layout options to the quiz settings on the course builder. For details on adding theme compatibility see: [https://lifterlms.com/docs/quiz-theme-compatibility-developers/](https://lifterlms.com/docs/quiz-theme-compatibility-developers/). -+ Quiz results "donut" chart had alternate styles for quizzes pending review (Dark grey text rather than red). You can target with the `.llms-donut.pending` CSS class to customize appearance. -+ Allow filtering when retrieving student answer for a quiz attempt question via `llms_quiz_attempt_question_get_answer` filter - -##### Bug Fixes - -+ Fix issues causing conditionally gradeable question types (fill in the blank and scale) from displaying without a status icon or possible points when awaiting admin review / grading. -+ Fix issue preventing conditionally gradeable question types (fill in the blank and scale) from being reviewable on the admin panel when the question is configured as requiring manual grading. -+ Fix analytics widget undefined index warning during admin-ajax calls. Thanks [@Mte90](https://github.com/Mte90)! -+ Fix issue causing `is_search()` to be called incorrectly. Thanks [@Mte90](https://github.com/Mte90)! -+ Fix issue preventing text / html formatting from saving properly for access plan description fields -+ Fix html character encoding issue on reporting widgets causing currency symbols to display as a charcter code instead of the symbol glyph. - -##### Templates changed - -+ templates/quiz/results-attempt-questions-list.php -+ templates/quiz/results-attempt.php - - -v3.16.7 - 2018-02-08 --------------------- - -+ Added manual saving methods for the course builder that passes data via standard ajax calls. Allows users (hosts) to disable the Heartbeat API but still save builder data. -+ Added an "Exit" button to the builder sidebar to allow exiting the builder back to the WP Edit Post screen for the current course -+ Added dashboard links to the WP Admin Bar to allow existing the course builder to various areas of the dashboard -+ Added data attribute to progress bars so JS (or CSS) can read the progress of a progress bar. Thanks [@dineshchouhan](https://github.com/dineshchouhan)! -+ Fixed issue causing newly created lessons to lose their assigned quiz -+ Fixed php `max_input_vars` issue causing a 400 Bad Request error when trying to save large courses in the course builder -+ Removed reliance on PHP bcmath functions - - -v3.16.6 - 2018-02-07 --------------------- - -+ Removed reliance on PHP Hashids Library in favor of a simpler solution with no PHP module dependencies -+ Added interfaces to allow customization of quiz url / slug -+ Fixed [audio] shortcodes added to quiz question descrpitions -+ Fixed untranslateable strings on frontend of quizzes -+ Fix issue causing certificate notifications to display as empty -+ Fix issue preventing quiz pass/fail notifications from triggering properly for manually graded quizzes -+ Fix undefined index warning on quiz pass/fail notifications - - -v3.16.5 - 2018-02-06 --------------------- - -+ Fix issue preventing manually graded quiz review points from saving properly -+ Improved background updater to ensure scripts don't timeout during upgrades -+ Admin builder JS now minified for increased performance -+ Made frontend quiz and quiz-builder strings output via Javascript translateable - - -v3.16.4 - 2018-02-05 --------------------- - -+ Fix issue causing newly created quizzes to not be properly related to their parent lesson -+ Fix issue preventing quiz time limits from starting unless an attempt limit is also set -+ Fixes a WP Engine issue that prevented the builder from loading due to a blocked dependency - - -v3.16.3 - 2018-02-02 --------------------- - -+ When switching a quiz to "Published" it will now update the parent lesson to ensure it's recorded as having an enabled quiz. -+ Declared the WordPress heartbeat API script as a dependency for the Course Builder JS. It seems that some servers and hosts dequeue the heartbeat when not explicitly required. This resolves a saving issue on those hosts. -+ Added a Quiz Description content editor under quiz settings. This is the "Editor" from pre 3.16.0 quizzes and any content saved in these fields is now available in this description field -+ Fixed issue causing points percentage calulation tooltip on quiz builder to show the incorrect percentage value -+ Fix issue preventing lessons with no drip settings from being updated on the WP post editor -+ Fix issue causing 500 error on lesson settings metabox for lessons not attached to sections -+ Add a "Quiz Description" field to allow quiz post content to be edited on the quiz builder -+ Added a database migration script to ensure quizzes migrated from 3.16 and lower that had quiz post content to automatically have the optional quiz description to be enabled - - -v3.16.2 - 2018-02-02 --------------------- - -+ Add an update notice to 3.16.0 migration scripts to provide more information about the major update. -+ Removed quiz assignment fields on the lesson metabox to reduce confusion as quizzes are now managed exclusively on the quiz builder. -+ Ensure questions migrated during 3.16 updates retain their initial points value from the quiz. - - -v3.16.1 - 2018-02-01 --------------------- - -+ Ensure quizzes in draft mode are only accessible by those with edit access (instructors, admins, etc...) -+ Restore pre 3.16 actions and filters related to quiz start buttons -+ Remove legacy error message for quiz accessibility issues by site admins -+ Students who cannot access a quiz are redirected to the parent lesson if they attempt to access a quiz directly -+ Fix undefined index warning on wp-login.php related to LifterLMS js assets. Thanks [Mte90](https://github.com/Mte90)! -+ Update checkout error message to provide user with direction when they already have access to a course. Thanks [@andreasblumberg](https://github.com/andreasblumberg)! - - -v3.16.0 - 2018-02-01 --------------------- - -##### Quizzes - -+ New question types: True/False, Picture Choice, and Non-question content -+ Picture & Multiple choice have options for multiple correct answers (checkbox-like questions) -+ You can now create questions with NO POINTS (maybe for surveys?) -+ Upgraded student quiz review interface -+ Upgraded instructor quiz attempt review interface -+ Admins may now leave remarks on questions directly -+ Improved data available related to quizzes and quiz attempts on reporting screens -+ Improved quiz user interface -+ Added a progress bar to the quiz interface -+ Shrunk the quiz timer -+ Added a question # counter on the quiz interface -+ Fixed issue causing randomized questions to get "lost" when navigating back through a quiz attempt -+ Improved error handling on quizzes -+ Overhauled quiz data structure for improved performance and scalability -+ Requires database migration and update: [3.16.0](https://lifterlms.com/docs/lifterlms-database-updates/#3160) - -##### Course Builder Improvements - -+ Quiz-building is now available on the course builder -+ Quiz and Question WordPress editors no longer available. Quizzes and Questions HAVE NOT DISAPPEARED, they've been improved and relocated -+ All hooks & filters attached to `the_content` and `the_title` are now being removed when loading the course builder. This should prevent infinite spinners on builder loading and builder AJAX calls due to third-parties accidentally outputting html during these events. - -##### Updates - -+ Added space between arrows and "Next" and "Previous" text on pagination lists. Thanks [sujaypawar](https://github.com/sujaypawar)! -+ Updated Quiz post type slug from "llms_quiz" to "quiz". -+ Updated default return of `llms_get_post()` to be `false` rather than a `WP_Post` object when a LifterLMS post cannot be located - -##### Bug Fixes - -+ Fixed a potential database read error related to database store abstract -+ Now passing Post ID as second parameter to the `the_title` filter called on post model getters - - -##### Removed templates - -The following quiz templates have been removed. Customization of these templates causes quiz application functionality to break and they should not have been available for customization but were due to oversights. This has been corrected. - -+ templates/content-single-question-after.php -+ templates/content-single-question-before.php -+ templates/quiz/next-question.php -+ templates/quiz/previous-question.php -+ templates/quiz/question-count.php -+ templates/quiz/quiz-question.php -+ templates/quiz/single-choice.php -+ templates/quiz/single-choice_ajax.php -+ templates/quiz/summary.php -+ templates/quiz/timer.php -+ templates/quiz/wrapper-end.php -+ templates/quiz/wrapper-start.php - -##### Removed Functions - -Various template functions related to quizzes were removed due to the deprecation of their related templates - -+ `lifterlms_template_quiz_timer()` -+ `lifterlms_template_single_next_question()` -+ `lifterlms_template_single_prev_question()` -+ `lifterlms_template_single_single_choice()` -+ `lifterlms_template_single_single_choice_ajax()` -+ `lifterlms_template_single_question_count()` - - -v3.15.1 - 2017-12-05 --------------------- - -+ Ensure course & membership titles with HTML characters are decoded during reporting exports -+ Fix issue causing some courses to display in membership columns on reporting exports - - -v3.15.0 - 2017-12-04 --------------------- - -##### Reporting Updates (and CSV exports!) - -+ Added course-level reporting table (see "Courses" tab of Reporting screen) -+ Updated the interface on reporting screen when reviewing a single student -+ Added reporting exports: students list, courses list, and list of students per course - -##### Bug fixes - -+ Fix error when `[lifterlms_course_continue_button]` shortcode is displayed to logged out or students not enrolled in the chosen course - -##### Minor updates - -+ Tested up to WordPress 4.9.1 -+ Added background data processors to ensure reporting data stays up to date in close to real time -+ Add nocache constants and headers on student dashboard & checkout page to increase compatibility with caching plugins -+ Added filter to student dashboard courses query - - -v3.14.9 - 2017-11-27 --------------------- - -+ Tested up to WordPress 4.9 -+ Fix error during uninstall related to missing file -+ Fix issue with rewinding quiz using "Previous Question" button -+ On final question of a quiz the "Next Lesson" button now says "Complete Quiz" -+ When completing a quiz, the loading message will now say "Grading Quiz" the entire time instead of "Loading Question" and then "Grading Quiz" -+ Fix issue causing the `` element on course builder pages from being partially empty - - -v3.14.8 - 2017-11-06 --------------------- - -+ Lessons can be cloned via the "Clone" action from the lessons post table - -##### Builder Improvements & Fixes - -+ Add "Existing Lesson" functionality can now clone and attach the clone (when adding a lesson currently attached to a course) OR attach orphans -+ Lessons created via Course builder will have their slugs renamed the first time the lesson title is updated via the builder -+ No longer display notices on the course builder -+ Add extra space to the scollable area on course builder -+ Removed logging and debugging functions from admin builder class -+ JS-generated error messages on the course builder are now translateable - -##### Bug Fixes - -+ Fix: Show all memberships on dashboard - - -v3.14.7 - 2017-10-25 --------------------- - -##### Navigation Menu Items - -+ Add LifterLMS endpoints to your nav menu -+ Add Sign In and Sign Out links which display conditionally based on whether or not the visitor is logged in -+ Checkout the docs at [https://lifterlms.com/docs/lifterlms-navigation-menu-items/](https://lifterlms.com/docs/lifterlms-navigation-menu-items/) - -##### Bug Fixes - -+ Fix SQL query issue with orphaned lesson query on course builder -+ Fix undefined index warning occurring during theme switches -+ Fix issue causing duplicate error messages to display on certain servers - - -v3.14.6 - 2017-10-21 --------------------- - -+ Fix: `<iframes>` are no longer stripped when exporting or duplicating courses (this applies to lessons within the courses as well) -+ Fix: Achievements on student dashboard now output the correct achievement title -+ Fix: Courses on student dashboard ordered by Order attributes will obey settings correctly - - -v3.14.5 - 2017-10-14 --------------------- - -+ Course builder will persist open/collapsed state of sections when they are re-orderd -+ Course builder lessons in a section are draggable after reordering a section - - -v3.14.4 - 2017-10-13 --------------------- - -+ You were right and we were wrong & we are sorry. This update returns the ability to add existing lessons to a course via the course builder. -+ Lessons added to a section will no longer visually disappear when editing a section title on the course builder -+ BuddyPress integration BP template fixes - - -v3.14.3 - 2017-10-12 --------------------- - -+ Fix [lifterlms_my_account] shortcode issue affecting Divi theme users - - -v3.14.2 - 2017-10-11 --------------------- - -+ Instructor query utilizes correct `$wpdb->prefix` for filtering by role instead of `wp_` which will not work when the `$table_prefix` in wp-config.php is customized -+ include the admin notices class when running database update functions - - -v3.14.1 - 2017-10-10 --------------------- - -+ Fix `[lifterlms_my_achievements]` shortcode -+ Fix reference to deprecated core function related to checking the permissions of content restricted to a membership -+ Builder titles will be saved on all field focusout/blur events, not just tab & enter key presses -+ LifterLMS custom meta save metaboxes will not trigger actions during ajax requests -+ Fix issue displaying certificates on admin panel reporting screens - - -v3.14.0 - 2017-10-10 --------------------- - -+ Updated JS for 3.13 course builder to address issues on PHP 5.6 servers with asp_tags enabled -+ Normalized date returns with various dates related to enrollments, achievements, and certificates. These dates now utilize the WP Core `date_format` option. -+ Fixed strict comparison issue related to database query abstract (affected checks for last page & first page on admin reporting screens) -+ Added a new capability `llms_instructor` for admins, lms managers, instructors, and instructor's assistant to easily differentiate "instructors" from "students" -+ Fix `$wpdb->prepare` issue related to notification queries. Fixes WP 4.9-beta issue. - -##### Student Dashboard Updates - -+ Achievements on student dashboard now viewable in popover modal. -+ Achievements tab added to student dashboard -+ Courses, Memberships, Achievements, and Certificates have been updated to have a unified style -+ Courses & Memberships extend the default catalog tiles -+ Courses shortcode has new parameters useful for displaying a list of a specific users courses only. [More info](https://lifterlms.com/docs/shortcodes/#lifterlms_courses) - -##### Deprecated functions - -+ `LLMS_Student_Dashboard::output_courses_content()` replaced with `lifterlms_template_student_dashboard_my_courses( false )` -+ `LLMS_Student_Dashboard::output_dashboard_content` replaced with `lifterlms_template_student_dashboard_home()` - -##### Template Updates - -+ [achievements/loop.php](https://github.com/gocodebox/lifterlms/blob/master/templates/achievements/loop.php) -+ [achievements/template.php](https://github.com/gocodebox/lifterlms/blob/master/templates/achievements/template.php) -+ [certificates/loop.php](https://github.com/gocodebox/lifterlms/blob/master/templates/certificates/loop.php) -+ [certificates/preview.php](https://github.com/gocodebox/lifterlms/blob/master/templates/certificates/preview.php) -+ [loop.php](https://github.com/gocodebox/lifterlms/blob/master/templates/loop.php) -+ [loop/content.php](https://github.com/gocodebox/lifterlms/blob/master/templates/loop/content.php) -+ [loop/enroll-date.php](https://github.com/gocodebox/lifterlms/blob/master/templates/loop/enroll-date.php) -+ [loop/enroll-status.php](https://github.com/gocodebox/lifterlms/blob/master/templates/loop/enroll-status.php) -+ [loop/pagination.php](https://github.com/gocodebox/lifterlms/blob/master/templates/loop/pagination.php) -+ [myaccount/dashboard-section.php](https://github.com/gocodebox/lifterlms/blob/master/templates/myaccount/dashboard-section.php) -+ [myaccount/dashboard.php](https://github.com/gocodebox/lifterlms/blob/master/templates/myaccount/dashboard.php) -+ [myaccount/header.php](https://github.com/gocodebox/lifterlms/blob/master/templates/myaccount/header.php) - -##### Deleted Templates - -+ /myaccount/my-achievements.php -+ /myaccount/my-courses.php -+ /myaccount/my-memberships.php - - -v3.13.1 - 2017-10-04 --------------------- - -+ Fix caching issue preventing quiz pass & fail engagements from triggering. -+ Fix issue causing the "Builder" link to display on the lesson post table screen. -+ Fix issue preventing new courses & memberships from being moved from draft -> published. -+ Fix `wpdb->prepare()` empty placeholder issue related to engagement queries. Fixes warning added in WP 4.9. -+ Add better version numbering to static assets to prevent caching issues during plugin updates - - -v3.13.0 - 2017-10-02 --------------------- - -##### An All New Course Builder - -+ The "Course Outline" metabox found on the admin panel when editing any LifterLMS course has been savagely beaten. We stole its lunch money and we put it towards the construction of an all interface -+ Asynchronous loading: fixes issues where very large courses would drastically slow and possibly even time out the loading of the course edit screen -+ Course outline is now collapsible and expandable. This Fixes issues where it was very hard to move lessons and sections around on very large courses -+ In addition to the familiar (and now improved) drag and drop functionality, you may now also move sections and lessons up and down with button clicks. You can also move lessons between sections with button clicks -+ Add new lessons and sectiosn with a click or drag a new lesson or section into the existing course -+ Edit section and lesson titles faster with inline title editing. No more modals with a potentially slow ajax load to update a title. Click the title, change it, and exit the field to automatically save! -+ Delete sections and lessons with the click of a button -+ Quick links to view (frontend) and edit (backend) lessons -+ Completely internationalized. Thanks for you patience translators! -+ Want to know more? Check out the [docs](https://lifterlms.com/docs/using-course-builder/). - -##### New User Roles - -+ Added new roles to enable you to provide access to LifterLMS (settings, courses building, etc...) without having to make an admin or mess with complicated code snippets. -+ New Roles: - - + LMS Manager: Do everything in LifterLMS and nothing with plugins, themes, core settings, and so on - + Instructor: Create, update, and delete courses and memberships - + Instructor's Assistant: Edit courses and memberships - -+ More details and a full list of new LifterLMS capabilities are available [here](https://lifterlms.com/docs/roles-and-capabilities/). - - -##### Updates & Fixes - -+ Tested up to WordPress 4.8.2 -+ The "Lesson Tree" metabox has been replaced with a simplified version of the lesson tree and a link to the launch the Course Builder. -+ Course and membership categories and tags will now display on their respective post tables for sorting and filtering. They can be disabled on a per-user basis via the screen options. -+ Removed `var_dump()` from bbPress integration restriction check - -##### Uninstall Script - -+ Uninstall script now removes all the things LifterLMS creates in your database if a constant is defined. Read more [here](https://lifterlms.com/docs/remove-lifterlms-data-plugin-uninstallation/). - -##### Database Update - -+ Adds default Instructor data for all LifterLMS Courses & Memberships based off of the post author of the course or membership -+ [More information](https://lifterlms.com/docs/lifterlms-database-updates/#3130) - -##### Template Updates - -+ [admin/post-types/students.php](https://github.com/gocodebox/lifterlms/blob/master/templates/admin/post-types/students.php) -+ [admin/reporting/tabs/students/courses.php](https://github.com/gocodebox/lifterlms/blob/master/templates/admin/reporting/tabs/students/courses.php) - -##### Deprecated Functions - -+ The following AJAX functions are no longer utilized by LifterLMS core. If you are utilizing them find alternatives (they all exist). These will be remove in the next **major** release: - - + `LLMS_AJAX::get_achievements()` - + `LLMS_AJAX::get_all_posts()` - + `LLMS_AJAX::get_associated_lessons()` - + `LLMS_AJAX::get_certificates()` - + `LLMS_AJAX::get_courses()` - + `LLMS_AJAX::get_course_tracks()` - + `LLMS_AJAX::get_emails()` - + `LLMS_AJAX::get_enrolled_students()` - + `LLMS_AJAX::get_enrolled_students_ids()` - + `LLMS_AJAX::get_lesson()` - + `LLMS_AJAX::get_lessons()` - + `LLMS_AJAX::get_lessons_alt()` - + `LLMS_AJAX::get_memberships()` - + `LLMS_AJAX::get_question()` - + `LLMS_AJAX::get_sections()` - + `LLMS_AJAX::get_sections_alt()` - + `LLMS_AJAX::get_students()` - + `LLMS_AJAX::update_syllabus()` - -##### Removed Filters - -+ The following filters have been removed and are no longer in use. - - + `lifterlms_admin_courses_access`: replaced with user capability `edit_courses` - + `lifterlms_admin_membership_access`: replaced with user capability `edit_memberships` - + `lifterlms_admin_reporting_access`: replaced with user capability `manage_lifterlms` - + `lifterlms_admin_settings_access`: replaced with user capability `manage_lifterlms` - + `lifterlms_admin_import_access`: replaced with user capability `manage_lifterlms` - + `lifterlms_admin_system_report_access`: replaced with user capability `manage_lifterlms` - - -v3.12.2 - 2017-09-18 --------------------- - -##### Bug fixes - -+ Fix issue with LifterLMS bbPress integration preventing course-restricted topics from being accessible by enrolled students -+ Fix an issue preventing students expired from courses via access expiration settings from being manually re-enrolled by admins - -##### Deprecations - -+ `LLMS_Student` class function `has_access` is scheduled for depercation in next major release. Developers should switch to `LLMS_Student->is_enrolled()` - - -v3.12.1 - 2017-08-25 --------------------- - -+ Prevent duplicate loading of repeater metabox fields -+ Fix undefined warning related to quiz completion -+ Ensure that the bbPress course forums shortcode & widget properly cascade up when used on a lesson or quiz - - -v3.12.0 - 2017-08-17 --------------------- - -+ New quiz feature: randomize the order of quiz questions each attempt! Props to [Larry Groebe](https://github.com/larrygroebe) -+ Fixed logic error related to access checks when bubbling from quiz->lesson->course -+ Fixed JS loader check for tinyMCE editors in repeater fields -+ Fixed CSS issue related to tinyMCE editors in repeater fields -+ Fixed issue causing tinyMCE editors in repeater fields to stop working after reordering rows -+ LifterLMS alert box notices are now cleared during shutdown instead of immediately after rendering. Fixes some plugin compatibility issues. -+ Fix reference to invalid meta key on order notes admin screen. -+ Record order note when orders with a defined length complete -+ When a payment is scheduled for an order with a defined length, calculate end date if no end date is saved -+ Minor updates to the `LLMS_Abstract_Integration` class -+ Fix undefined reference error on 404 pages resulting from the preview manager. - -##### bbPress Integration Updates - -+ Add "Private" Course Forums which allows forums to be made available only to students enrolled in the associated course -+ Adds a shortcode and widget for outputting a list of forums associated with a course -+ Adds the ability to restrict the page set as the bbPress forum index (via bbPress settings) to be restricted to LifterLMS memberships -+ Adds engagement triggers to allow engagements to be fired when a student posts a reply or creates a new topic -+ Improves integration membership restriction check performance -+ Migrated to the `LLMS_Abstract_Integration` class. Visually changes the settings display but has no other impact -+ [More information](https://lifterlms.com/docs/lifterlms-and-bbpress/) - -##### BuddyPress Integration Updates - -+ Add the ability to restrict activity, group, and memeber directory pages to LifterLMS memberships. -+ Migrated to the `LLMS_Abstract_Integration` class. Visually changes the settings display but has no other impact -+ [More information](https://lifterlms.com/docs/lifterlms-and-bbpress/) - -##### Database update - -+ calculate and store end dates for orders created prior to version 3.11.0 which have a defined length and do not have a stored end date. -+ migrate bbPress and BuddyPress options to `LLMS_Abstract_Integration` naming convention -+ [More information](https://lifterlms.com/docs/lifterlms-database-updates/#3120) - -##### Admin Post Table Upgrades - -+ Lessons - + Fix section titles which formerly were a dead link. Now they're just text - + Add filtering the table by associated course -+ Quizzes - + Display associated course and lesson columns with links - + Add filtering by associated course and/or lesson -+ Quiz Questions - + Display associated Quizzes with links - + Add filtering by associated quiz - -##### Template Updates - -+ [admin/post-types/order-details.php](https://github.com/gocodebox/lifterlms/blob/master/templates/admin/post-types/order-details.php) - - -v3.11.2 - 2017-08-14 --------------------- - -+ Tested up to WP Core 3.8.1 - -##### System Status and Reporting updates - -+ System Report renamed to "Status" -+ Added information of template overrides to the system report -+ Added "Get Help" button linking to LifterLMS Ticketing submission page -+ Added "Logs" tab which allows for easy viewing & managment of LifterLMS logs -+ Added "Tools and Utilities" tab and moved tools from the General Settings screen to this tab -+ Improved Session Reset tool - - -v3.11.1 - 2017-08-03 --------------------- - -+ New shortcode: `[lifterlms_course_continue_button]`. See [shortcode docs](https://lifterlms.com/docs/shortcodes/#lifterlms_course_continue_button) for more information. -+ New shortcode: `[lifterlms_lesson_mark_complete]`. See [shortcode docs](https://lifterlms.com/docs/shortcodes/#lifterlms_lesson_mark_complete) for more information. -+ Added filter `llms_product_pricing_table_enrollment_status` to allow forceful display of course/membership pricing tables regardless of user enrollment status. -+ Fix course author shortcode to allow usage outside of a course via the `course_id` parameter. - -##### Template Updates - -+ [product/pricing-table.php](https://github.com/gocodebox/lifterlms/blob/master/templates/product/pricing-table.php) -+ [product/course/progress.php](https://github.com/gocodebox/lifterlms/blob/master/templates/product/course/progress.php) - - -v3.11.0 - 2017-07-31 --------------------- - -+ New engagement trigger "Student purchases access plan" allows engagements to be triggered from a specific access plan! -+ Minor performance improvements to notification-related database queries -+ Fix issue causing payment gateways to always use test mode links from Orders on the admin panel -+ Added default email notification merge code for outputting an HTML divider -+ Added new actions to Dashboard template to allow adding custom content to course tiles on the dashboard - -##### Template Updates - -+ [myaccount/my-courses.php](https://github.com/gocodebox/lifterlms/blob/master/templates/myaccount/my-courses.php) - - -v3.10.2 - 2017-07-14 --------------------- - -+ Fix fatal error related to purchase receipts for trashed or deleted orders -+ l10n "Reviews" tab title on course settings -+ Remove commented out sample preheader text from email header template which was displaying in some email clients. - -##### Template Updates - -+ [emails/header.php](https://github.com/gocodebox/lifterlms/blob/master/templates/emails/header.php) - - -v3.10.1 - 2017-07-12 --------------------- - -##### Bugfixes - -+ Prevent errors related to attempting to display notification data related to deleted students -+ Fix errors related to displaying notifications for deleted post (courses, sections, lessons, quizzes, etc...) -+ Fix error causing email notifications being sent after related user has been deleted -+ Fix typo preventing `llms_form_field()` from outputting textareas - -##### Updates - -+ Add new filter `llms_allow_subscription_cancellation` useful for preventing students from self-cancelling their subscriptions on the student dashboard. [More info](https://lifterlms.com/docs/lifterlms-filters/#llms_allow_subscription_cancellation). -+ Add new API for querying students via AJAX select2 elements -+ Select2 Post Query elements can now query multiple post types simultaneously -+ Seletc2 Post Query elements can now support `<optgroup>` - -###### i18n - -+ Course option metabox for reviews is not translateable - - -v3.10.0 - 2017-07-05 --------------------- - -##### Recurring Order Management (for Admins) - -+ Admins can now edit various pieces of data related to a recurring order from the order screen on the admin panel - + Allow editing of the Next Payment Date - + Allow editing of the Trial End Date (when a trial is active for the order) - + Edit Payment Gateway and related gateway fields (Customer ID, Source ID, and Subscription ID) -+ If you're using LifterLMS Stripe or LifterLMS PayPal please update to the latest version of these add-ons to take advantage of these new features! - -##### Recurring Order Management (for Students) - -+ Students can now switch the payment method (source) for their recurring subscritions from the student dashboard -+ Students can now cancel their recurring orders to prevent future payments on recurring orders -+ If you're using LifterLMS Stripe or LifterLMS PayPal please update to the latest version of these add-ons to take advantage of these new features! - -##### Automatic Payment Retries (for supporting gateways) - -+ LifterLMS Stripe and LifterLMS PayPal can now automatically retry failed payments to help recover lost revenue as a result of temporary declines to payment sources. Please see our documentation on this new feature [here](https://lifterlms.com/docs/automatic-retry-failed-payments/). -+ If you're using LifterLMS Stripe or LifterLMS PayPal please update to the latest version of these add-ons to take advantage of these new features! - -##### Manual Payment Gateway Enhancements - -+ The Manual Payment Gateway (bundled with LifterLMS Core) can now handle recurring payments. For more information on utilizing recurring payments with the Manual Gateway please see the [gateway documentation](https://lifterlms.com/docs/using-lifterlms-manual-payment-gateway/). - -##### Updates and Fixes - -+ Force SSL setting now applies to Student Dashboard screens. This is useful as Google now recommends any page where a password is submitted should be encrypted and allows gateway communication from student dashboard screen with APIs that require an SSL connection. -+ Fixed spelling error related to quizzes - -##### Templates changed - -**NEW** - -+ [checkout/form-switch-source.php](https://github.com/gocodebox/lifterlms/blob/master/templates/checkout/form-switch-source.php) -+ [myaccount/view-order-transactions.php](https://github.com/gocodebox/lifterlms/blob/master/templates/myaccount/view-order-transactions.php) - -**UPDATED** - -+ [admin/post-types/order-details.php](https://github.com/gocodebox/lifterlms/blob/master/templates/admin/post-types/order-details.php) -+ [myaccount/my-orders.php](https://github.com/gocodebox/lifterlms/blob/master/templates/myaccount/my-orders.php) -+ [myaccount/navigation.php](https://github.com/gocodebox/lifterlms/blob/master/templates/myaccount/navigation.php) -+ [myaccount/view-order.php](https://github.com/gocodebox/lifterlms/blob/master/templates/myaccount/view-order.php) -+ [quiz/summary.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/summary.php) - - -v3.9.5 - 2017-06-13 -------------------- - -+ Increased css z-index of basic notifications to prevent issues with themes that have high z-index on menus and other elements -+ Increased the frequency of basic notification heartbeat check from 10 to 20 seconds -+ Added filter to allow for customization of the notifications heartbeat interval, example [here](https://lifterlms.com/docs/lifterlms-filters/#llms_notifications_settings). -+ Fixed error related to password reset when the "Disable Usernames" account setting is disabled - - -v3.9.4 - 2017-06-12 -------------------- - -+ Fix hardcoded db reference to `wp_posts` table - - -v3.9.3 - 2017-06-09 -------------------- - -+ Fix typo in notifications query - - -v3.9.2 - 2017-06-07 -------------------- - -+ Tested up to WordPress 4.8 -+ Fixed issue with merge codes on WP Editors for notifications, emails, etc... -+ Update notifications query to only return results related to posts which actually exist. Prevents errors occuring when reviewing achievements on the student dashboard for courses, lesseons, etc which have been deleted/trashed. -+ Only display quiz time limit meta information when a time limit exists -+ Fix display of quiz question order (question x of x) -+ Improved logic powering quiz attempt grading for increased consistency, especially with regards to floats and rounding - -##### Templates Changed - -+ [quiz/meta-information.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/meta-information.php) -+ [quiz/question-count.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/question-count.php) - - -v3.9.1 - 2017-06-02 -------------------- - -+ Fix engagement triggers with relation to quizzes to properly recieve 3.9 api updates -+ Fix quiz attempt counting issue resulting in the total attempts by a student always being one more than the actual value -+ Fix membership access plan restrictions tooltip - - -v3.9.0 - 2017-06-02 -------------------- - -##### Quizzes - -+ All new quiz results interface for students - + Donut charts are now animated - + Donuts will be green for passing attempt and red for failing - + Students can now review previous quiz attempts and summaries - + Removed the juxtaposition of the current and best attempts to reduce confusion on the interface - + Improved the consistency of the quiz meta information markup - + Adjusted various pieces of language for an improved student experience -+ Improvements to the quiz taking experience - + Added the LLMS_Spinner (seen on checkout screens and various places on the admin panel) and various loading messages when starting quiz, transitioning between questions, and completing a quiz - + Better error handling and management should issues arise during a quiz - + Better unload & beforeunload JS management to warn students when they attempt to leave a quiz in progress -+ Improved quiz data handling and management - + Improved API calls and handlers related to taking quizzes for increased performance and consistency - + quiz data can now be programattically queried via consistent apis and data classes, see `LLMS_Student->quizzes()` and `LLMS_Quiz_Attempt` -+ Quizzes no longer rely on session and cookie data. All quiz data will always be saved directly to the database and related to the student. Fixes an issue on certain servers preventing student from starting quizzes. -+ Deprecated `LLMS_Quiz::start_quiz()`, `LLMS_Quiz::answer_question()`, and, `LLMS_Quiz::complete_quiz()` - + Ajax handler functions of the same names should be used instead. - + To programmatically "take" quizzes use related functions of similar names from the `LLMS_Quiz_Attempt` class - -##### Templates changed - -+ New - + [quiz/meta-information.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/meta-information.php) - -+ Updated - + [admin/reporting/tabs/students/courses.php](https://github.com/gocodebox/lifterlms/blob/master/templates/admin/reporting/tabs/students/courses.php) - + [content-certificate.php](https://github.com/gocodebox/lifterlms/blob/master/templates/content-certificate.php) - + [course/complete-lesson-link.php](https://github.com/gocodebox/lifterlms/blob/master/templates/course/complete-lesson-link.php) - + [myaccount/my-notifications.php](https://github.com/gocodebox/lifterlms/blob/master/templates/myaccount/my-notifications.php) - + [quiz/next-question.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/next-question.php) - + [quiz/previous-question.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/previous-question.php) - + [quiz/question-count.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/question-count.php) - + [quiz/quiz-question.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/quiz-question.php) - + [quiz/quiz-wrapper-end.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/quiz-wrapper-end.php) - + [quiz/quiz-wrapper-start.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/quiz-wrapper-start.php) - + [quiz/results.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/results.php) - + [quiz/return-to-lesson.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/return-to-lesson.php) - + [quiz/single-choice_ajax.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/single-choice_ajax.php) - + [quiz/start-button.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/start-button.php) - + [quiz/summary.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/summary.php) - -+ Removed - + quiz/attempts.php - replaced by [quiz/meta-information.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/meta-information.php) - + quiz/passing-percent.php - replaced by [quiz/meta-information.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/meta-information.php) - + quiz/time-limit.php - replaced by [quiz/meta-information.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/meta-information.php) - -##### Fixes - -+ Student Dasbhoard notifications page will not display pagination links unless there's results to page through -+ Student Dasbhoard notifications page will now display a message when no notifications are found -+ Certificate previewing now takes into consideration the preview setting roles to allow admins (or other roles) to preview certificates -+ Made student name self fallback (you) i18n friendly - - -v3.8.1 - 2017-05-21 -------------------- - -+ Fix merge code issue related to course title on quiz notifications - - -v3.8.0 - 2017-05-20 -------------------- - -+ Automatic email and basic (on-screen) notifications for various events within LifterLMS - + All notifications can be customized - + Email notifications can be optionally sent to custom email address, course authors, and more -+ Students will automatically receive email receipts when making purchases and when recurring access plans rebill -+ Hidden Access Plans -+ Add a "Purchase Link" view button to access plans so admins can quickly grab the direct URL to an access plan -+ Notifications history screen on Student Dashboard to review past notifications that have been received -+ Updated LLMS_Email class and functionality -+ Email templates have been completely rewritten and styled -+ Updated and rewritten password reset flow -+ Earned certificates are only accessible by the student who earned the certificate -+ Added the functionality for image upload via options & settings api -+ Removed a handful of unused templates related to LifterLMS certificates that were replaced a long time ago but still existed in the codebase for unknown reasons. -+ Fixed filter on engagements settings page -+ Minor adjustments to language and settings order on Engagements settings screen for email settings -+ Email Header Image field is now an upload field as opposed to a "paste a url here" setting -+ Phone number recorded to order and displayed on order for admin panel during purchases -+ Order details now display full country name as opposed to the country code -+ Fix installation script to ensure admin can preview by default - - -v3.7.7 - 2017-05-16 -------------------- - -+ Updated a few strings on the admin panel to be translateable -+ Fix PHP warning output during plugin activation -+ Fix reporting issue related to outputting quiz question answers where the correct answer is the first available answer -+ Fix PHP 7.1 issue on the checkout screen -+ Removed some unnecessary files from vendor libraries - - -v3.7.6 - 2017-05-05 -------------------- - -+ New translations for new categories on Add-ons screen -+ Update to general settings which utilizes featured items from the general settings screen -+ Update readme & related meta files -+ Removed advert image files - - -v3.7.5 - 2017-05-02 -------------------- - -+ Upgrade WP Session Manager to latest version -+ Codestyle updates across most files in codebase to bring to most recent styling guidelines put forth by [WP Coding Standards](https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards) - - -v3.7.4 - 2017-04-26 -------------------- - -+ When cloned site detected automatically disable recurring_payments feature & trigger an action 3rd parties can hook into for custom 3rd party features -+ Add better JS dependency management to prevent issues where assets loaded in the wrong order -+ Fix issue where dismiss icon on LifterLMS admin notices was positioned poorly on non-LifterLMS admin screens -+ Fix issue preventing edit account form submission on student dashboard when password strength meter is disabled - - -v3.7.3 - 2017-04-21 -------------------- - -+ Fixed issues where Course Track checks were not functioning properly with relation to prerequisite associations -+ `LLMS_Generator` can now be used to generate course(s) from a raw array of course data using the SingleCourseGenerator and BulkCourseGenerator -+ `LLMS_Generator` default post status can be set at runtime using `set_default_post_status()` -+ Fixed an issue causing JS errors on the `wp-login.php` screen -+ Tested up to WordPress 4.7.4 - -### Template Updates - -+ `course/prerequisites.php` - Prerequisite checks check for 'course_track' rather than 'track' - - -v3.7.2 - 2017-04-17 -------------------- - -+ Resolved a JS errors on admin panel resulting from overly strict asset loading added in 3.7.0 - - -v3.7.1 - 2017-04-14 -------------------- - -+ Fix php notice when no roles are selected for preview management feature - - -v3.7.0 - 2017-04-13 -------------------- - -**Preview Management** - -+ All new view management for users to make editing content easier for course builders -+ Admins may customize the roles of users who can access view management -+ Qualifying users can view content as an enrolled student or a non-enrolled visitor -+ Default view allows users to bypass all restricitons (drip, membership, enrollment, and so on) for easy course navigation and management -+ Thanks to [@fabianmarz](https://github.com/fabianmarz) and the team at and the team at [netzstrategen](https://github.com/netzstrategen) for their assistance with this feature! - -**Improvements** - -+ Edit Account Screen now utilizes updated APIs for better customization management -+ Improve intelligence of enqueued admin js & css files - -**Fixes** - -+ Fixed coupon calculation issue related to currencies using commas as the decimal separator -+ Properly display track related information when reviewing engagements on the admin panel -+ fixed issue preventing course tracks from being recorded as completed - - -v3.6.2 - 2017-04-10 -------------------- - -+ Fix issue preventing export of vouchers via email -+ added action `after_llms_mark_complete` to allow custom actions to happen after a course, lesson, etc... is marked complete - - -v3.6.1 - 2017-03-28 -------------------- - -+ Fix issue related to taking a quiz for the first time when no quiz data is available for a user -+ Fix issue when course outline shortcode is displayed on non LifterLMS post types - - -v3.6.0 - 2017-03-27 -------------------- - -+ Courses and Memberships now have settings to control their visibility in catalogs and search results. For more information visit the [knowledge base](https://lifterlms.com/docs/course-membership-visibility-settings/). -+ Courses are now a searchable post type. All existing courses will automatically remain excluded from search via new catalog visibility settings. New courses added after this date will be searchable unless the visibility is updated prior to publishing the course. -+ Added options (and filters) to allow customization of the order of courses displayed on the Student Dashboard - + Existing behavior (ordered by enrollment date, most recent to least recent) will be preserved - + New installations will default (by popular demand) to Order (Low to High) which will obey the "Order" settings of courses - + Customize or update the order for your site by visiting LifterLMS -> Settings -> Accounts and changing the setting for "Courses Sorting" under "Account Dashboard" -+ New Shortcodes: - + `[lifterlms_course_author]` - Display the Course Author's name, avatar, and (optionally) biography. [Info & Usage](https://lifterlms.com/docs/shortcodes/#lifterlms_course_author) - + `[lifterlms_course_continue]` - Display a progress bar and continue button for enrolled students only. [Info & Usage](https://lifterlms.com/docs/shortcodes/#lifterlms_course_continue) - + `[lifterlms_course_meta_info]` - Display all meta information for a course. [Info & Usage](https://lifterlms.com/docs/shortcodes/#lifterlms_course_meta_info) - + `[lifterlms_course_prerequisites]` - Display a notice describing unfulfilled prerequisites for a course. [Info & Usage](https://lifterlms.com/docs/shortcodes/#lifterlms_course_prerequisites) - + `[lifterlms_course_reviews]` - Display reviews and review form for a LifterLMS Course. [Info & Usage](https://lifterlms.com/docs/shortcodes/#lifterlms_course_reviews) - + `[lifterlms_course_syllabus]` - Display the course syllabus. [Info & Usage](https://lifterlms.com/docs/shortcodes/#lifterlms_course_syllabus) -+ "Back" & "Next" pagination links on Student Dashboard View Courses are now buttons instaed of text links -+ Fixed an issue preventing pagination links from displaying on the "View Courses" page of the student dashboard when the endpoint slug was customized -+ Course and Membership taxonomy archive pages will now properly match the heights of tiles -+ Fixed typo in `lifterlms_get_enrollment_status_name` filter -+ Fixed typo in `lifterlms_get_order_status_name` filter -+ Reduced complexity and redundancy of `llms_get_enrolled_students()` - - -v3.5.3 - 2017-03-21 -------------------- - -+ Ensure that access plan subscription schedule details are fully translateable -+ Ensure "Services" title on admin add-ons screen can be translated -+ Fix "View All My Courses" link on Student Dashboard to obey endpoint slug customizations -+ Membership restriction checks only run on singular posts (not on archives) -+ Ensure `[lifterlms_course_outline]` and Course Syllabus widget can be used on Quizzes. -+ Fix reporting widgets for course & lesson completions to report the correct completion types only - - -v3.5.2 - 2017-03-16 -------------------- - -+ Fix course outline shortcode when used on a lesson -+ Fix custom html form fields produced by `llms_form_field()` - - -v3.5.1 - 2017-03-15 -------------------- - -+ Lessons marked as incomplete will now display as incomplete in the course outline generated by the above Course Syllabus Widget and the course outline shortcode -+ Updated course outline shortcode / course syllabus widget to utilize new APIs -+ The template at `templates/course/outline-list-small.php` updated to reflect above changes. If you're overriding this template please review the changes and update accordingly -+ Fix issue preventing course auto advance on lesson completion -+ Shortcodes added within `[lifterlms_hide_content]` will now be processed - - -v3.5.0 - 2017-03-13 -------------------- - -+ New course setting **Retake Lessons** allows students to mark lessons as "incomplete" after completing lessons. Admins may enable this site-wide setting under Settings -> Courses. -+ Course and Membership catalog per page settings will now only accept numbers -+ "Catalogs" settings tab has been split into "Course" and "Membership" settings -+ Settings added via filter `lifterlms_catalogs_settings` will be added to the "Course" settings tab and deprecated in the next major release -+ Default course and membership catalog courses per page changed to 9. Previous default was 10 which results in a 4th row on catalogs with only one item. -+ Tweaked size of LifterLMS admin tab menu items -+ Pass API Mode Context to links generated by LifterLMS payment gateways -+ Fixed typo on general settings screen -+ Moved LifterLMS Add-on Banners from General Settings to an Add-Ons menu -+ If required fields exist on checkout and are empty during free quick enrollment users will be redirected to the normal checkout page where they can enter required fields -+ Updated action scheduler lib to latest version. Minor changes, fixes compatibility with WooMemberships. -+ Recent activity stats widgets on general settings screen updated to be more reliable and accurate (and performant!) -+ Added 3 new widgets to enrollments reporting tab: courses completed, lessons completed, and user registrations - - - -v3.4.8 - 2017-03-07 -------------------- - -+ Tested to WordPress Version 4.7.3 -+ Fixed undefined index notice on admin panel -+ Added a real description to new `_nx()` functions -+ Access plan trial periods now allow proper translations - - -v3.4.7 - 2017-03-03 -------------------- - -+ Ensure run when the `lifterlms_db_version` option doesn't exist in the database - - -v3.4.6 - 2017-03-03 -------------------- - -+ Fixed a text domain typo preventing translation of "Correct Answer" on quiz results screen -+ Ensure access plan "periods" are translateable -+ Now using `date_i18n()` for certificate dates so that dates are properly localized -+ Load plugin textdomain during `init` rather than `plugins_loaded` - - -v3.4.5 - 2017-02-23 -------------------- - -+ Ensure free access plans are available to logged out users - - -v3.4.4 - 2017-02-22 -------------------- - -+ Added a popup to warn students when leaving a quiz they've already started -+ Enable removal of student quiz attempts by admins from student reporting screens -+ Fix an undefined error on quiz reporting screens for incomplete quizzes -+ Display incomplete (abandonded) quizzes as incomplete (instead of as still running) on the quiz reporting screen -+ Prevent logged in users from bypassing membership restrictions for free members-only access plans - - -v3.4.3 - 2017-02-20 -------------------- - -+ Fix issue with bbPress integration so that forums restricted to multiple memberships allow users of at least one membership that the forum is restricted to access topics within that forum -+ Ensure that the correct ajax url is used for quizzes, resolves issue for sites utilizing `FORCE_SSL_ADMIN` -+ Refactored database background update scripts for increased reliability & performance -+ Database ugrdate 3.3.0 moved to 3.4.3 in order to accommodate users who were unable to run the 3.3.0 update, please read the [3.4.3 database update notes](https://lifterlms.com/docs/lifterlms-database-updates/#343) for more information. -+ WIP: refactoring shortcodes to a more sane set of functions and classes - - -v3.4.2 - 2017-02-14 -------------------- - -+ Backwards compatible css for tooltips - - -v3.4.1 - 2017-02-14 -------------------- - -+ Password strength meter now functions correctly when using the [lifterlms_registration] shortcode -+ Ensure open registration with required voucher prevents registration with invalid vouchers -+ Lesson completion via quiz completion only recorded the first time the quiz is completed -+ Fix issue preventing membership catalog from obeying the catalog's ordering settings -+ Prevent duplicate engagements from being triggered -+ Admin tables can display percentages as a progress bar! -+ Students reporting table displays overall progress as a progress bar -+ Refactored frontend assets class to allow better management of inline scripts - - -v3.4.0 - 2017-02-10 -------------------- - -+ Enrollment for free access plans has improved based on your feedback. For more information see [https://lifterlms.com/docs/checkout-free-access-plans/](https://lifterlms.com/docs/checkout-free-access-plans/) -+ Updraded Student Management Table for courses and memberships: - + Allow searching students by name / email - + Allow filtering of students by current status - + Allow sorting of students by name, user id, status, and enrollment updated date - + Added student's grade to the table (courses only) - + Table pagination allows skipping to the first and last pages - + Student names link to full student reporting screen - + Student IDs added to the table. ID links to the WP User Edit screen which was previously accessible by clicking the student's name - + Utilizing improved database queries for displaying data on the table -+ One-click bulk enrollment of all current members of a membership into an auto-enrollment course. More info [here](https://lifterlms.com/docs/membership-auto-enrollment/#bulk-enrollment) -+ Students reporting table pagination can now jump to first and last page -+ Students reporting table pagination now displays current page and total number of pages -+ Added new class `LLMS_Student_Query` which is modeled, loosely, off of the `WP_User_Query` and allows for querying student data in relation to courses -+ `LLMS_Admin_Table` abstract now supports filtering and jump to first and last page pagination options -+ `llms_get_enrolled_students` now utilizes `LLMS_Student_Query` and resolves a bug where some users returned by this query would be returned with the incorrect status. -+ Ensure `LLMS_Course::has_prerequisite( 'course' )` & `LLMS_Course::has_prerequisite( 'track' )` always return booleans -+ Made a small performance tweak for courses without audio / video embeds -+ Fix coupon expiration dates check to be more i18n friendly -+ Update `LLMS_Coupon` class to utilize 3.3.0 class property enhancements -+ added `llms_current_time`, a pluggable wrapper for `current_time()` to enable easier unit testing of date-related functions -+ Shortcodes within course restriction messages are now handled properly to output their intend content rather than the raw shortcode -+ Ensure the Page Attributes area is available on lessons so WordPress 4.7 custom post type page templates can be utilized - - -v3.3.1 - 2017-01-31 -------------------- - -+ Tested up to WordPress core 4.7.2 -+ Added new engagement triggers for Quiz completion, quiz failure, and quiz passed. -+ Refactored Lesson Completion for sanity -+ Added function `llms_mark_complete()` for simple programmatic completion of courses, sections, lessons, and tracks. See [usage docs](https://github.com/gocodebox/lifterlms/blob/master/includes/functions/llms.functions.person.php#L146-L162) for more information. -+ Class function `LLMS_Lesson::mark_complete()` has been staged for deprecation. It will still function but developers should update code to use above function. -+ LifterLMS background updaters will now display a progress report on the admin panel to add some transparency to how the update is doing. -+ Added `author` support to `llms_membership` post type -+ Added a way to remove all LifterLMS-generated data during plugin uninstallation. -+ `llms_get_post()` will now work with any LifterLMS Post Model post types -+ Removed references to `LLMS_Activate` class which was removed back in 2.0. -+ Changed include method to session related classes for better handling via phpunit -+ Refactored some of the `LLMS_Install` class for reliability and test coverage - + Changed order of table and option creation during installation. Prevents a database warning from being thrown during installation. - + Added funciton for retrieving default difficulty categories added during installation - + Added function for removing default categories added during installation -+ `llms_are_terms_and_conditions_required()` ensure the page id used in this function is an absint -+ Removed redundant function `LLMS_Lesson::single_mark_complete_text()` -+ Add css classes for buttons to be auto-width rather than the width of their containers -+ Fix ID of engagement email class. Allows some filters and actions to actually be used. -+ Properly display quiz failures as failures on the quiz results screen -+ `loop/feature-image.php` now works for unsupported PHP 5.5 and down -+ Fix issue with modyfying section titles from within the course builder -+ Fix undefined warning resulting from admin notice "flash" being undefined on prexisting saved notices -+ Updated template at `templates/course/complete-lesson-link.php` to include a few new CSS classes and utilize `llms_form_field()` to standardize buttons - - -v3.3.0 - 2017-01-23 -------------------- - -+ New course option allows displaying the video embed in place of the featured image on course tiles displayed on the course catalog screen -+ Courses can now be exported individually or in bulk. Export of a course includes all course content, sections, lessons, and quizzes. -+ Courses can now be duplicated. Duplication duplicates all course content, sections, lessons, and quizzes. -+ Upon completion of the Setup Wizard a sample course can be automatically installed. -+ Postmeta keys for Lessons and Sections which denote their relationship to their parents have been renamed for consistency, database upgrade 330 included in this release will rename the keys automatically. [Read more here](https://lifterlms.com/docs/lifterlms-database-updates/#330) -+ Update to `LLMS_Post_Model` to allow easier programmatic definition and handling of extending class properties -+ classes extending `LLMS_Post_Model` can now be serialized to json and converted to arrays programatically -+ new function `llms_get_post()` allows easier instantiation of an `LLMS_Post_Model` instance -+ Added LifterLMS Database Version to the system report - - -v3.2.7 - 2017-01-16 -------------------- - -+ Fix float conversion of large numbers with relation to coupon price adjustments - - -v3.2.6 - 2017-01-16 -------------------- - -+ Tested up to WordPress Core 4.7.1 -+ Fix the display of track-related engagements on the engagement admin screen -+ Fix float conversion of large numbers with relation to prices - - -v3.2.5 - 2017-01-10 -------------------- - -+ New shortcode: `[lifterlms_pricing_table]` allows pricing table display outside of a course or membership. See [https://lifterlms.com/docs/shortcodes/#lifterlms_pricing_table](https://lifterlms.com/docs/shortcodes/#lifterlms_pricing_table) for usage information. -+ New shortcode: `[lifterlms_access_plan_button]` allows custom buttons for individual access plans to be created outside of a pricing table. See [https://lifterlms.com/docs/shortcodes/#lifterlms_access_plan_button](https://lifterlms.com/docs/shortcodes/#lifterlms_access_plan_button) for usage information. -+ ensure every return from `llms_page_restricted` is filtered. Thanks to @matthalliday -+ Ensure purchase page can only load for valid access plans -+ Course / Membership taxonomy archives now obey orders defined by their respective catalog settings -+ Fix language of automatic validation error message for numeric field types -+ Fix translation function error causing course syllabus to display incorrect "x of x" text -+ Added correct text domain to an i18n string displayed on the checkout confirmation screen, thanks @ymashev -+ Ensure search result pages are viewable by members and non members regardless of result membership restrictions (unless site is restricted to sitewide membership) - - -v3.2.4 - 2017-01-03 -------------------- - -+ Fixed tooltips on lesson preview tiles (in course syllabus and on next/prev tiles inside lessons) to show the actual reason the lesson is inaccessible rather than always showing a generic enrollment message -+ Removed the language "You must enroll in this course to unlock this lesson" in favor of "You do not have permission to access to this content" as a restriction message fallback when no better message is available -+ "Quiz Results" title is now translateable -+ Removed deprecated JS file "llms-metabox-data.js" which controlled UI/X for 2.x subscription data on courses and memberships -+ Non LMS Content (pages, posts, forums, etc...) restricted to multiple memberships will now correctly allow users access to the content as long as they have access to at least one of the memberships -+ Fixed a redirect loop encountered if direct access to a lesson with an incomplete prerequisite was attempted - - -v3.2.3 - 2016-12-29 -------------------- - -+ Progress and Grade are now sortable columns on the student reporting table -+ Make enrollment statuses translateable for courses and memberships on the Student Dashboard -+ "Sign Out" text on student dashboard is now translateable, thanks @yumashev -+ Fixed prerequisite lesson display on lesson post tables -+ Ensure post archive (blog) is visible regardless of post membership restrictions -+ Moved lesson post table managment functions to their own class -+ Unused section post table management functions removed - - -v3.2.2 - 2016-12-21 -------------------- - -+ Adds filter `llms_student_dashboard_login_redirect` allowing customization of the redirect upon login via the Student Dashboard -+ Adds a shortcode parameter, `login_redirect` to `[lifterlms_my_account]` allowing customization of the redirect upon login via the Student Dashboard -+ Adds a new tool under "Tools and Utilities" on the LifterLMS Settings screen which allows users to clear the cached student overall progress and overall grade data -+ Fixes a compatibility issue with the OptimizePress live editor -+ Adds a text domain to a translation function where none was present, rendering the string untranslateable - - -v3.2.1 - 2016-12-14 -------------------- - -+ Fix operator position on `is_complete` check - - -v3.2.0 - 2016-12-13 -------------------- - -##### LifterLMS Reporting Beta - -+ Students overview displays broad information about your students in a searchable and sortable table -+ Review data about individual students including: - + Membership enrollments and statuses - + Course enrollments, status, and progress - + Quiz attemtpts and and their submitted answers - + Earned achievements and certificates -+ Sales and Enrollments analytics are now found under the "Reporting" screen -+ Feedback on the beta? Let us know at [https://lifterlms.com/docs/lifterlms-reporting-beta/](https://lifterlms.com/docs/lifterlms-reporting-beta/) - -##### Other Updates & Fixes - -+ Lesson completion checks now look for at least one record of the completed lesson as opposed to looking for exactly one -+ Fix positioning of teacher avatar on course/membership tiles -+ Remove explicit color definition from Student Dashboard navigation links for greater theme compatibility - - -v3.1.7 - 2016-12-06 -------------------- - -+ Added support for WordPress Twenty Seventeen theme -+ Improved the messaging and functions related to LifterLMS Sidebar support -+ Add alternate language for a quiz requiring 100% grade to pass -+ Added CSS class `.llms-button-primaray` to lessom "Mark as Complete" buttons -+ Add box-sizing css rule to LifterLMS form field elements. Fixes layout issues on themes that don't border-box everything. -+ Fix an issue that prevented the admin notice to enable/disable recurring payments from clearing when a button was pressed from screens other than the LLMS Settings screen -+ Fix next payment date error when viewing a cancelled recurring order on the student dashboard -+ Recurring payments now scheduled based on UTC time in accordance with the action scheduler which executes based on UTC rather than site timezone -+ Add existing lesson to course modal now relies on async search. Improves performance and prevents timeouts on sites with a 500+ lessons -+ Removed 2.x -> 3.x update notification message -+ Fix an issue with comment counting on PHP7 -+ Updated action scheduler library to latest version - - -v3.1.6 - 2016-11-11 -------------------- - -+ Handle empty responses on analytics more responsibly -+ Fix typo preventing completed orders from displaying in analytics when using course / membership filters -+ Quiz builder now leverages llmsSelect2 rather than select2 directly. Resolves a number of theme and plugin compatiblity issues. -+ Prevent bullets and weird margins on LifterLMS notices with slightly more specific CSS -+ Login error messages will now display regardless of whether or not open registration is enabled -+ Attempts to access quizzes are redirected or error messages are output when student is not enrolled. - - -v3.1.5 - 2016-11-10 -------------------- - -+ Fix Month display on Analytics Screen - - -v3.1.4 - 2016-11-10 -------------------- - -+ Progress bars are sligthly more intelligent to prevent a widowed "%" on themes with larger base font sizes -+ LifterLMS Merge code button only displays where it's supposed to now -+ Fix issue where users removed from a membership were not properly removed from courses they were auto-enrolled into because of that membership -+ Fix analytics screen JS parsing error - - -v3.1.3 - 2016-11-04 -------------------- - -+ Added new action hooks to the course syllabus widget/shortcode template -+ Added a small text link on the student dashboard which links to the full courses list of the dashboard -+ Display order revenue for legacy orders instead of 0 -+ Make the Order History table on the Student Dashboard responsive -+ Only display _published_ courses on the student dashboard -+ Fixes a conflict with WP Seo Premium's redirect manager which was creating access plan redirects -+ Reenable course review options on the admin panel -+ Updates review output method so reviews are now output via a removeable action - - -v3.1.2 - 2016-10-31 -------------------- - -+ Update all course and lesson templates to rely only on `global $post` rather than on `$course` and `$lesson` globals which are working inconsistenly across environments -+ Fix typo related to the line-height of LifterLMS order notes on the admin panel. Thanks [@edent](https://github.com/edent)! - - -v3.1.1 - 2016-10-28 -------------------- - -+ Shortcode `[lifterlms_hide_content]` has some new functionality. See [documentaition](https://lifterlms.com/docs/shortcodes/#lifterlms_hide_content) for usage and more information! -+ Fix logic when determining if terms and condition checkboxes should be displayed on checkout & open registration. -+ Define a placeholder on the Terms & Conditions page selection so it can be removed -+ Explicitly declare `LLMS_Lesson` on lesson audio/video embed templates instead of relying the global `$lesson`. Some environments appear to be losing the global. -+ Removed unused lesson template "full-descritpion" - - -v3.1.0 - 2016-10-27 -------------------- - -+ New engagement triggers available to allow engagements to be fired when a student enrolls into a course or membership! -+ Add custom email addresses for to, cc, and bcc when sending email engagements -+ New Merge Code button for easy merging of custom merge codes when creating emails -+ Added post table data for LifterLMS Engagements -+ Added new filter `llms_email_engagement_date_format` which allows customization of the format of the `{current_date}` merge code availabe in LifterLMS Emails -+ Added explicit max width declaration to images within LLMS Catalogs to prevent image overflow. Fixes some theme compatibility issues. -+ Optimize course and lesson audio video templates for faster loads -+ Fix course & lesson video to load videos instead of duplicating audio embeds -+ Fix coupon usage query so that coupons cannot be used more than the maximum number of times. Also now displays the correct number of coupons used on the coupons post table. -+ Fix LLMS Engagement Email merge codes to work in subject line - - -v3.0.4 - 2016-10-20 -------------------- - -+ Added shortcode `[lifterlms_login]` so the login form can be displayed. Information usage at [https://lifterlms.com/docs/shortcodes/#lifterlms_login](https://lifterlms.com/docs/shortcodes/#lifterlms_login) -+ Added internal function `LLMS_Student->get_name()` -+ Three basic course difficulties will be automatically created on installation and upgrades -+ Updated course difficulty save methods to rely only on the taxonomy rather than the taxonomy and postmeta table -+ Updated admin settings screens to only flush rewrite rules on screens where it is necessary to update rewrites -+ Fix issue with customization of LifterLMS account endpoint URLs -+ Fix a conflict with [Redirection](https://wordpress.org/plugins/redirection/) url monitoring that was causing redirects to be created from Courses and Memberships to the site home page automatically whenever updating the post -+ Fix an undefined index warning on courses / memberships when updating post data -+ Remove confusing and invalid warning message from Membership post screen on admin panel - - -v3.0.3 - 2016-10-17 -------------------- - -+ Added filter `llms_show_preview_excerpt` which can be used to hide the excerpt on course syllabus or next/back preview tiles in lesson navigation -+ Fix logic so that only free lessons are marked as free lessons post 3.0 upgrade -+ Fix incorrect display of the "restricted" and "non-restricetd" content areas for memberships -+ Fix undefinded index warning output by membership metaboxes -+ Fix dead like under "Force SSL" checkout setting -+ Course & Membership tiles output by course or membership shortcodes now automatically match column heights like the default catalogs do. -+ Correctly register students as the "Student" Role -+ Database Upgrade script converts users with the role "studnet" to "student" - - -v3.0.2 - 2016-10-14 -------------------- - -+ Added action `lifterlms_before_student_dashboard_tab` -+ Added action `lifterlms_after_student_dashboard_greeting` -+ Added action `lifterlms_after_student_dashboard_tab` -+ Added action `lifterlms_sd_before_membership` -+ Added action `lifterlms_sd_after_membership` -+ Fix membership shortcode -+ Fix issue that prevented "Student Dashboard" from rendering if the page was set as the child of another page -+ Fix undefined function error in admin notices -+ Fix nonce errors resulting from admin notice html being served from the database rather than being dynamically generated -+ Fix db ugrade script which was enabling course time period for restrictions for all courses regardless of their pre 3.0 restriction settings -+ Fix db uprgade script that was causing empty sale dates to show start of unix epoch b/c they were empty strings -+ Fix Javascript parse error prevnting section & lesson editing from within the course outling on the admin panel -+ Fix lesson icons from highlighting lesson settings like drip delay & quiz association -+ Updated course outline color scheme to match the 3.0 admin color scheme overhaul -+ `LLMS_Lesson::get_assigned_quiz()` will output depecation warnings for those using debug mode. LLMS core no longer uses this function and will be deprecated in the next major release. -+ Handle enrollment status of legacy orders based on enrollment rather than enrollment AND order status - - -v3.0.1 - 2016-10-13 -------------------- - -+ Properly prefix `llms_is_ajax()` to prevent 500 errors when leaving HTTPS forced checkout screen -+ Fix student unenrollment from memberships which was leaving a trace of enrollment in the user_meta table -+ Update student dashboard nav list items to have more specific no styles to prevent "double discs" on various themes -+ Return course progress bar and "continue" button which was accidentally removed -+ Added core support for "Divi" theme sidebars - - -v3.0.0 - 2016-10-10 -------------------- - -**This is a massive update which _breaks_ backwards compatibility for many LifterLMS features. A database migration is also necessary for upgrading users to reformat certain pieces of information which are being accessed differently in 3.0.0** - -**We strongly recommend that you backup your website before upgrading and, if possible, test LifterLMS 3.0.0 in a non-public-facing testing environment to ensure compatibility with your theme and other plugins and to ensure that 3.0.0 changes do not adversely affect your existing website.** - -**Please thoroughly read the following changelog and, if necessary, submit support tickets or post in the forums with any questions _prior_ to upgrading. LifterLMS Support _cannot_ and _will not_ manually resolve migration issues which may arise from upgrading to 3.0.0.** - -+ New shortcodes to be documented later, checkout "includes/class.llms.shortcodes.php" if you're feeling anxious -+ All kinds of CSS changes to make LifterLMS, in general, be a little less old looking -+ Added a number of CSS classes to various areas in the Checkout template at "templates/checkout/form-checkout.php" -+ Added a "Cancel" button that allows you to hide the coupon form if the user decides not to add a coupon -+ Removed jQuery animations from the coupon form toggle in favor of a CSS class toggle. If you decide you want some animations on the form add some CSS transitions to the `.llms-coupon-entry` element (and children) to change when the class `.active` is added or removed from the element. -+ Refactored JavaScript related to LifterLMS Checkout. Improvements are minimal (if any) but the file is now smaller and more readable! Yay code stuff. -+ Fixed some redundant text on single payment confirmation screen. ("Single payment of single payment of") -+ Added a link to memberships listed under "My Memberships" on the LifterLMS Account Screen -+ LifterLMS Order posts have been renamed in the database from "order" to "llms_order" to prevent any potential conflicts with other plugins. Automated database migration will handle the renaming of old orders. -+ Fixed undefined variable notice generated by Sections without any lessons inside of them -+ renamed function `add_query_var_product_id()` to `llms_add_query_var_product_id()` -+ added a class for interacting with a course TRACK, instatiated by a track term or term_id (`LLMS_Track`) -+ password strength meter and related settings / options via utilizing WordPress password strength functions available -+ cleaned up the lesson locked tooltips to be a bit more sane and also utilized in course navigation on individual lessons. -+ Updated admin menus for LifterLMS content to be more sane and organized and intuitive and so on and so forth - -##### Payment Gateways - -**NOTE: at this release, LifterLMS PayPal is the only payment gateway that will work with this release. We haven't started working on Stripe 4.0.0 which will work with LifterLMS 3.0.0** - -+ Payment gateways powered by a new abstract gateway class -+ PayPal has been removed from LifterLMS and is available as premium extension - -##### Frontend Notices - -+ LifterLMS "Notices" have been rewritten, slightly. -+ Most templates have been updated -+ associated CSS has been updated -+ Some sanity has been added to the related functions - -##### Post "Model" Concept / Overhaul - -Updated classes for programmatically accessing all sorts of data related to custom post types registered by LifterLMS. - -These post types currently include: - -+ Access Plans -- a non-public post type associated with courses and memberships which store payment related information -+ Coupons (replaces includes/class.llms.coupon.php) -+ Courses (replaces includes/class.llms.course.php) -+ Lessons (replaces includes/class.llms.lesson.php) -+ Memberships -+ Orders (replaces includes/class.llms.order.php -+ Products -- can be instantiated from courses or memberships (replaces includes/class.llms.product.php) -+ Transaction -- a non-public post type associated with orders which store completed/attempted transaction data - -##### Improved admin metabox methods (and related) - -+ Updated custom LifterLMS Admin Metaboxes to have a more sane programmatic interface. This affects nearly all admin metabox classes in the plugin. -+ A set of methods and classes have been added to improve the programmatic interface around custom post type post tables. These can be found in "includes/admin/post-types/post-tables" - -##### Coupons - -+ New class `LLMS_Coupon` allows for easy getting & setting of coupon data. -+ Updated coupon post table to include relevant coupon information for all coupons at a glance -+ Refactored admin panel coupon metabox generation to utilize new model for saving data -+ Added translation functions to all strings in coupon settings screen -+ Added new coupon settings - + _Expiration Date_ -- coupons cannot be applied to a purchase after the expiration date - + _Payment Type_ -- coupons can only be applied to either single or recurring payment plans. Existing coupons will be treated as single payment coupons until updated by the Admin. - + _First Payment Discount_ -- Applies only to recurring payment coupons. Determines the discount applied to the first payment of a recurring payment transaction. - + _Recurring Payments Discount_ -- Applies only to recurring payment coupons. Determines the discount applied all payments (other than the first) of a recurring payment transaction. - + _Description_ -- Record internal notes for a coupon visible only by admins on the admin panel -+ The "Coupon Code" field has been removed in favor of the WordPress Coupon Post Title being utilized as the code. After upgrading, an automated database migration will move all coupon code fields to the title. The title previously functioned as the coupon description. During the migration the existing title will be moved to the new description field. - - -##### Orders - -+ Added Order Statuses - + Completed - Single payment only. Denotes a sucessful transaction - + Active - Recurring only. Denotes the subscription is active with no issues - + Expired - Recurring only. Denotes the subscription has ended and is no longer active - + Refunded - Denotes the order has been refunded. - + Cancelled - Denotes the order has been cancelled manually by an admin. - + Failed - Denotes payment has failed. For subscriptions a failed payment will switch from "active" to "failed" - + Pending - Denotes that the order has been created but payment has not been completed yet -+ Admin panel order table new features: - + The following columns are now sortable in ascending and descending orders: Order, Product, and Date - + Added totals based on order type (single or recurring) to the "Total" column - + Added an order status column for quick status review -+ Order notes available for internal and system notes. powered by WP comments. lots of inspiration (and code) from WooCommerce, thank you <3 -+ Added a bunch of currency settings (as well as right-side currency and decimal-less currency support!) - -##### New Templates - -+ __Pricing Table__ at "templates/product/pricing-table.php" utilized by courses and memberships for displaying access plan information. Replaces "templates/membership/purchase-link.php" and "templates/course/purchase-link.php" -+ __Course Taxonomy Templates__ at "templates/course/categories.php", "templates/course/tags.php", and "templates/course/tracks.php" display comma separated lists for course custom taxonomy terms -+ __Course Prerequisite Template__ at "templates/course/prerequisites.php" displays prerequisite information (course and tracks) for a given course. -+ __Meta Wrapper__ templates at "templates/course/meta-wrapper-end.php" and "templates/course/meta-wrapper-start.php" wrap some HTML around various meta data output about a course -+ Significantly updated checkout process with all kinds of new templates including: - + templates/checkout/form-gateways.php - + templates/checkout/form-summary.php -+ __Unified "Lesson Preview"__ at "templates/course/lesson-preview.php" displays "buttons" in course syllabus (on course page) and in course navigation (on lesson pages) -+ Various template hook priority changes in order to make adding content between default LifterLMS areas easier - - -##### Deleted Templates -+ templates/checkout/form-checkout-cc.php -+ templates/checkout/form-pricing.php - - -##### New & Updated Admin Interfaces & Templates - -+ Significantly improved, changed, or brand new templates for metaboxes for various post types: - + templates/admin/post-types/order-details.php - + templates/admin/post-types/order-transactions.php - + templates/admin/post-types/product-access-plan.php - + templates/admin/post-types/product.php - -##### New Functions -+ `llms_confirm_payment_url()` - Retreive the URL used for confirming LifterLMS Payments -+ `llms_cancel_payment_url()` - Retreive the URL users are directed to when cancelling a payment - -##### Install Script - -+ Removed some legacy default options that were being created and are no longer required for new installations. -+ Removed unused `update_courses_archive()` function & related hook - -##### Select2 - -Now utilizing a forked version of Select2 to prevent 3.5.x conflicts we've been plagued with - -##### Deprecated - -+ Removed filter `lifterlms_get_price_html`, use `lifterlms_get_single_price_html` instead -+ Removed unused `LLMS_Product->get_price_suffix_html()` function -+ Removed `LLMS_Product->set_price_html_as_value()` because we didn't like it anymore, don't use anything instead. -+ Removed `add_query_var_course_id()` function -+ Removed `displaying_sidebar_in_post_types()` function with the `LLMS_Sidebars::replace_default_sidebars()` function -+ Filter `lifterlms_order_process_pending_redirect` has been replaced with `lifterlms_order_process_payment_redirect` -+ Action `lifterlms_order_process_begin` has been deprecated -+ Removed `lifterlms_order_process_complete` action -+ Replaced `LLMS_Course::check_enrollment()` with various new utilities. See `llms_is_user_enrolled()` for fastest use. -+ Officially removed the `LLMS_Language` class -+ Officially removed the `PluginUpdateChecker` class stubs we created to prevent updating issues with LifterLMS extensions during our transition to 2.0.0. This library has caused nothing but pain for everyone on our team and many of our users. It's gone now, forever. -+ Removed function `lifterlms_template_single_price()` and replacted with `lifterlms_template_pricing_table()` -+ Removed templates at "includes/course/price.php" and "includes/membership/price.php" in favor of "includes/product/pricing-table.php" -+ Removed `LLMS_Person::create_new_person()` in favor of `LLMS_Person_Handler::register()` or `llms_create_new_person()` -+ Removed `LLMS_Person->set_user_login_timestamp_on_register()` and are simply adding the metadata during registration -+ Removed `lifterlms_register_post` action hook which fired after new user registration validation, this has been replaced with `lifterlms_user_registration_after_validation` -+ Removed `lifterlms_new_person_data` and `lifterlms_new_person_address` filters, replaced with `lifterlms_user_registration_data` -+ Removed `LLMS_Person::login_user()` in favor of `LLMS_Person_Handler::login()` -+ background updater -+ system report facelift + inclusion of all new settings via `LLMS_Data` class -+ Fix setup wizard styles to follow update admin panel styles -+ add links to last step of setup wizard for documentation and demo -+ removed a bunch of deprecated coupon-related functions -+ added a "force ssl" option to ensure checkout is secured -+ added settings and options around recurring payments and staging sites to prevent duplicate charges when testing on a cloned site -+ Check course restrictions automatically when checking lesson -+ Added user_id to all access function checks to allow for checks for non current user -+ course restriction messages display regardless of enrollment status -+ check memberships and lock purchase of members only access plans -+ Fixed titles of course closed and open messages on the course restrictions options -+ record a start date for access plans based off when order mobes to complete or active for the first time -+ automatically expire limited access plans -+ gave a quick facelift & unification to a lot of admin panel elements -+ Color consistency updated according to LLMS brand guide -+ Unified frint and backend button classes -+ Updated all frontend buttons to have consistent classes -+ Removed the "FREE" lesson SVG in favor of simple text which allows translating -+ Install & activation overhauls. Resolves [#179](https://github.com/gocodebox/lifterlms/issues/179) -+ jQuery MatchHeight lib unignored -+ A bunch of settings pages updated and a bunch of settings deprecated -+ Gateways setting page removed -+ Memberships & Courses page combined into "Catalogs" settings -+ Added a data getting class used by the tracker class -+ added a new page creation function witn better intelligence that (hopefully) prevents duplicate pages from being created during core page installation -+ new default country setting -+ all order status changes recorded as order notes -+ pending orders can be completed after failed payments -+ better handling for gateways with fields -+ JS spinners support multiples via start & stop! -+ Updated (and semi-finished) analytics -+ achievemnt metabox converted -+ minor updates to voucher class -+ Added a "post state" visible on the Pages posts table identifying if the page is saved as a LifterLMS page (EG: Checkout Page) -+ Fixed copy/paste error of duplicate enrollment closed message on course restrictions tab -+ Removed WC integration in favor of WC -+ Upgade "back to course" template to new lesson API -+ Renamed `course/parent_course.php` to `course/parent-course.php` for template naming consistency -+ use `strict` when auto generating usernames when creating from email addresses, resolves [#182](https://github.com/gocodebox/lifterlms/issues/182) - -##### 3.0.0 Auto Upgrader - -+ lots of postmeta data rekeyed -+ intelligently generated defaults for various peices of new meta data on courses, lessons, and memberships -+ automatically generate access plans from existing course and membership data -+ update existing orders to pull semi-accurate data into analytics based on new database structure -+ cleans database of a ton of deprecated options and postmeta data - -##### Deprecated - -+ function `llms_is_user_member()`, use `llms_is_user_enrolled()` instead -+ function `llms_check_course_date_restrictions()` -+ function `quiz_restricted()` -+ function `membership_page_restricted()` -+ function `is_topic_restricted()` -+ function `llms_get_post_memberships()` -+ function `llms_get_parent_post_memberships()` -+ function `parent_page_restricted_by_membership()` -+ function `outstanding_prerequisite_exists()` -+ function `find_prerequisite()` -+ function `llms_get_course_enrolled_date()` -+ function `llms_get_lesson_start_date()` -+ function `lesson_start_date_in_future()` -+ function `page_restricted_by_membership_alert()` -+ function `llms_does_user_memberships_contain_course()` -+ class `LLMS_Checkout` -+ function `LLMS()->checkout()` - - -##### Auto Enrollment - -+ Course auto enrollment for Memberships has been restored -+ Works exactly the same as previously except auto-enrollment is not dependent on a course "belonging to" the membership via membership restrictions. This is because membership restrictions no longer apply to courses - -##### Analytcis - -+ Charts! I'm really excited about this. I know we still need more data but please say nice things to me, I worked really hard on these little charts. -+ Updated styles & interface - -##### bbPress - -+ Restrict individual forums (and their topics) to LifterLMS Membership levels - -##### BuddyPress - -+ Fixes broken course display on bp profile -+ Adds memberships subpage to bp profile - -##### notices - -+ Admin notices class for managing admin notices, it's pretty neat! - -##### Student Management on Courses and Memberships - -+ All new and improved student management interface for managing student enrollments from courses and memberhips - -##### Deprecated - -+ filter: `llms_meta_fields_course_main`, replace with `llms_metabox_fields_lifterlms_course_options` - -##### Manual Payments - -+ Manual Payment Gateway can now be enabled on the frontend! -+ When a manual payment is recorded the user will be redirected to a view order page where they will be prompted to make a manual payment -+ Define the payment instructions on the admin panel "Checkout Settings" -+ Once you verify payment, head to the pending order and hit the "Record a Manual Payment" button to record the transaction -+ Upon recording the order status will be upgraded to "Complete" and the user will be enrolled automatically - -##### Student Dashboard Upgrades - -+ More sane template hooks and functions -+ Pagination on Courses endpoint (view only a preview on the mian dashboard) -+ Orders history & view orders screens! - - - -Deprecated options (and related functons where applicaple) for the following course & membership options: - - + `lifterlms_button_purchase_membership_custom_text` - + `lifterlms_course_display_outline_lesson_thumbnails` - + `lifterlms_course_display_author` - + `lifterlms_course_display_banner` - + `lifterlms_course_display_difficulty` - + `lifterlms_course_display_length` - + `lifterlms_course_display_categories` - + `lifterlms_course_display_tags` - + `lifterlms_course_display_tracks` - + `lifterlms_lesson_nav_display_excerpt` - + `lifterlms_course_display_outline` - + `lifterlms_course_display_outline_titles` - + `lifterlms_course_display_outline_lesson_thumbnails` - + `lifterlms_display_lesson_complete_placeholders` - + `redirect_to_checkout` - -In all scenarions either a `add_filter` (returning false) or a `remove_action()` can be used to replicate the option. - - -v3.0.0-beta.4 - 2016-09-01 --------------------------- - -+ fix issue with course prereq checks -+ next payment due date visible on order admin view -+ trial end date visible on order admin view - -##### Free Access Plans - -+ "Free" access plans now defined as such based on a checkbox rather than by entering 0 into the price -+ Only single payment access plans can be free (a free recurring payment makes no sense but we can certainly discuss this if you disagree with me) -+ trials are disabled with free plans (because trials only apply to recurring plans) -+ sales are disabled for free access plans - -##### Checkout Form JS API - -+ unified JS checkout handler -+ allows extensions to enqueue validation or pre-submission JS functions that should run prior to checkout form submission - -##### Manual Payment Gateway - -+ handles purchase of access plans marked ar FREE & orders that are discounted to 100% via coupons - - - - -##### Open Enrollment - -+ Open Enrollment allows users to register on the account dashboard without purchasing a course -+ Voucher settings are available to customize whether vouchers should be optional or required during open registration -+ Better error reporting around voucher usage during enrollment - -##### Deprecated Functions - -+ `llms_get_coupon()` -+ `get_section_id()` -+ `check_course_capacity()` - - -##### Quizzes - -+ Updated admin metaboxes to use new metabox abstract class -+ display 0 instead of negative attempts on quiz summary -+ updated logic in start button template - -##### Emails (for engagements) - -+ Admin metabox updated to new API -+ Postmeta data migration: - + `_email_subject` renamed to `_llms_email_subject` - + `_email_heading` renamed to `_llms_email_heading` - - -v2.7.12 - 2016-09-22 --------------------- - -+ Added a new filter on content returned after port permission checks -+ Added additional information to plugin update message in preparation for major 3.0 release -+ Updated plugin contributor metadata - - -v2.7.11 - 2016-07-22 --------------------- - -+ Removed a duplicate action hook on course archive loop. -+ Switched registration template include to use a more sane function -+ Added updated banner adds with prettier ones. Wooooooo. - - -v2.7.10 - 2016-07-19 --------------------- - -+ Fix undefined noticed related to LifterLMS custom post type archive filtering -+ Fix filter which was supposed to allow custom engagment types to be queried & triggered by engagements automatically but was passing data incorrectly - -v2.7.9 - 2016-07-11 -------------------- - -+ We are now properly storing delayed engagment trigger data. -+ Fixed an issue with our engagment query functions that caused, in very rare circumstances, the extra engagements to be triggered during an engagment trigger due to a lack of specificity in our query -+ Fixed an undefined property notice related to email engagments when the email had no subject or header -+ Fixed a typo in the description of a translation function. -+ Added an engagment debug logging function. You can log all sorts of data related to engagements by adding `define( 'LLMS_ENGAGEMENT_DEBUG', true );` to your `wp-config.php` file. -+ Allow course title shortcode to be used on course pages (and quizzes too). Documentation incorrectly said it was available on courses so we've fixed the function to allow for use on courses. - - -v2.7.8 - 2016-07-05 -------------------- - -+ Bugfix: Restore access to quiz results on quiz completion - - -v2.7.7 - 2016-07-01 -------------------- - -##### Russian - -+ LifterLMS is now 100% Translated into Russian thanks to our new Russian Translation Editor [@kellerpt](https://profiles.wordpress.org/kellerpt/) - -##### l18n - -+ All transition messages between questions during a Quiz are now translatable. -+ LifterLMS subpages below the LifterLMS icon on the admin panel will now always display regardless of how you've chosen to translate the menu items. Hopefully puts to rest a long-standing i18n issue. - -###### Bug fixes - -+ Attempting to access a quiz when not enrolled in the associated course and having not properly started the quiz now results in a useful error message rather than a PHP warning. -+ We've adjusted the way we're adding a admin panel "seperator" to reduce conflicts with other plugins that have menu items with the same position as our seperator (51). -+ Added new logic to display an error message (instead of nothing) if there's an error during question loading. -+ Resolve issue with course progress bar when added to a quiz sidebar (assuming your theme has sidebar support on your quizzes). -+ Updated version number in the changelog for last version (it was supposed to be 2.7.6) - - -v2.7.6 - 2016-06-28 -------------------- - -+ Students manually removed by Memberships by using the "Students" tab of a LifterLMS Membership will now be fully removed from the membership. -+ Updated a few time-related strings to be l18n friendly. These items were all around Quiz time reporting and quiz time limits. -+ Updated testing information, tested up to WP 4.5.3 -+ Fixed date of last release on changelog. It had the wrong date. Does that really matter? -+ Updated readme.txt description area, we have a new youtube video! Yassss. - - -v2.7.5 - 2016-06-13 -------------------- - -##### New features -+ Added an "id" parameter to both LifterLMS Courses and LifterLMS Memberships shortcodes - -##### i18n -+ Allow date translation on quiz results screen by using `date_i18n()` instead of `date()` -+ Allow date translation on my courses screen by using `date_i18n()` instead of `date()` -+ Ensure course status "Enrolled" is translatable on my courses screen - -##### Fixes -+ Thanks to [@kjohnson](https://github.com/kjohnson) who fixed undefined index warnings & errors which occurred when viewing the last lesson in a section when the next section contained no lessons. -+ Resolved an issue where formatting for "Restricted Access Description" course content would not display proper formatting. -+ Fixed an issue with the "FREE" stamp for a free lesson caused layout issues. -+ Removed the "is-complete" css class from incorrectly being added to lesson preview tiles for free lessons -+ Fix an escaping issue when rendering Course titles inside LifterLMS notices. Prevents "\'s" from displaying when "'s" should be displaying (and similar issues). - - -v2.7.4 - 2016-05-26 -------------------- - -+ Fixed a bug with the new localization methods from 2.7.3 -+ Removed bundled it_IT translation files in favor of official language pack available at [https://translate.wordpress.org/projects/wp-plugins/lifterlms/language-packs](https://translate.wordpress.org/projects/wp-plugins/lifterlms/language-packs). -+ Removed bundled en_US translation files because LifterLMS is in English so the files are unnecessary. -+ Fixed a few mis-labled filters applied when registering LifterLMS Custom Post Types -+ Adjusted the default supported features of LifterLMS Quizzes and Questions - + Quizzes now support custom fields as per user request - + Commenting, thumbnails, and excerpts are no longer "supported" as they were never intended to be and were never correctly implemented. - + If you are relying on any of these features for your quizzes or questions please use the following filters to re-implement these features: `lifterlms_register_post_type_quiz` or `lifterlms_register_post_type_question`. These will allow you filter the default arguments LifterLMS passes to the WordPress function `register_post_type()` - - -v2.7.3 - 2016-05-23 -------------------- - -+ Added a separate filter for login redirects `lifterlms_login_redirect` and added the user_id as a second parameter available to the filter -+ Added second parameter to `lifterlms_registration_redirect` to allow access to the registered users's user_id -+ Fixed a timestamp conversion issue on Course sale price checks that caused indefinite sales (those with no date restrictions) to appear not on sale during certain periods of time. The period would differe depending on the server's timezone settings and the time of visit. -+ Added a "Pointer" when hovering quiz summary accordion to allow for a slightly more obvious user experience that the elements are expandable. -+ Added some new localization methods to ensure strings that only appear in Javascript files will be translator friendly. This initially fixes a few issues on the Quiz Summary page and during quiz taking where strings only appeared in Javascript and were, therefore, completely inaccessible to translators. - - -v2.7.2 - 2016-05-19 -------------------- - -+ In course syllabus widget & shortcodes free lessons will now be clickable links. -+ Record `llms_last_login` timestamp in usermeta when a user registers. - - -v2.7.1 - 2016-05-09 -------------------- - -##### Enrollment & Voucher Checks - -+ Enrollment functions will now automatically check to ensure that users are not already enrolled in a course or membership before enrolling. This addresses an issue which would create double enrollment for user redeeming a voucher for a product they were already enrolled in. -+ Vouchers will now automatically check to see if the user has already redeemed this voucher before allowing the user to redeem it. This would have caused multiple enrollments and would allow one user to eat up an entire voucher by using it over and over again for funsies. A voucher can now *only* be redeemed once by a user as intended. -+ `llms_is_user_enrolled()` now allows developers to check membership enrollment. Previously this function would only check enrollemnt of Courses despite what the documentation stated. - -##### Translation - -+ 3 strings have had translation functions added to them. This makes LifterLMS voucher reemptions translatable! - -##### Bugs & Fixes - -+ Fix javascript dependency & enqueueing issue on admin panel which prevented LifterLMS settings from saving correctly in various places -+ Removed inline CSS from "next lesson button" on quiz completion / summary screen. This was overriding some default styles and making the button very thin and gross. - - -v2.7.0 - 2016-05-05 -------------------- - -##### LifterLMS Custom User Fields Exposed - -+ Custom fields added during registration via LifterLMS account settings are now exposed on the admin panel via the student's WordPress user profile -+ All custom fields that are available (billing and phone) are editable on the WordPress user profile by anyone with profile edit access regardless of LifterLMS settings. If the settings are disabled (eg not required for registration) you can still add this information manually to a user's profile. This is useful if you require the information and then disable it later, you would still be able to access the information on the admin panel but would no longer be required for user's during registration. -+ A few new filters added to help developers customize the experience here. Check out the documentation at [https://lifterlms.com/docs/lifterlms-filters/#admin-user-custom-fields](https://lifterlms.com/docs/lifterlms-filters/#admin-user-custom-fields) - -##### Membership Manual Add & Remove Student Functions - -+ Duplicated "Students" tab from the Course admin screen to Memberships - + Students can be manually added to a membership by an admin - + Students can be removed manually from a membership by an admin - -##### Updates - -+ Added the ability for students to edit their phone number via their account settings page if the phone number registration option is enabled on the site. - -##### Fixes - -+ Fixed a few spelling errors on LifterLMS admin panel order screens -+ Fixed a typo on meta data for LifterLMS admin created (manual) orders - - -v2.6.3 - 2016-05-02 -------------------- - -+ Removed redirecting action from WooCommerce integration that was causing issues on mutliple product purchase checkouts with larger databases. -+ Added a new payment action `lifterlms_order_complete` which runs at the same time as some previous actions during payment processing but servers a different purpose. This is mostly in preparation for a forthcoming AffiliateWP integration. -+ Fixed an issue with LifterLMS certificate background image that caused the wrong dimensions to be returned when outputing a LifterLMS certificate background image - - -v2.6.2 - 2016-04-27 -------------------- - -+ Fix class conflict in collapsible course outline widget template which caused some UX issues. -+ Added new filters run during course & lesson sidebar registration to allow customization of LifterLMS sidebars - + `lifterlms_register_course_sidebar` - + `lifterlms_register_lesson_sidebar` -+ Removed a stray logging function. -+ Cleaned up some undefined variable warnings & notices on the quiz summary template -+ Fixed an issue appearing when registering users did not submit the optional phone number which caused a PHP notice -+ LifterLMS Orders generated by WooCommerce will now have a payment method of "WooCommerce". This also addresses an undefined notice produced during WooCommerce order completion because a LifterLMS Payment Method wasn't being defined. - - -v2.6.1 - 2016-04-26 -------------------- - -+ Fix class conflict in collapsible course outline widget template which caused some UX issues. - - -v2.6.0 - 2016-04-25 -------------------- - -##### Collapsible Course Outline Widget - -+ By request we've added an option to make your course outline widgets collapsible! -+ View feature [Documentation](https://lifterlms.com/docs/course-syllabus-widget/) -+ New translations available related to feature. I think it's 4 strings. - -##### Bug Fixes - -+ Removed an unused CSS selector that caused some issues on the admin panel. This resolves an issue identified with the Page Builder by SiteOrigin plugin. The selector was very generic (`.title`) and may have caused issues with other themes or plugins using that class. -+ Resolved an issue that prevented post update, save, and publishing messages for core post types (posts, pages) from displaying properly. - - -v2.5.1 - 2016-04-22 -------------------- - -+ Fixed session handler initilization as it was being initialized prior to user data availability. -+ Staged `LLMS_Language` class for deprecation in favor of WordPress translation functions `__()`, `_e()`, etc... **If you're a developer you'll start seeing warning's on screen or in your logs if you're using this function, it will be completely removed in the next MAJOR release (3.0.0)** -+ Added a new function to handle the deprecation warning above (`llms_deprecated_function`) and now that we have this function we'll start deprecating all the things. Just kidding, or am I? -+ This gives translators access to 69 new strings that were previously untranslatable! However, this number might be innacurate +/- 5 strings. I only counted it once and I don't feel like the exact number is important enough for a recount to ensure accuracy. /shrug - - -v2.5.0 - 2016-04-15 -------------------- - -**Admin Panel Order Table Updates** - -+ Several visual improvements to the table -+ Exposed the following fields on the table - + Order number - + Customer name (with a link to their WP profile) - + Customer email (mailto link) - + Payment gateway used (this is filterable per gateway as well so gateways can improve the functionality here in the future) -+ Added a link to the product edit page from the product column -+ Free orders will now display as "Free" as opposed to {currency}0.00 -+ Removed the not-so-useful "Order" column which was a long ugly string of data that was displayed in other columns already -+ Removed the "Password Protected" flag since *all* orders are always automatically password protected for added security. This flag distracts from the interface so we've removed it. Orders _are_ still password protected though. -+ Numerous strings that were previously not translatable have been made translatable on this screen -+ A few new strings that previously didn't exist are now available for translation - -**Fixes and other small changes** - -+ Fixed a translation issue on the LifterLMS menu that we thought we fixed in the last release but have now really fixed (probably). -+ Fixed a few small issues with engagements as they related to external engagements triggered by other plugins and LifterLMS extensions. -+ Tired of seeing a banner for a plugin you've already installed? We have your back! The general settings area will now only display banners for plugins that aren't installed. -+ Fixed various javascript issues, mostly removed `console.log()` statements. -+ Fixed a spelling error on the membership admin panel settings screen - - -v2.4.1 - 2016-04-07 -------------------- - -+ Tested and compatible with WordPress 4.5 Release Candidate. -+ Fixed a pagination issue related to updates to the quiz builder from 2.4.0 which would cause results to return incorrect results on the last page of paginated results in the "Add Question" dropdown. -+ Added translation functions to LifterLMS Menu Items. Resolves an issue where translated LifterLMS installations might not see all the menu items under the LifterLMS Icon. -+ Italian translation updates curtosey of [@AndreaBarghigiani](https://github.com/AndreaBarghigiani) -+ On some themes the "Next Lesson" button was displayed while quizzes were being taken. We now *always* hide the next lesson button when a quiz is being taken. -+ Adjusted some static functions to be non static in `class.llms.post-types.php` -+ Added a function to ensure support for post thumbnails on LifterLMS custom post types -+ If a user views a course that is available to them because it belongs to a membership level they are a member of, course pricing information will no longer be visible. This addresses a confusing user experience issue. Previously it _appeared_ like payment for a course was still required even though it really wasn't. -+ Fixed undefined variable warning on quiz summary screen -+ Resolve an issue with quiz timer that caused issues on time display if the time limit was set to a fraction of a minute (eg 1.5 minutes) -+ resolved an undefined variable warning resulting from courses still holding a reference to a membership after the membership has been deleted or trashed - - -v2.4.0 - 2016-03-29 -------------------- - -##### Performance Improvements on the LifterLMS Quiz Builder - -+ Completely rewrote Javascript associated with building a LifterLMS Quiz. Our users have been identifying some performance issues and slowness when working with larger databases. We've refactored the Javascript and our related database queries to allow faster quiz building and fewer timeouts when working in the quiz builder. -+ Fixed a bunch of undefined variables that would produce PHP warnings in various quiz templates -+ Added validation to quiz questions on the admin panel to prevent the same question from being added to a quiz multiple times. -+ Fixed an issue that prevented quizzes from correctly marking the lesson as completed when the quiz was passed. -+ Added three new actions now available for developers to hook into. - + `lifterlms_quiz_completed` called upon completion of a quiz (regardless of grade) - + `lifterlms_quiz_passed` called when a quiz is completed with a passing grade - + `lifterlms_quiz_failed` called when a quiz is completed with a failing grade -+ Course Progress and Course Syllabus shortcodes (and widgets) now work on Quiz pages -+ Completed Metabox refactor for the LifterLMS Quiz post type and removed `LLMS_Meta_Box_Quiz_General` class. All functions now exist in `LLMS_Meta_Box_Quiz` -+ Added validation to the Quiz general settings - + Cannot only enter numbers in attempts, percentage, and time limit fields - + Cannot enter a negative number or a number greater than 100 in the percentage field -+ Removed the membership restriction metabox from quiz admin and question admin screens - -##### Other fixes - -+ Fixed an issue that caused multiple certificates awarded for the same Course or Lesson to not properly display on the My Account page. -+ Removed an event bound to the publishing of a LifterLMS Question that called a function that didn't exist and caused a Javascript error on the console (but didn't actually cause any problems) -+ Removed a warning message that would display on sidebars when a shortcode was being displayed in a place that it couldn't function. We now simply don't display any content if the shortcode can't function. -+ Resolved an issue that prevent users from "purchasing" products when using a 100% coupon and the Stripe payment gateway. Users experiencing this issue should also update to Stripe 3.0.1. -+ Fixed an AJAX related issue that was incompatible with PHP7 -+ Added the ability to have a "max" value on LifterLMS Admin Metabox number fields - - -v2.3.0 - 2016-03-24 -------------------- - -##### Engagements Refactoring (lots of bugfixes, performance improvements, more hook & filter friendly) - -+ We've completely rewritten the LifterLMS Engagement Handler methods (`class LLMS_Engagements`) and added some new engagement actions. -+ The rewrite unifies engagement handling into one function that can be easily hooked into by plugin and theme developers. -+ We've moved any engagment related data out of the main `LifterLMS` class -+ Fixed the broken engagement delay functionality which now runs of `wp_schedule_single_event`. This makes the function more reliable and also keeps it within the traditional WordPress architecture. -+ Added an additional check before sending emails or triggering any engagments that will prevent the achievement from being awarded or the email from being sent if the post is in not published. This fixes an issue that caused emails in the trash from still being emailed. -+ Removed the unused `LLMS_Engagements` class and file -+ Added two new engagment trigger events "Membership Purchased" and "Course Purchased" -+ Deprecated actions -- Removes some redundancy because the triggering actions (`lifterlms_course_completed` triggered the notification action, instead `lifterlms_course_completed` simply triggers the engagement now). - + `lifterlms_lesson_completed_notification` - + `lifterlms_section_completed_notification` - + `lifterlms_course_completed_notification` - + `lifterlms_course_track_completed_notification` - + `lifterlms_course_completed_notification` - + `lifterlms_user_purchased_product_notification` - + `lifterlms_created_person_notification` - -##### Bug and Issue fixes - -+ Adjusted the size of the LifterLMS Admin Menu Icon. It was super big because of, perhaps, some overcompensation. It caused an issue on Gravity Forms admin pages for some reason (we didn't ever determine why) but we've resolved it by using an appropriately sized icon. -+ Fixed a CSS issue that caused some weirdness on the course archive page on mobile devices -+ Fixed an issue with automated membership expirations -+ Fixed a function that should have been called statically in `LLMS_Ajax` class -+ Fixed a ton of issues related to the triggering of engagements and cleaned up a lot of classes and functions associated with them. -+ Properly instatiate `LifterLMS` singleton via LLMS() function and prevent direct instantiation of the class via `new LifterLMS()`. -+ Removed the deprecated 'class.llms.email.person.new.php' file as it was rendered useless a long time ago and caused some duplicate emails. - - -v2.2.3 - 2016-03-15 -------------------- - -##### Translations - -+ Added translation functions around quite a few untranslated strings. Thanks to the team at [Netzstrategen](http://netzstrategen.com) -+ Added German translation .mo and .po files again thanks to the team at [Netzstrategen](http://netzstrategen.com) - -##### Student Enrollment Functions - -We've refactored a bit of our code related to how to programmatically enroll a student in a course or membership during registration and purchase. - -A new class `LLMS_Student` makes working with a LifterLMS student (user) a bit easier. We'll begin exposing user meta data through this class as we continue to improve the usability of the codebase for other developers. - -We've also created a simple enrollment function `llms_enroll_student()` which enables programmatic enrollment to LifterLMS courses or memberships. This was previously handled in a pretty schizophrenic manner and this unifies various ways of enrollment into one clean function. All enrollment moving forward will use this functions. - -The enrollment function calls a new action as well as calling existing enrollment-related actions: - -+ `before_llms_user_enrollment` - called immediately prior to begining the user enrollment function -+ `llms_user_enrolled_in_course` (previously existing) -+ `llms_user_added_to_membership_level` (previously existing) - -This also addresses an issue that prevented the `llms_user_enrolled_in_course` action from being called when a user was auto-enrolled in a course because they joined a membership level that included auto-enrollment in one or more courses. - -##### Bug and Issue fixes - -+ Fixed an inconsistency in the way membership IDs were being saved to the postmeta table that would cause courses to not *appear* restricted on the Membership Enrollment tab, even though they were actually restricted and functioning correctly. -+ New lines are now preserved in the quiz question clarification text areas, thanks to @atimmer -+ Escape HTML in the quiz question description fields on the admin panel to allow outputting html without rendering it, thanks @atimmer -+ Fixed an issue related to the outputting of restricted course and membership content which caused errors on certain themes -+ added a clearfix to the `.llms-lesson-preview` element on the course syllabus template -+ Removed the `class.llms.person.handler.php` file as it wasn't actually being used by anything anywhere and contained no functions -+ Removed some unused and depreacted class functions from the LLMS Student Metabox class -+ Fixed an undefined javascript error resulting from code cleanup in 2.2.2. This issue prevented Vouchers from being published. The code has been further cleaned. - - -v2.2.2 - 2016-03-15 -------------------- - -##### One step closer to a public GitHub repository - -We've made a assive syntatical update to almost every file in the codebase for a (finally) unified and clearly defined coding standard. This puts us one step closer to beginning to open our GitHub repo publicly and accepting pull requests and contributions from developers everywhere. - -Okay, we haven't exactly _clearly_ defined it yet. We're working off a modified version of the [WordPress Coding Standards](https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/). - -Notable exceptions are related to file names because Thomas Levy didn't have the energy to rename a bunch of files as well as ignoring the Yoda Conditions standards. We'll be fixing these deviations in the future. - -##### Quizzes - -+ Created new time calculation and humanizing functions related to the display of quiz time on quiz results pages -+ Quizzes will now display hours, minutes, and seconds depending on the time it took to take the quiz -+ Timing calculations are more accurate and quizzes that are completed in less than 60 seconds will not bug out and display incredibly long lengths -+ Resolved an issue that occassionally prevented quiz data from saving during the last question causing the quiz to hang in an uncompletable state -+ Quiz questions now have a default point value of 1, thanks @atimmer -+ Quiz question answers now accept valid HTML as per `wp_kses_post`, thanks again to @atimmer - -##### Translations - -+ Thanks to @AndreaBarghigiani and the team at [codeat](http://codeat.co/) LifterLMS now ships with Italian language files! - -##### Issue and bug resolutions - -+ Fixed a restriction issue that would happen when individual lessons were restricted to a membership level -+ Fixed an issue with the `[lifterlms_my_account]` shortcode that was preventing the shortcode from working on the Divi theme. -+ Engagements will now only be triggered if they are "Published". Resolves an issue where draft or trashed engagements were still firing. -+ Fixed CSS overflow on LifterLMS Meta boxes. Fixes an issue where select boxes would be hidden inside a metabox. -+ Changed the ConvertKit extension banner image on the LifterLMS general settings page and replaced added a link to the extension now that it's available. -+ Added a link to the new ConvertKit extension to the .org readme -+ When restricting an entire site to a membership level the page selected as the "Terms and Conditions" page in LifterLMS settings will automatically bypass Membership restriction settings. This will allow your unregistered users to actually read the T&C that they're confirming during registration. -+ CSS fix for `has-icon` class on course syllabus -+ Fixed a PHP warning that displayed when purchasing a membership with no auto-enrollment courses -+ Fixed an undefined variable warning in the WooCommerce integration class -+ Fixed a few templating issues related to certificates -+ Added a few new CSS rules that should make certificates more compatible across various themes -+ Added a css class to LifterLMS Next Lesson buttons, `llms-next-lesson` -+ Updated the scheduled event name for cleaning up LifterLMS session data from the WP database. It had a conflicting name with the scheduled event for expiring LifterLMS memberships. - -v2.2.1 - 2016-03-07 -------------------- - -+ Added a few actions to the `class.llms.voucher.php` class. - - -v2.2.0 - 2016-03-04 -------------------- - -##### Translations - -+ We've updated our .pot file for the first time in quite a while. We're really sorry for de-emphasizing translation. An updated .pot file will now accompany each version of LifterLMS whenever a translatable string is adjusted or when a new string is added. -+ We've also made it easier to include custom translations. Read our [Translation Guide](https://lifterlms.readme.io/docs/getting-started-with-translation). - -##### Certificate Background Images - -_We've completely rewritten the certificates template (but it's all backwards compatible)._ - -+ New filters are available to make customizing the certificate template easier for developers. All new filters are documented at [https://lifterlms.readme.io/docs/functions-certificates](https://lifterlms.readme.io/docs/functions-certificates). -+ A new WordPress Image Size is now available and will be used for generating the image used by default when uploading certificates to the media library. Fore more information on these new settings visit [https://lifterlms.com/docs/certificate-background-image-sizes/](https://lifterlms.com/docs/certificate-background-image-sizes/). - -##### Course and Membership Pricing & Sales - -+ Sale price start and end date are now completely optional. - + Provide neither a start date nor an end date to have a sale run indefinetly - + Provide a start date with no end date to have a sale start at a pre-determined time with no pre-determined ending - + Provide an end date with no start date to have a sale end a a pre-determined date but start immediately - + Provide a start date and an end date to have a sale run for a pre-determined period of time -+ Optimized the `LLMS_Product` class to provide more reliable and extenable use of the class -+ The templates related to pricing functions have been refactored. Affected templates include: "templates/course/price.php", "templates/loop/price.php", "templates/membership/price.php" -+ Many people complained about the size of the `.llms-price` element on course and membership tiles on loop pages. We removed the inflated size and will now default to your theme for sizing. You selector remains the same if you wish to customize the size of the price text. - -##### Coupon Updates - -+ Coupons can (finally) be removed after being applied! -+ Coupons can now be restricted to specific courses and/or memberships -+ Percentage based coupons can no longer be created with a value larger than 100% -+ Added numeric restrictions to usage and coupon amount fieds on the admin panel -+ Fixed a programmatic error that prevented product restrictions from being entirely removed -+ Fixed a few instances where hardcoded a US Dollar symbol ($) where a dynamic currency symbol should have been displayed. - -##### Wow Bad Syntax, Very Typo, Such Grammar, So Undefined - -+ Fixed a typo in filter associated with modifying the registration of the lesson post type (`lifterlms_register_post_type_lesson`) -+ Fixed a grammatical error in a Membership restriction message -+ Fixed a syntax error in "/templates/course/outline-list-small.php" that prevented the `done` CSS class from being properly applied to completed lessons -+ Fixed a few typos and grammatical errors on the Course and Membership settings metaboxes -+ Fixed an undefined variable in "templates/course/syllabus.php" -+ Fixed an issue on the system report that prevented the "Courses Page" from being reported properly -+ Fixed an issue that caused PHP warnings on the admin panel for students or WP users with no LifterLMS menu permissions -+ Fixed an installation warning caused by a reference to an undefined class variable -+ Fixed an HTML character encoding issue that caused `–` to display on the admin panel when viewing LifterLMS Orders -+ Fixed an undefined variable found during engagment triggering for non-email engagements. - -##### Additional, less exciting updates - -+ Added input type restrictions to course & membership price fields. -+ The "Emails" LifterLMS Settings Tab has been renamed "Engagements." All Email settings are found under this tab as well as some new settings related to other kinds of LifterLMS engagements. -+ Added `the_content` filter to the content of emails sent by LifterLMS -+ Fixed some CSS issues on Voucher screens -+ Updated Courses settings retrieval function to retrieve the correct "shop" page id -+ Added translation functions to voucher export meta box class -+ Vouchers Export metabox will only allow export after a voucher has been published. This prevent's an issue caused by attempting to export voucher codes before they were saved in the database via the publish / save action. -+ Vouchers can no longer be saved with a use of "0" -+ added a CSS class for various syllabus outputs that notes that the lesson has an icon. Previously CSS relied on "is-complete" to output styles for having an icon but with the addition of placeholders the "is-complete" is used only to note that the lesson is completed and "has-icon" is a more semantic class that applies to both complete and incomplete lessons with an icon. -+ Removed the membership restriction metabox from some post types where it shouldn't have been displaying. -+ admin select fields now have an option `allow_null` (default to "true") which can be set to `false` in order to prevent the output of the default "None" option - - -v2.1.1 - 2016-02-15 -------------------- - -##### System Report - -+ A new LifterLMS Admin Page is available which reports information about various server, WordPress, and LifterLMS settings that will help expedite support requests. -+ More information about the system report is available at [https://lifterlms.com/docs/how-to-use-the-lifterlms-system-report/](https://lifterlms.com/docs/how-to-use-the-lifterlms-system-report/) - -##### Additional Updates - -+ Fixed a javascript issue which prevented users from saving vouchers -+ Cleaned up formatting in a large number of included PHP files - - -v2.0.5 - 2016-02-15 -------------------- - -+ PayPal requests now using HTTP Version 1.1 in preparation for June 2016 [TLS 1.2 and HTTP/1.1 Updates](https://www.paypal-knowledge.com/infocenter/index?page=content&widgetview=true&id=FAQ1914&viewlocale=en_US). This resolves user's inability to begin PayPal checkout when using Sandbox mode. -+ Updated deprecated function opt out to run off a constant that can be defined in `wp-config.php` instead of using a filter that is hard to use in the way that it is intended. - - -v2.0.4 - 2016-02-15 -------------------- - -+ Fixed a typo on the `class_exists` check in the deprecated functions file -+ added a filter so that progressive users can opt out of loading the deprecated functions file - - -v2.0.3 - 2016-02-12 -------------------- - -+ Removed an unsed quiz stub - - -v2.0.2 - 2016-02-11 -------------------- - -+ Bugfix: removed a progressive syntax array that caused fatal errors on older versions of PHP - - -v2.0.1 - 2016-02-11 -------------------- - -##### Updated General Settings Screen - -+ Improved the general settings interface to be more visually appealing and to provide some ad space to alert customers to other LifterLMS products and information. -+ Moved Currency options to the Checkout settings screen - -##### Bug Fixes - -+ Properly initialized jQuery on the vouchers metabox admin scripts -+ removed some php shortcut echos (`<?= $var; ?>`) -+ Resolve issue where courses that are available with a membership or on it's own outside of the membership would prevent users from accessing content if they were not a member. -+ Fixed a few files where undefined variables were being referenced and generating php notices -+ removed an call to a WordPress core function that has never existed. Not sure what we were thinking there... - -###### Enhancements - -+ Updated CSS to provide better course syllabus layout on smaller screens -+ Added validation to prevent against duplicate voucher code creation - -v2.0.0 - 2016-02-04 -------------------- - -##### Auto-advancing lessons - -+ We've heard your feedback and added a new global course option which will auto-advance a student to the next lesson upon lesson completion. - -##### Bug Fixes - -+ Added spaces between numbers and "of" on the counter for course syllabus templates -+ Removed a template hook that was creating duplicate lesson thumbnails on quite a few themes - -##### Membership Admin Improvements - -Visit the "Enrollment" tab on any membership to see some new additions to make managing your memberships easier. - -+ You can now add courses to and remove courses from a Membership from the Membership itself -+ You can now opt to automatically enroll students in a course (or multiple courses) when they sign up for a membership by checking "Auto Enroll" next to the course on the Membership enrollment tab - -##### Student Enrollment & Removal on Courses Admin Screen - -We've updated the Students tab interface for performance and usability! - -+ AJAX enabled searching by student name and or email -+ Increased performance for course page load by only calling student information when needed. This resolves a bug identified by users with large user databases and/or low-powered servers. -+ Allow for addition or removal of several students at a time. - -##### Syllabus Template - -+ Added a Course setting to optionally enable Lesson Thumbnails on the Course Syllabus -+ Added a Course setting Display greyed out lesson completion checkmark icons on lessons not competed in the course syllabus -+ Rewored CSS on the course syllabus to rely on floats rather than absolute positioning, should allow for more robust custimization with less frustration -+ Refactored the syllabus template at "templates/course/syllabus.php" for better performance and readability - -##### Updates and enhancements - -+ User email is now displayed on the "Students" table on student analytics screens -+ Membership now has it's own admin menu -+ Reordered the LifterLMS admin menu and submenu items -+ Removed membership specific taxonomies from courses -+ Removed course specific taxonomies from memberships -+ Coupon code is now a required field when creating a coupon -+ "Humbled" the metabox on all post types that restricts the post to a membership. The metabox would previously gain priority over the WordPress publishing actions metabox. The priority has been reduced to "default" and will to fall into line with all other metaboxes on the screen and appear based on registration priority. If you can't find the metabox, SCROLL DOWN! If you want to put it back up on the top, you can simply drag it up there and WordPress will save your preference. - -##### Deprecated Classes - -We've added a "deprecated" file which holds a few stubs for classes and functions deprecated below as to prevent fatal errors. The functions and classes in the deprecated class are classes which we know are being utilized by approved LifterLMS extensions and will allow users to upgrade LifterLMS without upgrade extensions without breaking their websites! - -+ `LLMS_Activate` which as previously used to activate the plugin for updates via the LifterLMS Update Server and is no longer required. -+ PUC (plugin update checker) Library has been completely removed as it is no longer required for plugin updates. -+ `LLMS_Analytics_Dashboard` was removed as it was a stub that was never used and shouldn't have ever been released as a part of the LifterLMS codebase. I can't believe no one reported this bug! - -##### Deprecated Functions - -+ `lifterlms_template_section_syllabus()` - -**The following are officiallby deprecated and removed to prevent WooCommerce compatibility conflicts** - -+ `is_shop()` replaced by `is_llms_shop()` -+ `is_account_page()` replaced by `is_llms_account_page()` -+ `is_checkout()` replaced by `is_llms_checkot()` - - -##### Deprecated Templates - -+ templates/course/section_syllabus.php - -##### New Account Dashboard Filters - -*[View documentation for more information](https://lifterlms.readme.io/docs/filters-account)* - -+ `lifterlms_account_greeting` -+ `lifterlms_my_courses_title` -+ `lifterlms_my_courses_enrollment_status_html` -+ `lifterlms_my_courses_start_date_html` -+ `lifterlms_my_courses_course_button_text` -+ `lifterlms_my_certificates_title` - -##### New Checkout Page Filters: - -*[View documentation for more information](https://lifterlms.readme.io/docs/filters-checkout)* - -+ `lifterlms_checkout_user_logged_in_output` -+ `lifterlms_checkout_user_not_logged_in_output` - -##### New Course Filters: - -*[View documentation for more information](https://lifterlms.readme.io/docs/filters-course)* - -+ `lifterlms_product_purchase_account_redirect` -+ `lifterlms_product_purchase_redirect_membership_required` -+ `lifterlms_product_purchase_checkout_redirect` -+ `lifterlms_product_purchase_membership_redirect` -+ `lifterlms_lesson_complete_icon` - - - - - - -v1.5.0 - 2016-01-22 -------------------- - -##### WooCommerce Integration Enhancements - -__NOTE: The following enhancements only apply when the WooCommerce Integration is enabled__ - -**Always redirect to the WooCommerce Cart when a SKU Matched Product can be found** - -+ LifterLMS Products (courses and memberships) which are SKU matched to a WooCommerce product will now automatically add the related WooCommerce product to the WooCommerce shopping cart and then automatically redirect the visitor to the WooCommerce cart when the visitor attempts to enroll in a course or membership from the LifterLMS course or membership page. -+ If no WooCommerce product is found via a SKU match, the user will proceed to the LifterLMS checkout. -+ This will enable you to determine which Cart you want a user to use on a product by product basis. You may sell certain courses via WooCommerce and others via LifterLMS (should you choose to do so). - -**Multiple Item Checkout** - -+ When a WooCommerce order is complete user's will now be automatically enrolled in **all** courses and/or memberships in the WooCommerce order. This improves upon a previously limitation that would only allow WooCommerce checkout with one LifterLMS product at a time. -+ The products in the order will be intelligently SKU matched to LifterLMS Courses or Memberships. -+ You may also mix and match between WooCommerce products matched to LifterLMS products and those which are not matched to LifterLMS products. For example, your customers may now buy a Course via SKU matching as well as a T-Shirt that is not matched to a LifterLMS course via a SKU. - -##### Other Fixes and improvements - -+ Fixed a bug that caused quiz results to display for users who had never taken the quiz. -+ Added Wistia as an oEmbed provider to fix an issue related to default oembed handling in WordPress 4.4. -+ added a `.cc_cvv` class that mimics the existing `#cc_cvv` styles to allow gateway extensions to change the ID of the field in their credit card forms -+ Added support for new 1.4.5 capability fixes to be also be reflected under the "+New" menu item in the WP Admin Bar. There are no changes to the filters, the capability filters will simply also remove restricted post types from the admin bar now (as they should). -+ Tested and compatible up to WordPress 4.4.1 - -##### Deprecations - -**The following functions have been staged for deprecation in LifterLMS 2.0!** - -+ Setup the `is_account_page()` function to be replaced by `is_llms_account_page()` function. The original causes conflicts when WooCommerce is installed as WooCommerce includes a core function by the same name. All references to `is_account_page()` in LifterLMS have been removed and the original has been left to prevent issues with developers currently relying on the LifterLMS version of thefunction. -+ Setup the `is_checkout()` function to be replaced by `is_llms_checkout()` function. The original causes conflicts when WooCommerce is installed as WooCommerce includes a core function by the same name. All references to `is_checkout()` in LifterLMS have been removed and the original has been left to prevent issues with developers currently relying on the LifterLMS version of thefunction. - -v1.4.5 - 2016-01-13 -------------------- - -+ Significant improvements to LifterLMS admin permissions as well as a hardening of permissions. Previously LifterLMS admin screens and menus were available to any users with `edit_posts` capabilities. This has been changed to `manage_options`. Filters for all screens and menus have been added with this release. If you're site currently relies on users with `edit_posts` to be able to access LifterLMS settings and analytics screens you must utilize these new filters in order to maintain their access. Please see full documentation on the new filters at [https://lifterlms.readme.io/docs/filters-admin-menu-and-screen-permissions](https://lifterlms.readme.io/docs/filters-admin-menu-and-screen-permissions). **Please consider testing your changes outside of production before updating to LifterLMS 1.4.5 in production.** -+ Allow "Payment Method" to be translated on the "Confirm Payment" screen -+ Allow the name of the payment gateway to be filtered on the "Confirm Payment" screen -+ Added pagination support to lifterlms membership archive pages -+ Fixed a bug related to some required global variables for quizzes and lessons being incorrectly set on certain hosts -+ updated readme file to remove incomplete documentation -+ Added Chosen multi-select options to admin panel metaboxes (settings and posts) -+ Added two new actions that developers can hook into: - + `llms_user_enrolled_in_course`, called when users are enrolled in a course. Usage details available [here](https://lifterlms.readme.io/docs/actions-user#llms_user_enrolled_in_course). - + `llms_user_added_to_membership_level`, called when users are added to a membership level. Usage details available [here](https://lifterlms.readme.io/docs/actions-user#llms_user_added_to_membership_level). - -v1.4.4 - 2015-12-21 -------------------- - -##### Updates - -+ My account page can now (optionally) display a list of memberships a student is currently enrolled in -+ Student analytics on the admin panel display student's Memberships -+ Student analytics on the admin panel will now display student's progress through courses in addition to their current enrollment status. -+ Custom taxonomy archive templates for Course tags, categories, tracks, and difficulties now exist and properly function. -+ Custom taxonomy archive templates for Membership categories and tags now exist and properly function. -+ Added the `[lifterlms_memberships]` shortcode which was documented but never implemented. Details on usage available at [https://lifterlms.readme.io/docs/short-codes#memberships-lifterlms_memberships](https://lifterlms.readme.io/docs/short-codes#memberships-lifterlms_memberships) -+ Added basic styles to LifterLMS pagination HTML elements (elements with class `.llms-pagination`) which formerly had no associated CSS. - -##### Deprecations - -+ Setup the `is_shop()` function to be replaced by `is_llms_shop()` function. The original causes conflicts when WooCommerce is installed as WooCommerce includes a core function by the same name. All references to `is_shop()` in LifterLMS have been removed and the original has been left to prevent issues with developers currently relying on the LifterLMS version of thefunction. It *will* be removed in the next major update (2.0) and will be noted as an officially deprecated feature at that time. - -##### Bug fixes - -+ Fixed pagination issues when using the `[lifterlms_courses]` shortcode -+ Fixed an issue with the `is_shop()` function that prevented courses per page option from functioning properly on the default course archive page -+ Student analytics profile on admin panel will display the correct number of memberships the student is enrolled in. -+ Fixed a small CSS issue that caused extra white space to be displayed above Course or Membership tiles on archive pages when using the WordPress Twentyfifteen default theme - -##### Miscellaneus - -+ Account settings screen displays the correct title ("Account Settings" it previously said "Archive Settings") -+ Made language changes to the LifterLMS settings intro screen copy -+ Added link to CourseClinic on settings intro screen -+ Added link to LifterLMS documentation on the settings intro screen - -v1.4.3 - 2015-12-11 -------------------- - -+ Fixed an issue that could prevent some older servers from being able to run LifterLMS - -v1.4.2 - 2015-12-10 -------------------- - -+ Tested and compatible with WordPress version 4.4 -+ BugFixes: fixed issue in `llms_featured_img()` that was preventing the `$size` variable from being passed to the WP core function being utilized. -+ BugFixes: correctly handling conflicts with Plugin Update library - -v1.4.1 - 2015-12-02 -------------------- -+ Feature: Custom single price text - Display custom text for the single price on the courses and course page. Custom field does not require a single payment price be set. IE: Free! -+ Feature: Custom Purchase Course Button Text Option. Change the text of the Take This Course button in Settings->Courses. -+ Feature: New Become A Member button on courses that are restricted to memberships. -+ Feature: Custom Become A Member Text Option. Change the text of the become a member button in Settings->Courses. -+ Feature: Paypal Debug Mode. Enable debug mode in Settings->Gateways to view responses from Paypal API when errors occur. -+ Updates: Updated support links in Settings->General. -+ Updates: added minor styling to course page to increase margin and padding for some themes. -+ Updates: Achievement content now available to pull into custom templates. The Achievement content is not by default displayed but can now be used in custom templates. -+ BugFixes: Resolved issue with no default price selected at checkout when only recurring option existed. -+ BugFixes: Lesson prerequisite now alert the user and provide a link to redirect the user to the next required lesson in the course. -+ BugFixes: Paypal errors now return error message instead of white screen when Paypal API fails. -+ BugFixes: Corrected JavaScript error with modals on course edit page in Internet Explorer 11. - -v1.4.0 - 2015-10-29 -------------------- -+ Feature: Free lessons - demo lessons that can be taken at any time by any user -+ Feature: Guest lessons - demo lessons that can be taken by a non-logged in user -+ Feature: Random quiz question - quiz questions can now be set to be in user set order or random order -+ Updates: Automatically registers appropriate sidebars for Genesis theme -+ Updates: Backend file cleanup -+ Updates: Text cleanup -+ Updates: Adds greater localization support (more strings to translate! yay!) -+ Updates: Cleans up some unneccessary console.log() calls -+ Updates: Removes mass of commented out code (cleaner reading) -+ Updates: 'Next Lesson' button added after successful completion of quiz -+ Updates: 'Next Lesson' button at bottom of lesson properly gets starting lesson of next section at the end of the previous section -+ Updates: 'Previous Lesson' button at bottom of lesson will now properly get last lesson of previous section (if applicable) -+ Updates: Move Registration Form to global templates to allow users to disable registration on login page but use registration form on custom page. -+ BugFixes: WordPress pages are now properly restricted by memberships -+ BugFixes: Fixes bug that caused order screen to act up if user was deleted -+ BugFixes: Resolves nastly little bug that caused syllabus numbers to be out of whack -+ BugFixes: Resolved error with WooCommerce integration where courses would not always register the user -+ BugFixes: Corrected CSS conflict with Bridge theme settings page - -v1.3.10 - 2015-10-15 --------------------- -+ Updates: Clarifies some prerequisite text -+ Updates: Quiz questions are now randomized! -+ Updates: Fixes small CSS issue -+ BugFixes: Resolves fatal errors with a small subset of premium themes - -v1.3.9 - 2015-10-5 ------------------- -+ BugFixes: Removes conflict with Yoast SEO -+ BugFixes: Fixes CSS issues with box-sizing takeover -+ Feature: New Settings Tile: Session Management. Found at LifterLMS->Settings->General. -+ Feature: Clear User Session Tool. You can now clear all LifterLMS user session data from your site in LifterLMS->Settings->General -+ Updates: Backend code cleanup - -v1.3.8 - 2015-10-02 -------------------- -+ BugFixes: Fixes Random error notices -+ Updates: Updates email template handler - -v1.3.7 - 2015-09-25 -------------------- -+ Updates: Adds Spanish translation -+ Updates: Adds new filter 'lifterlms_single_payment_text' to customize single payment string on checkout -+ Updates: Student analytics now indicate which courses a student has completed -+ BugFixes: Resolved security issue with WordPress searches and lessons -+ BugFixes: Fixes analytics bug that potentially arises after a course is deleted - -v1.3.6 - 2015-09-18 -------------------- -+ BugFixes: Fixes pesky Zend Error that plagued some unfortunate victims -+ BugFixes: Students can now be properly deleted from the course -+ BugFixes: Fixes random class redeclaration error messages -+ Updates: Adds new filter 'lifterlms_quiz_passed' to customize 'Passed' text after quiz -+ Updates: Adds new filter 'lifterlms_quiz_failed' to customize 'Failed' text after quiz - -v1.3.5 - 2015-09-11 -------------------- -+ Revisions: Fixes typos -+ Updates: Adds sidebar functionality to various themes - -v1.3.4 - 2015-09-04 -------------------- -+ BugFixes: Fixes bug with featured image on course page -+ BugFixes: Fixes issue with lesson completed percentage on analytics page - -v1.3.3 - 2015-09-01 -------------------- -+ Updates: Removes depricated plugin updater -+ Updates: Adds Course Track prerequisite -+ Updates: Various text fixes -+ BugFixes: Fixes lesson name on prerequisite notification -+ BugFixes: Fixes critical error with WordPress customizer - -v1.3.2 - 2015-08-30 -------------------- -+ Hotfix: resolves issues with sidebar shortcodes -+ Updates: Text clarifications - -v1.3.1 - 2015-08-28 -------------------- -+ Hotfix: resolves issue with ajax url - -v1.3.0 - 2015-08-28 -------------------- -+ Improved popopver behavior in course creation. -+ BugFixnig. Prevent multiple lesson and section form submition -+ Fixed typos at backend quiz page -+ Fixed check for update bug when plugin isn't properly activated. -+ BugFixing, quiz post type should show author metabox -+ Added course category filter to lifter_lms shortcode -+ BugFixing, typo in [lifterlms_course_progess shortcode] -+ BugFixing, Analytics shouldn't fetch students meta info from users were deleted. -+ Adds in basic review functionality -+ Updates plugin-updater to remedy PHP conflicts -+ Fixes date bug in Analytics -+ Cleans up jQuery console messages -+ Adds in course tracks - -v1.2.8 - 2015-07-17 -------------------- -+ Updated Portuguese translation file -+ Fixed issue where quiz score could not be equal to required grade. -+ New Feature: Quiz Results Summary. Display the quiz results to the user on quiz completion. -+ New feature: Clarification. Display information about correct and incorrect answers to users -+ New Feature: Display correct answers to user on quiz completion -+ Removed ability to add negative time limit to quiz -+ New Membership feature: Make membership archive links go directly to checkout. Setting allows you to skip membership sales page and send users directly to registration and checkout. -+ Sidebar support for prototype theme -+ Sidebar support for X theme -+ Sidebar support for WooCanvas -+ New Shortcode: [lifterlms_hide_content]: Use to restrict content on a page, course or lesson to a specific membership. Pass the post id of the membership you want to restrict the content to. Example: [lifterlms_hide_content membership="5"] -+ New updates to gulp build process -+ Class autoloading and LLMS namespace introduced for more efficient coding. - -v1.2.7 - 2015-06-05 -------------------- -+ Minor bug fix with lesson redirect to quiz -+ Minor change to global Course object instantiation. -+ Bug Fix: Remove student from course -+ Bug Fix: Appearance Menus missing select field (THANKS ANDREA!) -+ New Course Setting: Hide Course Outline on course page -+ New Shortcode: [lifterlms_course_outline] - displays course outline with settings (see documentation) -+ Membership metabox design update -+ Certificate metabox design update -+ Achievement metabox design update -+ Lesson metabox design update -+ Emails metabox design update -+ Coupons metabox design update -+ Update to certificate design (better alignment and theme functionality) -+ Better theme sidebar support -+ More awesome control for devlopers building new settings for LifterLMS -+ Advanced filter system for metabox fields with finite control for 3rd party developers. -+ Woocommerce confict correction to archive templates -+ Style updates to allow themes better control on design - -v1.2.6 - 2015-04-28 -------------------- -+ Corrected issue with lesson re-order on save -+ corrected html formatting issue on purchase page -+ corrected html formatting issue on course page - -v1.2.5 - 2015-04-23 -------------------- -+ Corrected excerpt to not pull in lesson navigation -+ Modified metabox api for better extension integration -+ Corrected issue with order not displaying all information if coupon was not applied to order - -v1.2.4 - 2015-04-22 -------------------- -+ Moved All Course metaboxes to global Course Options Metabox -+ Move Enrolled and Non-Enrolled user wysiwyg post editors to Options Metabox -+ Removed Course Syllabus metabox, Added Course Outline Metabox -+ Set priority of Course Outline and Course Options Metabox to top -+ Added ability to Create new section to Course Outline -+ Added abiliyt to Create new lesson to Course Outline -+ Added ability to add existing Lesson to Course Outline -+ Added Lesson duplicate functionality when adding lesson previously assigned to another course. -+ Added ability to drag lessons between sections in Course Outline -+ Added ability to edit Section Title in Course Outline -+ Added ability to edit lesson title and excerpt in Course Outline -+ Added New Style and Design for better usability to Course Outline -+ Added Lesson Icon with tooltip to Course Outline: Prerequisite - shows if prerequisite exists and displays name of prerequisite -+ Added Lesson Icon with tooltip to Course Outline: Quiz - shows if quiz is assigned to course and displays name of quiz -+ Added Lesson Icon with tooltip to Course Outline: Drip Content - shows if drip days are set and # of days -+ Added Lesson Icon with tooltip to Course Outline: Content - displays if lesson has content added. -+ Added Course Outline Metabox to Lesson Post Editor: Allows you to assign lesson to section and view entire course tree. Links to Course and all other lessons in course. -+ Style Update: backgrounds on frontend. Removed all references to white background on front end elements -+ Corrected Restriction for course in past. Updated course in past message to display as Course ended instead of Course not available until. -+ Added restriction message when user attempts to visit a restricted lesson. -+ Updated course syllabus sidebar widget to not display lessons as links if user is not enrolled in course. -+ Added ability to use Attribute Order for sorting Courses and Memberships on Archive pages. -+ Added support for selling memberships with Woocommerce. LifterLMS now checks memberships for SKU matches in addition to Courses when products are purchased using WooCommerce. -+ Added gulp for scss, js and svg management -+ Added svg sprite and svg class for managing svg elements on front and backend. -+ Added better language translation support for strings -+ Refactored Ajax Classes for cleaner, faster development -+ Refactored metabox build class for cleaner, faster development -+ Refactored Course syllabus to reduce query size for larger, complex courses -+ Added Handler classes for Lessons, Sections, Courses and Posts -+ Refactored Course get / set methods to reduce database queries - -v1.2.3 - 2015-03-12 -------------------- -+ Achievement design and functionality updates -+ Achievemnt shortcode added -+ Better searching added to engagement screen -+ Achievement bug fixes -+ On screen error reporting added to activation for trouble shooting -+ Custom engagement methods added to certificate, achievement and sections -+ Corrected new user registration engagement bug -+ LifterLMS access reduced from manage_options to edit_posts -+ Filters added to analytics to allow custom developement -+ Engagment bug fix: Section and Lesson bug select -+ Syllabus bug corrected: No longer displays lessons in section box if no sections exist. -+ Removed depreciated achievement template -+ Membership Bug fix: Membership restriction will now only display on single posts. - - -v1.2.2 - 2015-02-23 -------------------- -+ Corrected drip content bug -+ Added Ajax functionality to quiz -+ rounded quiz grades -+ Added quiz time limit setting to Quiz -+ Added quiz timer to quiz, front end -+ Quiz allowed attempts field now allows unlimited attempts -+ Set Ajax lesson delete method to not return empty lesson value -+ Set next and previous questions to display below quiz question -+ Decoupled Single option select question type from quiz to allow for more question types -+ Added Quiz time limit to display on Quiz page -+ Added functionality to automatically complete quiz when quiz timer reaches 0 -+ Moved Quiz functionality methods from front end forms class to Quiz class - -v1.2.1 - 2015-02-19 -------------------- -+ Updated settings page theming -+ Added Set up Quick Start Guide -+ Added Plugin Deactivation Option -+ Updated language POT file -+ Added Portuguese language support. Thank you Fernando Cassino for the translation :) - - -v1.2.0 - 2015-02-17 -------------------- -+ Admin Course Analytics Dashboard Page. View at LifterLMS->Analytics->Course -+ Admin Sales Analytics Dashboard Page. View at LifterLMS->Analytics->Sales -+ Admin Memberships Analytics Dashboard Page. View at LifterLMS->Analytics->Memberships -+ Admin Students Search Page. View at LifterLMS->Students -+ Admin Student Profile Page ( View user information related to courses and memberships ) -+ Lesson and Course Sidebar Widgets ( Syllabus, Course Progress ) -+ Course Syllabus: Lesson blocks greyed out. Clicking lesson displays message to take course. -+ Misc. Front end bug fixes -+ Misc. Admin bug fixes -+ Course and Lesson prerequisites: Can no longer select a prerequisite without marking "Has Prerequisite" -+ Admin CSS updates -+ Better Session Management -+ Number and Date formatting handled by seperate classes to provide consistant date formats across system -+ Zero dollar coupon management: Coupons that set total to 0 will bypass payment gateway, generate order and enroll users. -+ Better coupon verification. -+ Better third party payment gateway support. Third party gateway plugins are now easier to develop and integrate. -+ User Registration: Phone Number Registration field option now available in Accounts settings page. - -v1.1.2 - 2014-12-18 -------------------- -+ Moved Sidebar registration from plugin install to init - -v1.1.1 - 2014-12-16 -------------------- -+ Added user registration settings to require users to agree to Terms and Conditions on user registration -+ Added comments to all classes methods and functions -+ Removed unused and depreciated methods -+ Added Lesson and Course Sidebar Widget Areas -+ Fixed bug with course capacity option -+ Fixed bug with endpoint rewrite -+ Added localization POT file and us_EN.po translation file - -v1.1.0 - 2014-12-08 -------------------- -+ Updated HTML / CSS on Registration form -+ Added Coupon Creation -+ Added Coupon support for checkout processing -+ Added Credit Card Support processing support -+ Added Form filters for external integration -+ Added Form templates for external integration -+ Added Account Setting: Require First and Last Name on registration -+ Added Account Setting: Require Billing Address on registration -+ Added Account Setting: Require users to validate email address (double entry) -+ Added password validation (double entry) on user registration / account creation -+ Added Quiz Question post type and associated metaboxes -+ Added Quiz post type and associated metaboxes -+ Added ability to assign a quiz to a lesson -+ Added front end quiz functionality -+ Added Course capacity (limit # of students) - -### User Admin Table -+ Added Membership Custom Column that displays user's membership information -+ Added "Last Login" custom column that displays user's last login date/time - -### User Roles -+ Updated user role from "person" to "student" -+ Added temporary migration function to transition any register users with "person" role to "student" role -+ Added "Student" role install function - - -### BUDDYPRESS -+ BuddyPress Screen Permission Fix -+ Added two additional screens to BuddyPress: Certificates and Achievements - -### MISC -+ Added llms options for course archive pagination and added course archive page pagination template -+ Added user statisticc shortcode - - -v1.0.5 - 2014-11-12 -------------------- - -+ Fixed a mis-placed parenthesis in templates/course/lesson-navigation.php related to outputting excerpt in navigation option -+ Changed theme override template directory from /llms to /lifterlms -+ Update the positiong & name of the "My Courses" Menu in BuddyPress Compatibility file -+ New meta_key _parent_section added for easier connection and quicker queries. -+ Section sorting on course syllabus -+ Edit links added to course syllabus -+ Assign section to course and view associated lessons metabox added to sections -+ Assign lesson to section and view associated lessons metabox added to lessons -+ Assigned Course, Assigned Section, Prerequisite and Membership Required added to lesson edit grid -+ Assigned Course added to section edit grid' -+ New membership setting: Restrict Entire Site by Membership Level (allows site restriction to everything but membership purchase and account). -+ Updated template overriding to check child & parent themes -+ Updated template overriding to apply filters to directories to check for overrides to allow themes and plugins to add their own directories - -v1.0.4 - 2014-11-04 -------------------- - -+ Templating bug fix -+ Added shortcode and autop support to course and lesson content / excerpt - - -v1.0.3 - 2014-11-04 -------------------- - -+ Major Templating Update! -+ Removed Course, Lesson and Membership single lesson templates. -+ Course and Section content templates now filter through WP content - - -v1.0.2 - 2014-10-31 -------------------- - -+ Added lesson short description to previous lesson preview links -- it was rendering on "Next" but not "Previous" -+ Added a class to course shop links wrapper to signify the course has been completed -+ Removed an uncessary CSS rule related to the progress bar - - -v1.0.2 - 2014-10-30 -------------------- - -+ Fixed SSL certificate issues when retreiving data from https://lifterlms.com -+ Added rocket settings icon back into repo - - -v1.0.1 - 2014-10-30 -------------------- - -+ Updated activation endpoint url to point towards live server rather than dev diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 9cecc1d466..0000000000 --- a/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - {one line to give the program's name and a brief idea of what it does.} - Copyright (C) {year} {name of author} - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - {project} Copyright (C) {year} {fullname} - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -<http://www.gnu.org/licenses/>. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -<http://www.gnu.org/philosophy/why-not-lgpl.html>. diff --git a/README.md b/README.md deleted file mode 100644 index 4d76559dea..0000000000 --- a/README.md +++ /dev/null @@ -1,92 +0,0 @@ -[![LifterLMS](https://3xwbw71rswfz42rmgp5qgl85-wpengine.netdna-ssl.com/wp-content/uploads/2015/03/logo.png "LifterLMS")](https://lifterlms.com) - -[![WordPress plugin](https://img.shields.io/wordpress/plugin/v/lifterlms.svg)]() -[![WordPress](https://img.shields.io/wordpress/v/lifterlms.svg)]() -[![WordPress rating](https://img.shields.io/wordpress/plugin/r/lifterlms.svg)]() -[![WordPress](https://img.shields.io/wordpress/plugin/dt/lifterlms.svg)]() -[![Build Status](https://travis-ci.org/gocodebox/lifterlms.svg?branch=master)](https://travis-ci.org/gocodebox/lifterlms) -[![Code Climate](https://codeclimate.com/github/gocodebox/lifterlms/badges/gpa.svg)](https://codeclimate.com/github/gocodebox/lifterlms) -[![Test Coverage](https://codeclimate.com/github/gocodebox/lifterlms/badges/coverage.svg)](https://codeclimate.com/github/gocodebox/lifterlms/coverage) - -[LifterLMS](https://lifterlms.com), the #1 WordPress LMS solution, makes it easy to create, sell, and protect engaging online courses. - - -### [Changelog](./CHANGELOG.md) - - -### Documentation -+ [https://lifterlms.com/docs/](https://lifterlms.com/docs/) - - -### Getting Help and Support Support - -GitHub is for bug reports and contributions only! If you have a support question or a request for a customization this is not the right place to post it. Please refer to [LifterLMS Support](https://lifterlms.com/my-account/my-tickets) or the [community forums](https://wordpress.org/support/plugin/lifterlms). If you're looking for help customizing LifterLMS, please consider hiring a [LifterLMS Expert](https://lifterlms.com/docs/do-you-have-any-recommended-developers-who-can-modifycustomize-lifterlms/). - - -### Reporting a Bug - -Bugs can be reported at [https://github.com/gocodebox/lifterlms/issues/new](https://github.com/gocodebox/lifterlms/issues/new). - -Before reporting a bug, [search existing issues](https://github.com/gocodebox/lifterlms/issues) and ensure you're not creating a duplicate. If the issue already exists you can add your information to the existing report. - -Also check our [known issues and conflicts](https://lifterlms.com/doc-category/lifterlms/known-conflicts/) for possible resolutions. - -### Contributing [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](.github/CONTRIBUTING.md) - -Interested in contributing to LifterLMS? We'd love to have your contributions. Read our contributor's guidelines [here](.github/CONTRIBUTING.md). - -### Installing for Production Usage - -If you clone or download this repo directly it will not run as a plugin inside WordPress! Installable production releases are available in on the [Releases tab](https://github.com/gocodebox/lifterlms/releases). You can get the latest stable release from [WordPress.org](https://downloads.wordpress.org/plugin/lifterlms.zip) - -### Installing for Development - -1. Composer - + `curl -sS https://getcomposer.org/installer | php` - + `php composer.phar install` - -2. Node - + Install node - + Install npm - + `npm install --global gulp` - + `npm install` - - -### Coding Standards - -For standards we're working off a modified version of the [WordPress Coding Standards](https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/). - -We're utilizing (a currently slightly modified version of) the [WordPress Coding Standards Core Ruleset](https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards) for PHPCS (php codesniffing). - -Our javascript and SCSS are a mess. We're tackling that next. - - -### Running phpcs - -Use the shorthand composer script to run phpcs against all PHP files. - -+ `composer run-script phpcs` - -Alternatively access the executable: - -+ `./vendor/bin/phpcs path/to/file.php` - -To see errors only (no warnings): - -+ `./vendor/bin/phpcs -n path/to/file.php` - -To see all options: - -+ `./vendor/bin/phpcs -h` - - -### Running phpcbf - -+ `./vendor/bin/phpcbf` to run on all php files -+ `./vendor/bin/phpcbf path/to/file.php` to run on a specific file - -### Sponsors - -[BrowserStack](https://www.browserstack.com/) helps us ensure LifterLMS looks great and works on every imaginable browser and device. - -[![BrowserStack](https://raw.githubusercontent.com/gocodebox/lifterlms/master/.github/sponsors/browserstack-logo.png "BrowserStack")](https://www.browserstack.com/) diff --git a/_private/svg/llms-icon-calendar.svg b/_private/svg/llms-icon-calendar.svg deleted file mode 100644 index 4e02ca4d61..0000000000 --- a/_private/svg/llms-icon-calendar.svg +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="101.802px" height="100px" viewBox="0 0 101.802 100" enable-background="new 0 0 101.802 100" xml:space="preserve"> -<g> - <g id="_x31_5_38_"> - <g> - <path d="M24.876,23.083h1.457c2.214,0,4.008-1.777,4.008-3.968V8.163V4.067c0-2.192-1.794-3.968-4.008-3.968h-1.457 - c-2.213,0-4.007,1.776-4.007,3.968v4.096v10.952C20.869,21.306,22.663,23.083,24.876,23.083z"/> - <path d="M76.28,22.985h1.457c2.212,0,4.006-1.777,4.006-3.969V7.124V3.968c0-2.19-1.794-3.968-4.006-3.968H76.28 - c-2.214,0-4.01,1.777-4.01,3.968v3.156v11.893C72.272,21.208,74.066,22.985,76.28,22.985z"/> - <path d="M95.287,7.972H85v12.044c0,4.019-3.26,6.235-7.264,6.235h-1.455c-4.007,0-7.268-3.269-7.268-7.287V7.972H33.599v11.091 - c0,4.019-3.259,7.287-7.266,7.287h-1.456c-4.005,0-7.265-3.269-7.265-7.287V7.972H6.515C2.922,7.972,0,10.903,0,14.506v78.959 - C0,97.069,2.922,100,6.515,100h88.771c3.592,0,6.516-2.931,6.516-6.535V14.506C101.802,10.903,98.878,7.972,95.287,7.972z - M95.287,93.465H6.516l0-59.628h88.773l0.002,59.628C95.291,93.465,95.289,93.465,95.287,93.465z"/> - <path d="M54.264,53.84h11.698c0.462,0,0.839-0.38,0.839-0.843v-10.16c0-0.465-0.377-0.842-0.839-0.842H54.264 - c-0.464,0-0.839,0.376-0.839,0.842v10.16C53.425,53.46,53.8,53.84,54.264,53.84z"/> - <path d="M73.355,53.84h11.698c0.463,0,0.839-0.38,0.839-0.843v-10.16c0-0.465-0.376-0.842-0.839-0.842H73.355 - c-0.464,0-0.839,0.376-0.839,0.842v10.16C72.516,53.46,72.891,53.84,73.355,53.84z"/> - <path d="M16.082,70.472H27.78c0.463,0,0.839-0.377,0.839-0.842V59.47c0-0.467-0.376-0.843-0.839-0.843H16.082 - c-0.463,0-0.839,0.376-0.839,0.843v10.16C15.242,70.095,15.619,70.472,16.082,70.472z"/> - <path d="M35.173,70.472h11.697c0.464,0,0.839-0.377,0.839-0.842V59.47c0-0.467-0.375-0.843-0.839-0.843H35.173 - c-0.464,0-0.84,0.376-0.84,0.843v10.16C34.333,70.095,34.709,70.472,35.173,70.472z"/> - <path fill="#777676" d="M54.264,70.472h11.698c0.462,0,0.839-0.377,0.839-0.842V59.47c0-0.467-0.377-0.843-0.839-0.843H54.264 - c-0.462,0-0.839,0.376-0.839,0.843v10.16C53.425,70.095,53.802,70.472,54.264,70.472z"/> - <path d="M73.355,70.472h11.698c0.463,0,0.839-0.377,0.839-0.842V59.47c0-0.467-0.376-0.843-0.839-0.843H73.355 - c-0.464,0-0.839,0.376-0.839,0.843v10.16C72.516,70.095,72.891,70.472,73.355,70.472z"/> - <path d="M27.78,75.26H16.082c-0.463,0-0.839,0.376-0.839,0.843v10.16c0,0.465,0.376,0.841,0.839,0.841H27.78 - c0.463,0,0.839-0.376,0.839-0.841v-10.16C28.62,75.636,28.244,75.26,27.78,75.26z"/> - <path d="M46.871,75.26H35.174c-0.465,0-0.841,0.376-0.841,0.843v10.16c0,0.465,0.376,0.841,0.841,0.841h11.696 - c0.464,0,0.839-0.376,0.839-0.841v-10.16C47.71,75.636,47.335,75.26,46.871,75.26z"/> - <path d="M65.962,75.26H54.264c-0.462,0-0.839,0.376-0.839,0.843v10.16c0,0.465,0.377,0.841,0.839,0.841h11.698 - c0.464,0,0.839-0.376,0.839-0.841v-10.16C66.801,75.636,66.426,75.26,65.962,75.26z"/> - <path d="M85.053,75.26H73.355c-0.464,0-0.839,0.376-0.839,0.843v10.16c0,0.465,0.375,0.841,0.839,0.841h11.698 - c0.463,0,0.839-0.376,0.839-0.841v-10.16C85.892,75.636,85.516,75.26,85.053,75.26z"/> - </g> - </g> -</g> -</svg> diff --git a/_private/svg/llms-icon-checkmark.svg b/_private/svg/llms-icon-checkmark.svg deleted file mode 100644 index c8bdd2eb0c..0000000000 --- a/_private/svg/llms-icon-checkmark.svg +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="99.235px" height="79.441px" viewBox="0 0 99.235 79.441" enable-background="new 0 0 99.235 79.441" xml:space="preserve"> -<g> - <path d="M23.925,75.434c2.565,2.564,6.011,4.008,9.618,4.008c3.606,0,7.053-1.443,9.618-4.008l51.938-51.938 - c5.208-5.21,5.609-13.786,0.562-19.157c-5.291-5.69-14.188-5.771-19.558-0.321L39.234,40.888c-3.126,3.126-8.176,3.126-11.302,0 - l-4.729-4.809c-5.29-5.289-13.947-5.289-19.236,0c-5.29,5.291-5.29,13.946,0,19.235L23.925,75.434z"/> -</g> -</svg> diff --git a/_private/svg/llms-icon-circle-empty.svg b/_private/svg/llms-icon-circle-empty.svg deleted file mode 100644 index cff0485a3a..0000000000 --- a/_private/svg/llms-icon-circle-empty.svg +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="100px" height="99.999px" viewBox="0 0 100 99.999" enable-background="new 0 0 100 99.999" xml:space="preserve"> -<g> - <path d="M50,0C22.387,0,0,22.387,0,50c0,27.611,22.387,50,50,50c27.61,0,50-22.389,50-50C100,22.387,77.61,0,50,0z M49.886,89.521 - c-22.092,0-40-17.91-40-40c0-22.092,17.908-40,40-40c22.09,0,40,17.908,40,40C89.886,71.61,71.976,89.521,49.886,89.521z"/> -</g> -</svg> diff --git a/_private/svg/llms-icon-circle.svg b/_private/svg/llms-icon-circle.svg deleted file mode 100644 index 37eafb0f77..0000000000 --- a/_private/svg/llms-icon-circle.svg +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"> -<path d="M100,50c0,27.611-22.389,50-50,50C22.388,100,0,77.611,0,50C0,22.388,22.388,0,50,0C77.611,0,100,22.388,100,50z"/> -</svg> diff --git a/_private/svg/llms-icon-close.svg b/_private/svg/llms-icon-close.svg deleted file mode 100644 index 08ede2e8ea..0000000000 --- a/_private/svg/llms-icon-close.svg +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="41.347px" height="41.347px" viewBox="0 0 41.347 41.347" enable-background="new 0 0 41.347 41.347" xml:space="preserve"> -<path d="M39.552,32.456L27.769,20.673L39.552,8.89c2.189-2.189,2.405-5.524,0.481-7.448l-0.129-0.129 - c-1.923-1.924-5.259-1.708-7.448,0.482L20.673,13.578L8.89,1.794C6.701-0.395,3.366-0.611,1.442,1.313L1.313,1.442 - C-0.611,3.365-0.395,6.701,1.795,8.89l11.783,11.783L1.795,32.456c-2.19,2.19-2.406,5.526-0.482,7.448l0.129,0.129 - c1.924,1.924,5.258,1.709,7.448-0.481l11.783-11.783l11.783,11.783c2.19,2.19,5.526,2.406,7.448,0.482l0.129-0.13 - C41.957,37.98,41.742,34.646,39.552,32.456z"/> -</svg> diff --git a/_private/svg/llms-icon-course-section.svg b/_private/svg/llms-icon-course-section.svg deleted file mode 100644 index c4fa2f9590..0000000000 --- a/_private/svg/llms-icon-course-section.svg +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="74.075px" height="59.345px" viewBox="14.259 4.771 74.075 59.345" enable-background="new 14.259 4.771 74.075 59.345" - xml:space="preserve"> -<g id="Captions"> -</g> -<g id="Your_Icon"> - <path d="M85.367,46.827c-1.463-1.462-3.26-2.382-5.146-2.763V30.686v-0.018c0.008-0.399-0.119-0.778-0.391-1.052l-0.014-0.015 - l0.01-0.011l-3.621-2.077L61.25,18.928v-0.002l-0.045-0.045c-0.176-0.173-0.39-0.288-0.626-0.345 - c1.392-3.621,0.633-7.878-2.29-10.797c-3.954-3.956-10.366-3.956-14.322,0c-2.953,2.954-3.699,7.276-2.242,10.925 - c-0.112,0.059-0.22,0.134-0.312,0.227l-0.041,0.042l0,0l-14.97,8.593l-3.61,2.07l-0.009-0.011l-0.019,0.02 - c-0.218,0.218-0.34,0.505-0.379,0.813c-0.017,0.141-0.017,0.291,0,0.443v13.199c-1.893,0.382-3.693,1.302-5.161,2.767 - c-3.956,3.955-3.954,10.367,0,14.323c3.957,3.956,10.369,3.956,14.323,0s3.954-10.368,0-14.323 - c-1.463-1.462-3.261-2.382-5.146-2.763V31.998l17.476-10.032c0.03,0.031,0.059,0.064,0.089,0.096 - c1.467,1.466,3.268,2.387,5.163,2.768l-0.005,19.231c-1.89,0.38-3.69,1.3-5.158,2.766c-3.954,3.955-3.954,10.367,0,14.323 - c3.957,3.956,10.368,3.956,14.322,0c3.957-3.956,3.957-10.368,0-14.323c-1.46-1.462-3.261-2.382-5.145-2.763V24.824 - c1.887-0.381,3.686-1.299,5.145-2.762c0.078-0.078,0.15-0.158,0.227-0.235l17.69,10.153v12.08 - c-1.893,0.382-3.694,1.302-5.159,2.767c-3.955,3.955-3.955,10.367,0,14.323c3.954,3.956,10.367,3.956,14.321,0 - S89.322,50.781,85.367,46.827z"/> -</g> -</svg> \ No newline at end of file diff --git a/_private/svg/llms-icon-existing-lesson.svg b/_private/svg/llms-icon-existing-lesson.svg deleted file mode 100644 index c81a2e1444..0000000000 --- a/_private/svg/llms-icon-existing-lesson.svg +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="57.167px" height="67.093px" viewBox="25.833 5.809 57.167 67.093" enable-background="new 25.833 5.809 57.167 67.093" - xml:space="preserve"> -<g> - <polygon fill="none" points="76.76,30.078 76.76,59.559 78.25,59.559 78.25,10.309 40.25,10.309 40.25,12.717 59.398,12.717 "/> - <polygon fill="none" points="53.611,35.865 53.611,17.346 40.25,17.346 40.25,59.559 72.129,59.559 72.129,35.865 "/> - <polygon fill="none" points="35.25,17.346 30.462,17.346 30.462,68.271 72.129,68.271 72.129,63.809 35.25,63.809 "/> - <polygon fill="none" points="58.24,18.504 58.24,31.235 70.973,31.235 "/> - <path d="M35.25,5.809v6.908h-9.417v60.186H76.76v-9.094H83v-58H35.25z M72.129,68.271H30.462V17.346h4.787h5h13.362v18.519h18.518 - v23.694v4.25V68.271z M58.24,31.235V18.504l12.732,12.731H58.24z M78.25,59.559h-1.49V30.078L59.398,12.717H40.25v-2.408h38V59.559 - z"/> -</g> -</svg> diff --git a/_private/svg/llms-icon-facebook.svg b/_private/svg/llms-icon-facebook.svg deleted file mode 100644 index 052d7607ae..0000000000 --- a/_private/svg/llms-icon-facebook.svg +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="96.421px" height="96.417px" viewBox="0 0 96.421 96.417" enable-background="new 0 0 96.421 96.417" xml:space="preserve"> -<path fill="#FFFFFF" d="M96.421,48.208c0,26.628-21.586,48.209-48.212,48.209C21.582,96.417,0,74.836,0,48.208 - C0,21.581,21.582,0,48.209,0C74.835,0,96.421,21.581,96.421,48.208z"/> -<path fill="#41A7DE" d="M48.178,5.217c-23.666,0-42.855,19.19-42.855,42.854c0,23.67,19.19,42.854,42.855,42.854 - c23.668,0,42.853-19.185,42.853-42.854C91.031,24.407,71.846,5.217,48.178,5.217z M57.359,48.088h-6.007c0,9.594,0,21.41,0,21.41 - h-8.898c0,0,0-11.7,0-21.41h-4.233v-7.566h4.233v-4.898c0-3.505,1.664-8.979,8.978-8.979l6.595,0.027v7.346c0,0-4.008,0-4.785,0 - c-0.779,0-1.89,0.385-1.89,2.058v4.447h6.786L57.359,48.088z"/> -</svg> diff --git a/_private/svg/llms-icon-folder.svg b/_private/svg/llms-icon-folder.svg deleted file mode 100644 index 78a73d7c3a..0000000000 --- a/_private/svg/llms-icon-folder.svg +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="98.372px" height="82.271px" viewBox="0 0 98.372 82.271" enable-background="new 0 0 98.372 82.271" xml:space="preserve"> -<path d="M97.278,28.066c-1.18-1.663-3.158-2.612-5.439-2.612H83.17v-9.43c0-3.629-2.957-6.588-6.588-6.588H46.187 - c-1.294,0-3.311-1.023-4.068-2.068l-2.277-3.11C38.068,1.826,34.464,0,31.456,0H20.92c-3.309,0-6.637,2.35-7.739,5.471l-0.725,2.054 - c-0.344,0.966-1.681,1.912-2.707,1.912H6.595C2.956,9.437,0,12.396,0,16.024v59.513c0,0.318,0.061,0.621,0.159,0.896 - c0.057,1.182,0.418,2.295,1.091,3.23c1.172,1.654,3.154,2.605,5.43,2.605h67.143c4.062,0,8.285-2.998,9.629-6.826l14.492-41.396 - C98.694,31.904,98.45,29.719,97.278,28.066z M6.595,14.784h3.154c3.311,0,6.639-2.355,7.741-5.484l0.724-2.043 - c0.345-0.965,1.685-1.912,2.706-1.912h10.536c1.292,0,3.309,1.026,4.072,2.068l2.271,3.11c1.775,2.425,5.384,4.261,8.388,4.261 - h30.396c0.676,0,1.25,0.568,1.25,1.24v9.43H24.701c-4.056,0-8.289,2.999-9.628,6.837L5.345,60.062V16.024 - C5.345,15.353,5.913,14.784,6.595,14.784z M92.901,32.291L78.409,73.676c-0.594,1.695-2.783,3.25-4.586,3.25H6.68 - c-0.516,0-0.917-0.131-1.077-0.354c-0.155-0.227-0.146-0.646,0.023-1.129l14.489-41.396c0.6-1.697,2.78-3.249,4.586-3.249h67.137 - c0.518,0,0.924,0.13,1.08,0.354C93.077,31.376,93.069,31.799,92.901,32.291z"/> -</svg> diff --git a/_private/svg/llms-icon-free.svg b/_private/svg/llms-icon-free.svg deleted file mode 100644 index 97f8e04613..0000000000 --- a/_private/svg/llms-icon-free.svg +++ /dev/null @@ -1,6 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" width="210px" height="100px" viewBox="0 0 210 100" enable-background="new 0 0 210 100" xml:space="preserve"> -<g> - <path d="M92.284,43.255c0.421-0.912,0.633-2.071,0.633-3.475c0-2.106-0.599-4.065-1.792-5.47S88.213,32,85.965,32H75v16h10.965 c0.796,0,1.603-0.693,2.423-0.881c0.818-0.187,1.567-0.849,2.246-1.389C91.312,45.194,91.862,44.168,92.284,43.255z"/> - <path d="M210,14.19C210,6.353,203.646,0,195.81,0H14.19C6.354,0,0,6.353,0,14.19v71.62C0,93.647,6.354,100,14.19,100H195.81 c7.837,0,14.19-6.353,14.19-14.19V14.19z M53.604,46c1.029,0,1.896,0.073,2.597,0.752c0.703,0.678,1.054,1.399,1.054,2.429 c0,0.982-0.351,1.468-1.054,2.146C55.5,52.006,54.634,52,53.604,52H37v19.581c0,1.029-0.238,1.895-0.963,2.597 c-0.729,0.703-1.519,1.053-2.502,1.053c-1.028,0-1.792-0.351-2.539-1.053C30.247,73.476,30,72.609,30,71.581V29.812 c0-1.217,0.348-2.43,1.237-3.319C32.125,25.605,33.107,25,34.371,25h20.147c1.028,0,1.895,0.5,2.597,1.177 c0.702,0.68,1.053,1.615,1.053,2.643c0,0.983-0.351,1.65-1.053,2.329C56.412,31.826,55.546,32,54.518,32H37v14H53.604z M99.479,74.143c-0.726,0.725-1.579,1.088-2.562,1.088c-0.656,0-1.254-0.152-1.791-0.456c-0.537-0.305-0.972-0.683-1.299-1.245 L82.104,54H75v17.581c0,1.029,0.02,1.895-0.729,2.597c-0.748,0.703-1.418,1.053-2.4,1.053c-1.03,0-1.983-0.351-2.709-1.053 C68.437,73.476,68,72.609,68,71.581V29.812c0-1.217,0.619-2.43,1.507-3.319C70.396,25.605,71.646,25,72.908,25h13.057 c4.258,0,7.698,1.47,10.319,4.091c2.713,2.715,4.071,6.304,4.071,10.61c0,4.306-1.333,7.786-4,10.358 c-1.64,1.545-3.675,2.666-6.107,3.32l9.757,16.366c0.374,0.608,0.561,1.246,0.561,1.9C100.565,72.583,100.204,73.418,99.479,74.143 z M139.63,73.746c-0.725,0.679-1.579,1.254-2.562,1.254H116.22c-1.218,0-2.109-0.668-3.024-1.533 c-0.91-0.866-1.195-2.167-1.195-3.43V29.812c0-1.217,0.273-2.43,1.163-3.319c0.888-0.888,1.795-1.493,3.057-1.493h20.357 c1.029,0,1.896,0.511,2.598,1.212c0.702,0.702,1.054,1.649,1.054,2.678c0,0.983-0.352,1.639-1.054,2.292 c-0.701,0.657-1.568,0.818-2.598,0.818H119v14h16.665c1.027,0,1.896,0.073,2.597,0.752c0.701,0.678,1.053,1.399,1.053,2.429 c0,0.982-0.352,1.468-1.053,2.146c-0.701,0.679-1.569,0.673-2.597,0.673H119v15h18.068c0.982,0,1.837,0.56,2.562,1.237 c0.727,0.679,1.089,1.736,1.089,2.721C140.719,71.987,140.356,73.068,139.63,73.746z M180.135,73.746 c-0.726,0.679-1.578,1.254-2.562,1.254h-20.85c-1.217,0-1.86-0.668-2.774-1.533C153.037,72.601,153,71.3,153,70.037V29.812 c0-1.217,0.025-2.43,0.916-3.319c0.888-0.888,1.544-1.493,2.808-1.493h20.357c1.029,0,1.896,0.511,2.598,1.212 c0.702,0.702,1.053,1.649,1.053,2.678c0,0.983-0.351,1.639-1.053,2.292C178.977,31.839,178.11,32,177.081,32H160v14h16.168 c1.029,0,1.896,0.073,2.598,0.752c0.702,0.678,1.054,1.399,1.054,2.429c0,0.982-0.352,1.468-1.054,2.146 c-0.702,0.679-1.568,0.673-2.598,0.673H160v15h17.573c0.983,0,1.836,0.56,2.562,1.237c0.726,0.679,1.088,1.736,1.088,2.721 C181.223,71.987,180.86,73.068,180.135,73.746z"/> -</g> -</svg> diff --git a/_private/svg/llms-icon-gear.svg b/_private/svg/llms-icon-gear.svg deleted file mode 100644 index f5e213cc24..0000000000 --- a/_private/svg/llms-icon-gear.svg +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"> -<g> - <g id="cog"> - <path d="M100,56.153v-12.5l-14.94-6.225c-0.416-1.172-0.854-2.306-1.391-3.419L89.7,18.994l-8.841-8.837 - l-14.881,6.128c-1.135-0.55-2.294-1.012-3.491-1.44L56.153,0h-12.5l-6.178,14.794c-1.244,0.44-2.441,0.903-3.625,1.465 - l-14.856-5.969l-8.837,8.837l6.056,14.722c-0.587,1.209-1.062,2.44-1.516,3.712L0,43.847v12.5l14.709,6.128 - c0.453,1.27,0.94,2.504,1.525,3.713l-5.944,14.818l8.837,8.838l14.76-6.078c1.184,0.562,2.394,1.013,3.637,1.44L43.847,100h12.5 - l6.188-14.869c1.185-0.44,2.356-0.902,3.479-1.44l14.99,6.007l8.838-8.838l-6.153-14.916c0.525-1.121,0.953-2.259,1.369-3.418 - L100,56.153z M49.903,68.75c-10.35,0-18.75-8.4-18.75-18.75c0-10.35,8.4-18.75,18.75-18.75c10.35,0,18.75,8.4,18.75,18.75 - C68.653,60.35,60.253,68.75,49.903,68.75z"/> - </g> -</g> -</svg> diff --git a/_private/svg/llms-icon-google.svg b/_private/svg/llms-icon-google.svg deleted file mode 100644 index e5ae714900..0000000000 --- a/_private/svg/llms-icon-google.svg +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="96.42px" height="96.418px" viewBox="0 0 96.42 96.418" enable-background="new 0 0 96.42 96.418" xml:space="preserve"> -<path fill="#FFFFFF" d="M96.42,48.209c0,26.627-21.584,48.209-48.213,48.209C21.582,96.418,0,74.836,0,48.209S21.582,0,48.207,0 - C74.836,0,96.42,21.582,96.42,48.209z"/> -<path fill="#449ED8" d="M39.4,29.062c-3.396-0.104-5.682,3.321-5.092,7.787c0.588,4.474,3.818,7.599,7.225,7.701 - c3.402,0.099,5.361-2.777,4.775-7.25C45.725,32.833,42.807,29.166,39.4,29.062z"/> -<path fill="#449ED8" d="M40.836,53.701c-5.074-0.059-9.371,3.201-9.371,6.981c0,3.856,3.666,7.066,8.732,7.066 - c7.137,0,9.621-3.011,9.621-6.871c0-0.466-0.055-0.923-0.162-1.361c-0.561-2.181-2.777-3.38-5.535-5.296 - C43.123,53.898,42.018,53.711,40.836,53.701z"/> -<path fill="#41A7DE" d="M48.109,5.578c-23.666,0-42.854,19.188-42.854,42.854c0,23.672,19.188,42.855,42.854,42.855 - s42.854-19.184,42.854-42.855C90.963,24.767,71.775,5.578,48.109,5.578z M51.381,37.111c0,2.793-1.547,5.045-3.727,6.746 - c-2.137,1.67-2.537,2.368-2.537,3.785c0,1.209,2.547,3.006,3.719,3.889c4.074,3.057,4.902,4.981,4.902,8.809 - c0,4.771-5.141,9.518-13.508,9.518c-7.34,0-13.533-2.98-13.533-7.758c0-4.844,5.137-9.895,12.475-9.895 - c0.799,0,1.533-0.023,2.293-0.023c-1.004-0.97-1.816-1.815-1.816-3.288c0-0.882,0.277-1.718,0.67-2.464 - c-0.398,0.023-0.805,0.051-1.223,0.051c-6.033,0-9.543-4.239-9.543-9.549c0-5.196,5.348-9.926,11.756-9.926 - c3.303,0,12.627,0,12.627,0l-2.818,2.965h-3.318C50.137,31.31,51.381,34.067,51.381,37.111z M69.52,36.332h-5.828v5.824h-2.914 - v-5.824h-5.826v-2.914h5.826V27.59h2.914v5.828h5.828V36.332z"/> -</svg> diff --git a/_private/svg/llms-icon-graph.svg b/_private/svg/llms-icon-graph.svg deleted file mode 100644 index d44b4b3562..0000000000 --- a/_private/svg/llms-icon-graph.svg +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="98.976px" height="81.71px" viewBox="0 0 98.976 81.71" enable-background="new 0 0 98.976 81.71" xml:space="preserve"> -<g> - <path d="M5.822,56.414H2.811c-0.833,0-1.505,0.673-1.505,1.506v22.285c0,0.828,0.672,1.505,1.505,1.505h3.011 - c0.833,0,1.505-0.677,1.505-1.505V57.92C7.327,57.087,6.655,56.414,5.822,56.414z"/> - <path d="M23.891,56.414H20.88c-0.831,0-1.505,0.673-1.505,1.506v22.285c0,0.828,0.674,1.505,1.505,1.505h3.011 - c0.831,0,1.505-0.677,1.505-1.505V57.92C25.396,57.087,24.721,56.414,23.891,56.414z"/> - <path d="M41.959,40.15h-3.011c-0.831,0-1.505,0.677-1.505,1.51v38.545c0,0.828,0.675,1.505,1.505,1.505h3.011 - c0.833,0,1.505-0.677,1.505-1.505V41.66C43.464,40.827,42.792,40.15,41.959,40.15z"/> - <path d="M60.028,27.504h-3.011c-0.831,0-1.505,0.673-1.505,1.506v51.195c0,0.828,0.675,1.505,1.505,1.505h3.011 - c0.831,0,1.508-0.677,1.508-1.505V29.01C61.536,28.177,60.859,27.504,60.028,27.504z"/> - <path d="M78.098,40.15h-3.013c-0.83,0-1.505,0.677-1.505,1.51v38.545c0,0.828,0.675,1.505,1.505,1.505h3.013 - c0.831,0,1.504-0.677,1.504-1.505V41.66C79.602,40.827,78.929,40.15,78.098,40.15z"/> - <path d="M96.166,20.276h-3.011c-0.831,0-1.504,0.673-1.504,1.506v58.423c0,0.828,0.673,1.505,1.504,1.505h3.011 - c0.83,0,1.505-0.677,1.505-1.505V21.782C97.67,20.949,96.996,20.276,96.166,20.276z"/> - <path d="M94.66,0c-2.38,0-4.314,1.935-4.314,4.312c0,0.915,0.284,1.761,0.768,2.455L77.927,25.669 - c-0.419-0.139-0.87-0.217-1.334-0.217c-1.023,0-1.963,0.355-2.7,0.954l-11.169-8.068c0.071-0.312,0.115-0.643,0.115-0.98 - c0-2.382-1.938-4.316-4.317-4.316c-2.379,0-4.314,1.935-4.314,4.316c0,0.391,0.057,0.771,0.154,1.137l-12.102,9.413 - c-0.551-0.26-1.161-0.403-1.807-0.403c-2.377,0-4.312,1.931-4.316,4.309L25.24,37.625c-0.761-0.677-1.759-1.084-2.854-1.084 - c-1.614,0-3.021,0.885-3.764,2.203L8.544,37.179c-0.399-1.966-2.145-3.449-4.228-3.449C1.937,33.729,0,35.664,0,38.042 - c0,2.382,1.937,4.32,4.316,4.32c1.614,0,3.021-0.894,3.764-2.212l10.075,1.57c0.404,1.97,2.146,3.453,4.23,3.453 - c2.379,0,4.316-1.939,4.316-4.321c0-0.19-0.018-0.382-0.043-0.572l10.548-5.622c0.794,0.902,1.952,1.475,3.247,1.475 - c2.38,0,4.317-1.935,4.317-4.312c0-0.624-0.137-1.223-0.38-1.761l11.729-9.119c0.69,0.46,1.514,0.729,2.403,0.729 - c0.944,0,1.816-0.304,2.527-0.819l11.297,8.16c-0.043,0.243-0.071,0.499-0.071,0.759c0,2.382,1.935,4.316,4.316,4.316 - c2.379,0,4.316-1.935,4.316-4.316c0-0.811-0.23-1.57-0.62-2.217L93.583,8.49c0.346,0.091,0.703,0.143,1.076,0.143 - c2.38,0,4.316-1.935,4.316-4.316S97.042,0,94.66,0z"/> -</g> -</svg> diff --git a/_private/svg/llms-icon-instagram.svg b/_private/svg/llms-icon-instagram.svg deleted file mode 100644 index 2ded6d4aca..0000000000 --- a/_private/svg/llms-icon-instagram.svg +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="96.42px" height="96.418px" viewBox="0 0 96.42 96.418" enable-background="new 0 0 96.42 96.418" xml:space="preserve"> -<circle fill="#FFFFFF" cx="48.21" cy="48.209" r="48.21"/> -<path fill="#FFFFFF" d="M48.656,5.578c-23.662,0-42.85,19.188-42.85,42.854c0,23.672,19.188,42.855,42.85,42.855 - c23.672,0,42.854-19.184,42.854-42.855C91.51,24.767,72.328,5.578,48.656,5.578z"/> -<g> - <path fill="#41A7DE" d="M48.154,57.057c4.811,0,8.729-3.914,8.729-8.725c0-1.905-0.619-3.658-1.648-5.088 - c-1.584-2.205-4.166-3.639-7.076-3.639c-2.916,0-5.49,1.434-7.08,3.637c-1.033,1.43-1.646,3.185-1.648,5.09 - C39.422,53.143,43.342,57.057,48.154,57.057z"/> - <polygon fill="#41A7DE" points="67.213,37.655 67.213,30.334 67.213,29.246 66.119,29.247 58.807,29.271 58.834,37.682 "/> - <path fill="#41A7DE" d="M48.154,4.729c-24.039,0-43.602,19.56-43.602,43.603c0,24.037,19.562,43.598,43.602,43.598 - s43.6-19.561,43.6-43.598C91.754,24.289,72.199,4.729,48.154,4.729z M72.949,43.244v20.299c0,5.287-4.295,9.588-9.582,9.588H32.943 - c-5.287,0-9.586-4.301-9.586-9.588V43.244V33.117c0-5.287,4.299-9.584,9.586-9.584h30.424c5.287,0,9.582,4.297,9.582,9.584V43.244z - "/> - <path fill="#41A7DE" d="M61.715,48.332c0,7.473-6.082,13.558-13.561,13.558c-7.48,0-13.559-6.085-13.559-13.558 - c0-1.802,0.354-3.521,0.994-5.088h-7.402v20.299c0,2.627,2.133,4.752,4.754,4.752h30.426c2.615,0,4.752-2.125,4.752-4.752V43.244 - h-7.41C61.354,44.811,61.715,46.53,61.715,48.332z"/> -</g> -</svg> diff --git a/_private/svg/llms-icon-lightbulb.svg b/_private/svg/llms-icon-lightbulb.svg deleted file mode 100644 index ac4d827f84..0000000000 --- a/_private/svg/llms-icon-lightbulb.svg +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="98.03px" height="132.97px" viewBox="0 0 98.03 132.97" enable-background="new 0 0 98.03 132.97" xml:space="preserve"> -<path d="M73.946,95.57H24.083c-2.298,0-4.155-1.857-4.155-4.155s1.857-4.155,4.155-4.155h49.862c2.298,0,4.154,1.857,4.154,4.155 - S76.244,95.57,73.946,95.57z M78.1,103.884c0-2.301-1.856-4.156-4.154-4.156H24.083c-2.298,0-4.155,1.855-4.155,4.156 - c0,2.298,1.857,4.155,4.155,4.155h49.862C76.244,108.039,78.1,106.182,78.1,103.884z M69.791,116.35 - c0-2.296-1.857-4.156-4.155-4.156H32.394c-2.298,0-4.155,1.86-4.155,4.156c0,2.298,1.857,4.154,4.155,4.154h33.242 - C67.933,120.504,69.791,118.647,69.791,116.35z M18.555,82.115c1.707-1.531,1.843-4.161,0.302-5.868 - C4.102,59.896,4.947,35.099,20.779,19.801c15.835-15.307,40.645-15.307,56.471,0c15.836,15.298,16.678,40.094,1.923,56.446 - c-1.544,1.707-1.405,4.337,0.299,5.868c1.708,1.535,4.337,1.396,5.871-0.3c17.771-19.695,16.757-49.562-2.312-67.987 - c-19.066-18.438-48.95-18.438-68.026,0C-4.07,32.253-5.085,62.12,12.689,81.815c0.82,0.911,1.945,1.371,3.084,1.371 - C16.763,83.187,17.763,82.83,18.555,82.115z M61.48,128.814c0-2.298-1.856-4.155-4.154-4.155H40.704 - c-2.298,0-4.155,1.857-4.155,4.155c0,2.296,1.857,4.155,4.155,4.155h16.622C59.624,132.97,61.48,131.11,61.48,128.814z"/> -</svg> diff --git a/_private/svg/llms-icon-linkedin.svg b/_private/svg/llms-icon-linkedin.svg deleted file mode 100644 index eb2b4d370a..0000000000 --- a/_private/svg/llms-icon-linkedin.svg +++ /dev/null @@ -1,14 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="96.421px" height="96.418px" viewBox="0 0 96.421 96.418" enable-background="new 0 0 96.421 96.418" xml:space="preserve"> -<circle fill="#FFFFFF" cx="48.211" cy="48.209" r="48.211"/> -<path fill="#449ED8" d="M51.203,45.278v-0.087c-0.016,0.031-0.039,0.062-0.061,0.087H51.203z"/> -<path fill="#41A7DE" d="M48.634,5.578c-23.669,0-42.854,19.185-42.854,42.85c0,23.673,19.186,42.855,42.854,42.855 - c23.667,0,42.856-19.183,42.856-42.855C91.49,24.763,72.3,5.578,48.634,5.578z M36.935,68.908h-9.187V41.279h9.187V68.908z - M32.342,37.5h-0.06c-3.081,0-5.075-2.121-5.075-4.773c0-2.711,2.056-4.779,5.193-4.779c3.145,0,5.082,2.068,5.141,4.779 - C37.541,35.379,35.545,37.5,32.342,37.5z M70.058,68.908h-9.186V54.127c0-3.716-1.326-6.25-4.654-6.25 - c-2.533,0-4.049,1.715-4.711,3.363c-0.246,0.59-0.305,1.404-0.305,2.237v15.431H42.02c0,0,0.118-25.041,0-27.629h9.183v3.912 - c1.223-1.89,3.408-4.562,8.281-4.562c6.039,0,10.574,3.944,10.574,12.432V68.908z"/> -</svg> diff --git a/_private/svg/llms-icon-lock.svg b/_private/svg/llms-icon-lock.svg deleted file mode 100644 index 0e6e321254..0000000000 --- a/_private/svg/llms-icon-lock.svg +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="76.861px" height="100px" viewBox="0 0 76.861 100" enable-background="new 0 0 76.861 100" xml:space="preserve"> -<g> - <path d="M71.409,40.384h-1.949v-9.12c0-16.867-13.386-30.958-30.115-31.258c-0.457-0.008-1.37-0.008-1.828,0 - C20.786,0.307,7.4,14.397,7.4,31.264v9.12H5.452C2.45,40.384,0,43.483,0,47.31v45.739C0,96.871,2.45,100,5.452,100h65.957 - c3.004,0,5.452-3.129,5.452-6.951V47.31C76.861,43.483,74.413,40.384,71.409,40.384z M44.609,70.133v13.821 - c0,1.582-1.323,2.922-2.908,2.922h-6.54c-1.585,0-2.909-1.34-2.909-2.922V70.133c-1.537-1.512-2.431-3.603-2.431-5.916 - c0-4.382,3.389-8.149,7.695-8.324c0.458-0.018,1.371-0.018,1.828,0c4.309,0.175,7.695,3.942,7.695,8.324 - C47.04,66.53,46.146,68.621,44.609,70.133z M56.617,40.384H39.344h-1.828H20.244v-9.12c0-10.047,8.166-18.355,18.187-18.355 - s18.187,8.309,18.187,18.355V40.384L56.617,40.384z"/> -</g> -</svg> diff --git a/_private/svg/llms-icon-media.svg b/_private/svg/llms-icon-media.svg deleted file mode 100644 index 8642eaecbb..0000000000 --- a/_private/svg/llms-icon-media.svg +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="100.438px" height="76.853px" viewBox="0 0 100.438 76.853" enable-background="new 0 0 100.438 76.853" - xml:space="preserve"> -<g> - <g> - <path d="M89.695,0H10.746C4.819,0,0,4.828,0,10.75v55.359c0,5.923,4.819,10.743,10.746,10.743h78.949 - c5.919,0,10.742-4.82,10.742-10.743V10.75C100.438,4.828,95.614,0,89.695,0z M95.322,66.109c0,3.106-2.521,5.636-5.627,5.636 - H10.746c-3.101,0-5.63-2.529-5.63-5.636V10.75c0-3.105,2.529-5.635,5.63-5.635h78.949c3.098,0,5.627,2.529,5.627,5.635V66.109z"/> - <path d="M50.219,12.917c-14.091,0-25.509,11.426-25.509,25.513c0,14.087,11.418,25.505,25.509,25.505 - c14.087,0,25.513-11.41,25.513-25.505C75.731,24.343,64.306,12.917,50.219,12.917z M43.299,52.271V24.599L61.785,38.43 - L43.299,52.271z"/> - </g> -</g> -</svg> diff --git a/_private/svg/llms-icon-member.svg b/_private/svg/llms-icon-member.svg deleted file mode 100644 index 29296c5204..0000000000 --- a/_private/svg/llms-icon-member.svg +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="98.062px" height="135.368px" viewBox="0 0 98.062 135.368" enable-background="new 0 0 98.062 135.368" - xml:space="preserve"> -<path d="M49.041,57.537c15.889,0,28.775-12.875,28.775-28.761C77.815,12.885,64.93,0,49.041,0C33.149,0,20.273,12.885,20.273,28.776 - C20.273,44.663,33.149,57.537,49.041,57.537z M61.222,59.5H36.829C16.522,59.5,0,76.019,0,96.338v29.834l0.08,0.47l2.055,0.655 - c19.389,6.039,36.221,8.071,50.08,8.071c27.07,0,42.757-7.726,43.729-8.213l1.929-0.973h0.188V96.338 - C98.081,76.019,81.543,59.5,61.222,59.5z"/> -</svg> diff --git a/_private/svg/llms-icon-new-lesson.svg b/_private/svg/llms-icon-new-lesson.svg deleted file mode 100644 index 5c77d519fd..0000000000 --- a/_private/svg/llms-icon-new-lesson.svg +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="50.926px" height="60.185px" viewBox="25.833 4.352 50.926 60.185" enable-background="new 25.833 4.352 50.926 60.185" - xml:space="preserve"> -<path d="M25.833,4.352h33.565L76.76,21.713v42.824H25.833V4.352z M30.463,8.981v50.926h41.666V27.5H53.611V8.981H30.463z - M58.24,10.139V22.87h12.732L58.24,10.139z"/> -</svg> diff --git a/_private/svg/llms-icon-paper.svg b/_private/svg/llms-icon-paper.svg deleted file mode 100644 index 33d0ee01d8..0000000000 --- a/_private/svg/llms-icon-paper.svg +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="100px" height="100.008px" viewBox="0 0 100 100.008" enable-background="new 0 0 100 100.008" xml:space="preserve"> -<g> - <g> - <path d="M0,0v100.008h65.267L100,65.269V0H0L0,0z M4.65,95.35V4.647h90.701v58.692l-0.961,0.959H64.306v30.091l-0.969,0.963H4.65 - V95.35z"/> - <rect x="16.528" y="15.283" width="66.945" height="4.769"/> - <rect x="16.528" y="30.826" width="66.945" height="4.768"/> - <rect x="16.528" y="46.376" width="33.375" height="4.768"/> - <rect x="16.528" y="61.911" width="16.685" height="4.768"/> - </g> -</g> -</svg> diff --git a/_private/svg/llms-icon-papers.svg b/_private/svg/llms-icon-papers.svg deleted file mode 100644 index 971fbb8a3f..0000000000 --- a/_private/svg/llms-icon-papers.svg +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="86.048px" height="100.557px" viewBox="0 0 86.048 100.557" enable-background="new 0 0 86.048 100.557" - xml:space="preserve"> -<path d="M83.773,25.916h-2.274c-1.257,0-2.274,1.021-2.274,2.28c0,1.251,1.018,2.272,2.274,2.272v65.545H30.472 - c-0.002-1.26-1.02-2.281-2.276-2.281c-1.255,0-2.274,1.021-2.274,2.281v2.271c0,1.26,1.02,2.272,2.274,2.272h55.578 - c1.257,0,2.274-1.013,2.274-2.272V28.196C86.048,26.937,85.03,25.916,83.773,25.916z"/> -<path d="M77.409,89.647V19.549c0-1.251-1.02-2.272-2.276-2.272h-2.274c-1.255,0-2.274,1.021-2.274,2.272 - c0,1.259,1.018,2.28,2.274,2.28v65.537H21.832c0-1.251-1.02-2.272-2.276-2.272c-1.255,0-2.274,1.021-2.274,2.28v2.272 - c0,1.251,1.02,2.272,2.274,2.272h55.578C76.39,91.919,77.409,90.898,77.409,89.647z"/> -<path d="M68.768,81.008V10.911c0-1.259-1.02-2.272-2.274-2.272h-7.54c-1.257,0-2.276,1.013-2.276,2.272 - c0,1.259,1.02,2.28,2.276,2.28h5.263v65.537H13.191c-0.002-1.251-1.02-2.272-2.274-2.272c-1.259,0-2.276,1.021-2.276,2.272v2.28 - c0,1.251,1.017,2.272,2.276,2.272h55.576C67.748,83.281,68.768,82.259,68.768,81.008z"/> -<path d="M60.127,72.362V18.908c0-0.08-0.004-0.15-0.01-0.23c-0.006-0.055-0.017-0.111-0.026-0.158 - c-0.002-0.024-0.004-0.04-0.008-0.063c-0.012-0.063-0.031-0.126-0.05-0.19c-0.002-0.008-0.002-0.016-0.004-0.024 - c-0.02-0.063-0.043-0.126-0.069-0.19c-0.002,0-0.004-0.016-0.006-0.016c-0.025-0.063-0.053-0.119-0.081-0.174 - c-0.004-0.008-0.01-0.024-0.014-0.032c-0.027-0.047-0.058-0.095-0.087-0.143c-0.01-0.016-0.018-0.031-0.03-0.047 - c-0.027-0.04-0.059-0.079-0.091-0.126c-0.014-0.016-0.025-0.032-0.041-0.056c-0.036-0.04-0.071-0.079-0.109-0.119 - c-0.014-0.016-0.025-0.032-0.041-0.04L42.826,0.665c-0.014-0.016-0.03-0.023-0.043-0.04c-0.04-0.04-0.078-0.079-0.119-0.111 - c-0.018-0.016-0.04-0.032-0.057-0.04c-0.04-0.032-0.081-0.063-0.123-0.095c-0.016-0.008-0.031-0.016-0.045-0.023 - c-0.049-0.032-0.095-0.063-0.146-0.087c-0.01-0.008-0.021-0.016-0.032-0.016c-0.055-0.032-0.111-0.056-0.17-0.079 - c-0.006-0.008-0.014-0.008-0.02-0.008c-0.063-0.032-0.125-0.048-0.188-0.071c-0.008,0-0.016,0-0.024-0.008 - c-0.063-0.016-0.126-0.031-0.19-0.047c-0.02,0-0.04,0-0.059-0.008c-0.054-0.008-0.107-0.016-0.163-0.024C41.371,0,41.296,0,41.219,0 - H2.274C1.02,0,0,1.014,0,2.272v70.089c0,1.259,1.02,2.28,2.274,2.28h55.578C59.109,74.642,60.127,73.621,60.127,72.362z - M43.493,7.768l8.866,8.86h-8.866V7.768z M4.551,70.089V4.545h34.392v14.363c0,1.251,1.02,2.272,2.274,2.272h14.359v48.909H4.551z" - /> -</svg> diff --git a/_private/svg/llms-icon-play.svg b/_private/svg/llms-icon-play.svg deleted file mode 100644 index 84f24e06af..0000000000 --- a/_private/svg/llms-icon-play.svg +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"> -<g> - <g id="_x33_56._Play_1_"> - <g> - <path d="M92.297,24.63C78.692,1.075,48.583-6.992,25.037,6.607C1.482,20.201-6.587,50.316,7.008,73.871 - c13.604,23.548,43.714,31.617,67.264,18.02C97.818,78.291,105.898,48.178,92.297,24.63z M69.35,83.358 - C50.514,94.237,26.421,87.783,15.542,68.94C4.66,50.103,11.121,26.012,29.956,15.138C48.794,4.26,72.888,10.715,83.763,29.554 - C94.642,48.391,88.186,72.478,69.35,83.358z M67.382,47.242l-25.789-15.03c-2.345-1.373-4.241-0.276-4.229,2.442l0.134,29.848 - c0.013,2.718,1.932,3.821,4.289,2.461L67.375,52.19C69.721,50.831,69.728,48.622,67.382,47.242z"/> - </g> - </g> -</g> -</svg> diff --git a/_private/svg/llms-icon-plus.svg b/_private/svg/llms-icon-plus.svg deleted file mode 100644 index 68e72da1aa..0000000000 --- a/_private/svg/llms-icon-plus.svg +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"> -<g> - <path d="M90.897,40.873H59.097V9.104C59.097,4.078,55.042,0,50.011,0c-5.028,0-9.084,4.078-9.084,9.106v31.788H9.116 - C4.087,40.894-0.002,44.97,0,50c-0.002,2.514,1.013,4.817,2.659,6.461c1.647,1.651,3.921,2.694,6.432,2.694h31.836v31.742 - c0,2.514,1,4.793,2.647,6.437c1.647,1.646,3.915,2.665,6.429,2.665c5.029,0,9.094-4.078,9.094-9.102V59.152h31.801 - c5.027,0,9.107-4.112,9.102-9.141C99.999,44.985,95.921,40.873,90.897,40.873z"/> -</g> -</svg> diff --git a/_private/svg/llms-icon-question.svg b/_private/svg/llms-icon-question.svg deleted file mode 100644 index 96a968e830..0000000000 --- a/_private/svg/llms-icon-question.svg +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="100px" height="100.001px" viewBox="0 0 100 100.001" enable-background="new 0 0 100 100.001" xml:space="preserve"> -<g> - <path d="M49.333,0.004C21.72,0.374-0.363,23.06,0.004,50.673c0.37,27.601,23.054,49.691,50.665,49.323 - c27.605-0.372,49.693-23.058,49.326-50.669C99.625,21.724,76.941-0.364,49.333,0.004z M49.184,80.435l-0.276-0.004 - c-4.252-0.126-7.25-3.259-7.129-7.447c0.119-4.118,3.189-7.107,7.301-7.107l0.247,0.005c4.37,0.129,7.335,3.231,7.212,7.54 - C56.417,77.551,53.394,80.435,49.184,80.435z M67.07,44.937c-1,1.42-3.199,3.185-5.969,5.343l-3.052,2.106 - c-1.675,1.302-2.686,2.527-3.065,3.734c-0.299,0.947-0.445,1.198-0.471,3.129l-0.005,0.49h-11.65l0.034-0.985 - c0.143-4.053,0.242-6.437,1.922-8.406c2.634-3.094,8.446-6.836,8.693-6.994c0.832-0.628,1.535-1.342,2.058-2.104 - c1.223-1.686,1.764-3.014,1.764-4.317c0-1.81-0.536-3.483-1.599-4.974c-1.021-1.438-2.96-2.166-5.764-2.166 - c-2.782,0-4.687,0.882-5.826,2.692c-1.171,1.862-1.764,3.818-1.764,5.815v0.497H30.365l0.021-0.519 - c0.311-7.357,2.936-12.655,7.802-15.747c3.058-1.969,6.863-2.966,11.302-2.966c5.811,0,10.717,1.412,14.578,4.196 - c3.913,2.821,5.898,7.048,5.898,12.562C69.966,39.407,68.992,42.304,67.07,44.937z"/> -</g> -</svg> diff --git a/_private/svg/llms-icon-rightarrow.svg b/_private/svg/llms-icon-rightarrow.svg deleted file mode 100644 index b41f94050f..0000000000 --- a/_private/svg/llms-icon-rightarrow.svg +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="58.862px" height="100.225px" viewBox="0 0 58.862 100.225" enable-background="new 0 0 58.862 100.225" - xml:space="preserve"> -<path d="M57.36,46.492L12.37,1.508c-2-2.011-5.25-2.011-7.247,0L1.5,5.124c-2,2.003-2,5.25,0,7.247l37.737,37.743L1.5,87.845 - c-2,2.01-2,5.251,0,7.261l3.624,3.616c1.996,2.004,5.247,2.004,7.247,0L57.36,53.738C59.363,51.734,59.363,48.487,57.36,46.492z"/> -</svg> diff --git a/_private/svg/llms-icon-search.svg b/_private/svg/llms-icon-search.svg deleted file mode 100644 index b6c659b26a..0000000000 --- a/_private/svg/llms-icon-search.svg +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="98.727px" height="98.726px" viewBox="0 0 98.727 98.726" enable-background="new 0 0 98.727 98.726" xml:space="preserve"> -<g id="Search"> - <path d="M96.311,84.64l-21.45-21.445c-0.113-0.111-0.247-0.192-0.367-0.303c4.222-6.397,6.685-14.062,6.685-22.304 - C81.179,18.174,63.004,0,40.59,0C18.174,0,0,18.174,0,40.588s18.171,40.594,40.588,40.594c8.243,0,15.906-2.466,22.306-6.686 - c0.106,0.121,0.187,0.252,0.3,0.363l21.449,21.446c3.224,3.227,8.442,3.227,11.668,0C99.533,93.089,99.533,87.866,96.311,84.64z - M40.59,67.105c-14.647,0-26.52-11.872-26.52-26.518S25.943,14.07,40.59,14.07c14.643,0,26.515,11.872,26.515,26.518 - S55.233,67.105,40.59,67.105z"/> -</g> -</svg> diff --git a/_private/svg/llms-icon-target.svg b/_private/svg/llms-icon-target.svg deleted file mode 100644 index 0df9f3ea7c..0000000000 --- a/_private/svg/llms-icon-target.svg +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="101.105px" height="101.103px" viewBox="0 0 101.105 101.103" enable-background="new 0 0 101.105 101.103" - xml:space="preserve"> -<path d="M76.976,34.705l-4.366,4.371c2.049,3.771,3.218,8.063,3.218,12.643c0,14.576-11.869,26.444-26.444,26.444 - S22.941,66.295,22.941,51.719c0-14.575,11.867-26.441,26.442-26.441c4.58,0,8.873,1.167,12.646,3.216l4.369-4.369 - c-4.954-3.069-10.774-4.833-17.015-4.833c-17.884,0-32.428,14.544-32.428,32.427c0,17.882,14.544,32.428,32.428,32.428 - c17.881,0,32.427-14.544,32.427-32.428C81.811,45.48,80.045,39.658,76.976,34.705z M64.841,46.855l-5.25,5.237 - c-0.195,5.479-4.686,9.846-10.208,9.846c-5.643,0-10.22-4.577-10.22-10.22c0-5.521,4.369-10.009,9.848-10.203l5.252-5.24 - c-1.544-0.495-3.174-0.765-4.878-0.765c-8.937,0-16.208,7.276-16.208,16.208c0,8.936,7.271,16.209,16.208,16.209 - c8.932,0,16.206-7.273,16.206-16.209C65.589,50.03,65.335,48.385,64.841,46.855z M91.719,26.324l-4.372,4.371 - c3.46,6.225,5.433,13.394,5.433,21.024c0,23.929-19.467,43.398-43.396,43.398c-23.928,0-43.398-19.47-43.398-43.398 - c0-23.925,19.47-43.397,43.398-43.397c7.632,0,14.799,1.976,21.024,5.435l4.372-4.369c-7.425-4.476-16.118-7.051-25.396-7.051 - C22.148,2.336,0,24.482,0,51.719c0,27.235,22.148,49.384,49.383,49.384s49.383-22.148,49.383-49.384 - C98.767,42.439,96.191,33.748,91.719,26.324z M85.233,26.453l-5.716-0.636L51.371,53.963c-1.169,1.17-3.065,1.17-4.234,0 - c-1.167-1.166-1.167-3.06,0-4.229l28.146-28.148l-0.632-5.711L90.523,0l2.115,8.466l8.467,2.113L85.233,26.453z"/> -</svg> diff --git a/_private/svg/llms-icon-twitter.svg b/_private/svg/llms-icon-twitter.svg deleted file mode 100644 index c1d3cebb54..0000000000 --- a/_private/svg/llms-icon-twitter.svg +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="96.42px" height="96.418px" viewBox="0 0 96.42 96.418" enable-background="new 0 0 96.42 96.418" xml:space="preserve"> -<circle fill="#FFFFFF" cx="48.21" cy="48.209" r="48.21"/> -<path fill="#41A7DE" d="M47.882,5.466C24.216,5.466,5.03,24.655,5.03,48.322c0,23.667,19.186,42.852,42.853,42.852 - c23.668,0,42.855-19.185,42.855-42.852C90.738,24.655,71.55,5.466,47.882,5.466z M64.925,39.584c0.018,0.375,0.024,0.75,0.024,1.133 - c0,11.618-8.843,25.019-25.016,25.019c-4.967,0-9.587-1.456-13.477-3.951c0.688,0.078,1.388,0.118,2.095,0.118 - c4.123,0,7.91-1.401,10.918-3.761c-3.845-0.072-7.09-2.613-8.209-6.104c0.536,0.098,1.087,0.156,1.653,0.156 - c0.804,0,1.578-0.109,2.315-0.307c-4.018-0.812-7.053-4.363-7.053-8.622c0-0.036,0-0.071,0-0.107 - c1.188,0.657,2.543,1.049,3.984,1.094c-2.359-1.574-3.91-4.268-3.91-7.317c0-1.611,0.434-3.122,1.19-4.423 - c4.335,5.322,10.813,8.824,18.12,9.187c-0.148-0.641-0.226-1.313-0.226-2.004c0-4.855,3.937-8.786,8.794-8.786 - c2.525,0,4.812,1.066,6.414,2.771c2.002-0.392,3.885-1.123,5.586-2.133c-0.66,2.053-2.053,3.776-3.866,4.864 - c1.776-0.206,3.472-0.686,5.048-1.381C68.132,36.793,66.642,38.345,64.925,39.584z"/> -</svg> diff --git a/_private/svg/llms-icon-users.svg b/_private/svg/llms-icon-users.svg deleted file mode 100644 index e7abbd1aa6..0000000000 --- a/_private/svg/llms-icon-users.svg +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="100.188px" height="84.312px" viewBox="0 0 100.188 84.312" enable-background="new 0 0 100.188 84.312" - xml:space="preserve"> -<path d="M60.464,14.467c4.635,2.909,7.881,7.823,8.467,13.527c1.894,0.887,3.991,1.393,6.209,1.393 - c8.12,0,14.698-6.582,14.698-14.698S83.26,0,75.14,0C67.104,0,60.584,6.458,60.464,14.467z M50.835,44.555 - c8.116,0,14.698-6.573,14.698-14.689s-6.582-14.698-14.698-14.698S36.142,21.75,36.142,29.866S42.719,44.555,50.835,44.555z - M57.062,45.557H44.6c-10.374,0-18.814,8.436-18.814,18.814v15.248l0.04,0.239l1.051,0.328c9.903,3.087,18.499,4.125,25.582,4.125 - c13.829,0,21.838-3.947,22.335-4.196l0.984-0.496h0.098V64.371C75.885,53.993,67.44,45.557,57.062,45.557z M81.375,30.389H69.01 - c-0.133,4.95-2.253,9.411-5.592,12.613c9.22,2.741,15.966,11.292,15.966,21.395v4.692c12.219-0.443,19.262-3.912,19.723-4.143 - l0.98-0.497h0.102V49.203C100.188,38.825,91.749,30.389,81.375,30.389z M25.049,29.387c2.878,0,5.553-0.834,7.819-2.271 - c0.723-4.702,3.242-8.799,6.834-11.594c0.013-0.275,0.044-0.55,0.044-0.825C39.748,6.582,33.166,0,25.049,0 - C16.938,0,10.36,6.582,10.36,14.698S16.938,29.387,25.049,29.387z M38.249,43.002c-3.327-3.193-5.429-7.628-5.584-12.551 - c-0.461-0.026-0.909-0.062-1.379-0.062H18.813C8.44,30.389,0,38.825,0,49.203V64.45l0.04,0.24l1.051,0.328 - c7.948,2.475,15.031,3.619,21.191,3.982v-4.604C22.282,54.294,29.023,45.744,38.249,43.002z"/> -</svg> diff --git a/_private/svg/llms-icon-view.svg b/_private/svg/llms-icon-view.svg deleted file mode 100644 index 730ef22729..0000000000 --- a/_private/svg/llms-icon-view.svg +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="98.5px" height="98.5px" viewBox="0 0 98.5 98.5" enable-background="new 0 0 98.5 98.5" xml:space="preserve"> -<g> - <g id="curved_x5F_arrow"> - <path d="M54.559,24.021c-15.641-0.298-28.567,12.146-28.863,27.787c-0.297,15.639,12.146,28.564,27.786,28.863 - c-11.175-0.213-20.061-9.443-19.847-20.617c0.21-11.176,9.441-20.061,20.616-19.847l4.047,0.076l-0.155,8.094l16.493-15.879 - L58.757,16.005l-0.152,8.093L54.559,24.021z"/> - </g> -</g> -<g> - <path d="M49.25,0C22.049,0,0,22.049,0,49.25S22.049,98.5,49.25,98.5S98.5,76.451,98.5,49.25S76.451,0,49.25,0z M49.25,97.359 - c-26.571,0-48.11-21.539-48.11-48.109c0-26.571,21.54-48.11,48.11-48.11c26.57,0,48.109,21.54,48.109,48.11 - C97.359,75.82,75.82,97.359,49.25,97.359z"/> -</g> -</svg> diff --git a/_private/svg/llms-icon-youtube.svg b/_private/svg/llms-icon-youtube.svg deleted file mode 100644 index 543bc31e90..0000000000 --- a/_private/svg/llms-icon-youtube.svg +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="96.42px" height="96.418px" viewBox="0 0 96.42 96.418" enable-background="new 0 0 96.42 96.418" xml:space="preserve"> -<circle fill="#FFFFFF" cx="48.21" cy="48.209" r="48.21"/> -<path fill="#449ED8" d="M48.279,41.904c0.332,0,0.594-0.09,0.789-0.271c0.195-0.184,0.295-0.439,0.295-0.757v-6.509 - c0-0.265-0.1-0.473-0.301-0.634c-0.197-0.163-0.457-0.245-0.783-0.245c-0.295,0-0.539,0.082-0.725,0.245 - c-0.186,0.161-0.279,0.369-0.279,0.634v6.509c0,0.327,0.09,0.577,0.262,0.757C47.711,41.818,47.957,41.904,48.279,41.904z"/> -<path fill="#449ED8" d="M53.666,53.926c-0.334,0-0.668,0.08-1.002,0.255c-0.322,0.173-0.635,0.43-0.926,0.754v-4.733h-2.193v14.705 - h2.193v-0.832c0.281,0.331,0.594,0.574,0.926,0.731c0.332,0.164,0.707,0.235,1.133,0.235c0.643,0,1.135-0.2,1.475-0.613 - c0.344-0.412,0.512-0.998,0.512-1.76v-6.023c0-0.889-0.182-1.564-0.541-2.029C54.877,54.153,54.355,53.926,53.666,53.926z - M53.547,62.361c0,0.352-0.061,0.598-0.184,0.75c-0.129,0.157-0.32,0.232-0.586,0.232c-0.186,0-0.357-0.039-0.525-0.121 - c-0.166-0.07-0.34-0.205-0.514-0.38v-6.757c0.146-0.15,0.295-0.262,0.447-0.334c0.152-0.07,0.305-0.105,0.457-0.105 - c0.293,0,0.518,0.096,0.678,0.279c0.154,0.191,0.227,0.467,0.227,0.84V62.361z"/> -<polygon fill="#449ED8" points="33.275,52.341 35.803,52.341 35.803,64.906 38.242,64.906 38.242,52.341 40.775,52.341 - 40.775,50.201 33.275,50.201 "/> -<path fill="#449ED8" d="M45.748,62.292c-0.205,0.237-0.426,0.43-0.674,0.587c-0.242,0.151-0.449,0.226-0.602,0.226 - c-0.203,0-0.348-0.052-0.445-0.172c-0.088-0.116-0.137-0.296-0.137-0.553v-8.324h-2.166v9.069c0,0.649,0.129,1.125,0.381,1.451 - c0.252,0.33,0.631,0.487,1.133,0.487c0.408,0,0.826-0.112,1.258-0.347c0.434-0.231,0.854-0.566,1.252-1.005v1.194h2.166V54.056 - h-2.166V62.292z"/> -<path fill="#41A7DE" d="M48.658,5.578c-23.664,0-42.852,19.188-42.852,42.854c0,23.672,19.188,42.855,42.852,42.855 - c23.67,0,42.854-19.184,42.854-42.855C91.512,24.767,72.328,5.578,48.658,5.578z M53.826,31.726h2.439v9.159 - c0,0.282,0.057,0.483,0.156,0.609c0.098,0.129,0.27,0.192,0.496,0.192c0.178,0,0.408-0.081,0.684-0.251 - c0.275-0.171,0.521-0.381,0.75-0.643v-9.067h2.445v11.946h-2.445V42.35c-0.445,0.482-0.914,0.863-1.402,1.113 - c-0.488,0.252-0.959,0.385-1.418,0.385c-0.568,0-0.986-0.183-1.275-0.541c-0.283-0.351-0.43-0.887-0.43-1.599V31.726z - M44.766,34.453c0-0.923,0.328-1.664,0.982-2.207c0.658-0.55,1.543-0.82,2.652-0.82c1.01,0,1.836,0.287,2.484,0.861 - c0.641,0.58,0.963,1.328,0.963,2.234v6.173c0,1.022-0.314,1.819-0.945,2.407c-0.635,0.582-1.506,0.872-2.615,0.872 - c-1.066,0-1.922-0.302-2.564-0.903c-0.637-0.601-0.957-1.406-0.957-2.422V34.453z M38.115,27.477l1.785,6.477h0.172l1.701-6.477 - h2.791l-3.199,9.479v6.717h-2.746v-6.42l-3.27-9.775H38.115z M70.084,61.562c0,4.32-3.506,7.83-7.828,7.83H35.057 - c-4.324,0-7.824-3.51-7.824-7.83v-6.294c0-4.319,3.5-7.829,7.824-7.829h27.199c4.322,0,7.828,3.51,7.828,7.829V61.562z"/> -<path fill="#449ED8" d="M60.213,53.789c-0.973,0-1.758,0.293-2.371,0.884c-0.619,0.591-0.924,1.366-0.924,2.301v4.87 - c0,1.049,0.283,1.868,0.838,2.457c0.555,0.605,1.324,0.896,2.293,0.896c1.082,0,1.896-0.277,2.436-0.837 - c0.547-0.563,0.816-1.401,0.816-2.517v-0.555h-2.232v0.492c0,0.639-0.076,1.053-0.213,1.241c-0.143,0.188-0.395,0.282-0.758,0.282 - c-0.342,0-0.59-0.113-0.734-0.33c-0.141-0.227-0.209-0.623-0.209-1.193V59.74h4.146v-2.767c0-1.029-0.266-1.814-0.799-2.363 - C61.969,54.06,61.205,53.789,60.213,53.789z M61.068,58.053h-1.914v-1.092c0-0.457,0.07-0.788,0.223-0.977 - c0.148-0.201,0.398-0.303,0.742-0.303c0.33,0,0.578,0.102,0.725,0.303c0.146,0.188,0.225,0.52,0.225,0.977V58.053z"/> -</svg> diff --git a/_readme/changelog.md b/_readme/changelog.md deleted file mode 100644 index 8d04458652..0000000000 --- a/_readme/changelog.md +++ /dev/null @@ -1,203 +0,0 @@ -== Changelog == - - -= v3.17.8 - 2018-05-04 = ------------------------- - -##### Updates and Enchancements - -+ Added admin email notification when student cancels a subscription -+ Quiz results will now display the question's description when reviewing results as a student and on the admin panel during grading -+ Add action hook fired when a student cancels a subscription (`llms_subscription_cancelled_by_student`) -+ Reduce unnecessary DB queries for integrations by checking for dependencies and then calling querying the options table to see if the integration has been enabled. -+ Updated the notifications settings table to be more friendly to the human eye - -##### Bug Fixes - -+ Fix admin scripts enqueue order. Fixes issue preventing manual student enrollment selection from functioning properly in certain scenarios. -+ Shift + Enter when in a question choice field now adds a return as expected instead of exiting the field -+ When pasting into question choice fields HTML from RTF documents will be automatically stripped -+ Ensure certificates print with a white brackground regardless of theme CSS -+ Fix issue causing themes with `overflow:hidden` on divs from cutting certificate background images -+ Upon export completion unlock tables regardless of mail success / failure -+ Resolve issue causing incorrect number of access plans to be returned on systems that have custom defaults set for `WP_Query` `post_per_page` parameter -+ Fix error occurring when all 3rd party integrations are disabled by filter, credit to [@Mte90](https://github.com/Mte90)! -+ Ensure `LLMS()->integrations()->integrations()` returns all integrations regardless of availability. -+ Updated `LLMS_Abstract_Options_Data` to have an option set method - -##### Template Updates - -+ [templates/quiz/results-attempt-questions-list.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/results-attempt-questions-list.php) - - -= v3.17.7 - 2018-04-27 = ------------------------- - -+ Fix issue preventing assignments passing grade requirement from saving properly -+ Fix issue preventing builder toggle switches from properly saving some switch field data -+ Fix with "Launch Builder" button causing it to extend outside the bounds of its container -+ Fix issue with builder radio select fields during view rerenders -+ Course Outline shortcode (and widget) now retrieve parent course of the current page more consistently with other shortcodes -+ Added ability to filter which custom post types which can be children of a course (allows course shortcodes & widgets to be used in assignment sidebars of custom content areas) - - -= v3.17.6 - 2018-04-26 = ------------------------- - -+ Updated language on recurring orders with no expiration settings. Orders no longer say "Lifetime Access" and instead output no expiration information -+ Quiz editor on builder updated to be consistent visually and functionally to the lesson settings editor -+ Improved the builder field API to allow for radio element fields -+ Fix issue causing JS error on admin settings pages -+ Updated CSS for Certificates to be more generally compatible with theme styles when printed -+ Allow system print settings to control print layout for certificates by removing explicit landscape declarations -+ Now passing additional data to filters used to create custom columns on reporting screens -+ Remove unused JS files & Chosen JS library -+ Added filter to allow opting into alternate student dashboard order layout. Use `add_filter( 'llms_sd_stacked_order_layout', '__return_true' )` to stack the payment update sidebar below the main order information. This is disabled by default. -+ Achievement and Certificate basic notifications now auto-dismiss after 10 seconds like all other basic notifications -+ Deprecated Filter `llms_get_quiz_theme_settings` and added backwards compatible methods to transition themes using this filter to the new custom field api. For more information see new methods at https://lifterlms.com/docs/course-builder-custom-fields-for-developers/ -+ Increased default z-index on notifications to prevent notifications from being hidden behind floating / static navigation menus - - -##### Template Updates - -+ [templates/myaccount/my-orders.php](https://github.com/gocodebox/lifterlms/blob/master/templates/myaccount/my-orders.php) -+ [templates/myaccount/view-order.php](https://github.com/gocodebox/lifterlms/blob/master/templates/myaccount/view-order.php) - - -= v3.17.5 - 2018-04-23 = ------------------------- - -##### Admin Settings Interface Improvements - -+ Improved admin settings page interface to allow for section navigation -+ Updated checkout setting pages to utilize a separate section (page) for each available payment gateway -+ Added a table of payment gateways to see at a glance which gateways are enabled and allows drag and drop reordering of gateway display order -+ Moved dashboard endpoints to a separate section on the accounts settings area -+ Updated CSS on settings page to have more regular spacing between subtitles and settings fields -+ Added a "View" button next to any admin setting post/page selection field to allow quick viewing of the selected post -+ Purchase page setting field is now ajax powered like all other page selection settings -+ Renamed dashboard settings section titles to be more consistent with language in other areas of LifterLMS -+ All dashboard endpoints now automatically sanitized to be URL safe - -##### Updates and Enhancements - -+ Dashboard endpoints can now be deregistered by setting the endpoint slug to be blank on account settings - -##### Bug Fixes - -+ Fix issue causing 404s for various script files when SCRIPT_DEBUG is enabled -+ Fix issue with audio & video embeds to prexvent fallback to default post attachments -+ Fix issue causing student selection boxes to malfunction due to missing dependencies when loaded over slow connections - -##### Template Updates - -+ [templates/myaccount/navigation.php](https://github.com/gocodebox/lifterlms/blob/master/templates/myaccount/navigation.php) - - -= v3.17.4 - 2018-04-17 = ------------------------- - -+ Added core RTL language support -+ Fixed fatal error on student management tables resulting from deleted admin users who manually enrolled students -+ Added filter to allow 3rd parties to disable achievement dupchecking (`llms_achievement_has_user_earned`) -+ Added {student_id} merge code which can be utilized on certificates -+ Added merge code insert button to certificates editor -+ Added filter to allow 3rd parties to disable certificate dupchecking (`llms_certificate_has_user_earned`) -+ Added filter to allow 3rd parties to add custom merge codes to certificates (`llms_certificate_merge_codes`) -+ Fix restriction check issue for lessons with drip or prerequisites on course outline widget / shortcode -+ Bumped WP tested to version to 4.9.5 - -##### Template Updates - -+ [templates/course/complete-lesson-link.php](https://github.com/gocodebox/lifterlms/blob/master/templates/course/complete-lesson-link.php) -+ [templates/course/outline-list-small.php](https://github.com/gocodebox/lifterlms/blob/master/templates/course/outline-list-small.php) - - -= v3.17.3 - 2018-04-11 = ------------------------- - -+ Course and Membership instructor metabox search field now correcty states "Select an Instructor" instead of previous "Select a Student" -+ Added missing translation for "Select a Student" on admin panel student selection search fields -+ Fix issue causing reporting export CSVs to throw a SYLK interpretation error when opened in Excel -+ Fix issue causing drafted courses and memberships to be published when the "Update" button is clicked to save changes -+ Remove use of PHP 7.2 deprecated `create_function` -+ Fix errors resulting from quiz questions which have been deleted -+ Fix issue causing current date / time to display as the End Date for incomplete quiz attempts on quiz reporting screens - -##### Template Updates - -+ [templates/admin/reporting/tabs/quizzes/attempt.php](https://github.com/gocodebox/lifterlms/blob/master/templates/admin/reporting/tabs/quizzes/attempt.php) -+ [templates/quiz/results-attempt-questions-list.php](https://github.com/gocodebox/lifterlms/blob/master/templates/quiz/results-attempt-questions-list.php) - - -= v3.17.2 - 2018-04-09 = ------------------------- - -+ Fixed issue preventing lesson video and audio embeds from being *removed* when using the course builder settings editor -+ Fixed issue causing question images to lose the image source -+ Updated student management table for courses and memberships to show the name (and a link to the user profile) of the site user who manually enrolled the student. -+ Add "All Time" reporting to various reporting filters -+ Added API for builder fields to enable multiple select fields -+ Fix memory leak related to assignments rendering on course builder -+ Fix issue causing course progress and enrollment checks to incorrectly display progress data cached for other users -+ Lesson progression actions (Mark Complete & Take Quiz buttons) will now always display to users with edit capabilities regardless of enrollment status - -##### Template Updates - -+ [templates/course/complete-lesson-link.php](https://github.com/gocodebox/lifterlms/blob/master/templates/course/complete-lesson-link.php) -+ [templates/course/outline-list-small.php](https://github.com/gocodebox/lifterlms/blob/master/templates/course/outline-list-small.php) - - -= v3.17.1 - 2018-03-30 = ------------------------- - -+ Refactored lesson completion methods to allow 3rd party customization of lesson completion behavior via filters and hooks. -+ Remove duplicate lesson completion notice implemented. Only popover notifications will display now instead of popovers and inline messages. -+ Object completion will now automatically prevent multiple records of completion from being recorded for a single object. -+ Lesson Mark Complete button and lessons completed by quiz now utilizes a generic trigger to mark lessons as complete: `llms_trigger_lesson_completion`. -+ Removed several unused functions from frontend forms class -+ Moved lesson completion form controllers to their own class - -##### Templates updates - -+ [templates/course/complete-lesson-link.php](https://github.com/gocodebox/lifterlms/blob/master/templates/course/complete-lesson-link.php) - - -= v3.17.0 - 2018-03-27 = ------------------------- - -##### Builder Updates - -+ Moved action buttons for each lesson (for opening quiz and lesson editor) to be static below the lesson title as opposed to only being visible on hover -+ Added new audio and video status indicator icons for each lesson -+ Various status indicator icons will now have different icons in addition to different colors depending on their state -+ Replaced "pencil" icons that open the WordPress post editor with a small "WP" icon -+ Added several actions and filters to backend functions so that 3rd parties can hook into builder saves -+ Added lesson settings editing to the builder. Lesson settings can now be updated from settings metaboxes on the lesson post edit screen AND on the builder. -+ Added prerequisite validation for lessons to prevent accidental impossible prerequisite creating (eg: Lesson 5 can never be a prerequisite for Lesson 4) -+ Added functions and filters to allow 3rd parties to add custom fields to the builder. For more details see [an example](https://lifterlms.com/docs/course-builder-custom-fields-for-developers/). -+ Fixed issue causing changes made in "Text" mode on content editors wouldn't trigger save events -+ Fixed issue causing lesson prerequisites to not properly display on the course builder -+ Fixed CSS z-index issues related to builder field tooltip displays -+ Removed unused Javascript dependencies - -##### Bug Fixes - -+ Fixed typo on filter on quiz question image getter function - -##### Updates - -+ Performance improvements made to database queries and functions related to student enrollment status and student course progress queries. Thanks to [@mte90](https://github.com/Mte90) for raising issues and testing solutions related to these updates and changes! -+ Added PHP Requires plugin header (5.6 minimum) -+ Added HTTP User Agent data to the system report -+ [LifterLMS Assignments Beta](https://lifterlms.com/product/lifterlms-assignments?utm_source=LifterLMS%20Plugin&utm_medium=CHANGELOG&utm_campaign=assignments%20preorder) is imminent and this release adds functionality to the Builder which will be extended by Assignments upon when availability - - -= v3.16.16 - 2018-03-19 = -------------------------- - -+ Fixed builder issue causing multiple question choices to be incorrectly selected -+ Fixed builder issue with media library uploads causing an error message to prevent new uploads before the quiz or question has been persistend to the database -+ Fixed builder issue preventing quizzes from being deleted before they were persisted to the database -+ Fixed builder issue causing autosaves to interrupt typing and reset lesson and section titles -+ Fixed JS console error related to LifterLMS JS dependency checks \ No newline at end of file diff --git a/_readme/description.md b/_readme/description.md deleted file mode 100644 index a18f477539..0000000000 --- a/_readme/description.md +++ /dev/null @@ -1,227 +0,0 @@ -== Description == - -LifterLMS is a powerful WordPress LMS plugin that makes it easy to create, sell, and protect engaging online courses. The mission of LifterLMS is to democratize education in the digital classroom. - -https://www.youtube.com/watch?v=LugJPS7bhxI - - -# **Extend and Enhance LifterLMS with Add-ons** - -#### **Advanced** - -_Courses + Community + Coaching = Engagement_ - -+ [LifterLMS Private Areas][pa] -+ [LifterLMS Social Learning][sl] - -#### **Integrations** - -_Integrate with the third-party tools you know and love_ - -+ [LifterLMS Stripe][stripe] -+ [LifterLMS PayPal][pp] -+ [LifterLMS Authorize.Net][anet] -+ [LifterLMS WooCommerce][wc] -+ [LifterLMS ConvertKit][ck] -+ [LifterLMS MailChimp][mc] - -#### **Design Tools** - -_Make your learning platform beautiful_ - -+ [LifterLMS Pro][pro] -+ [LifterLMS LaunchPad Theme][lp] - -#### **Support** - -_Our world-class support has your back_ - -+ [LifterLMS Pro][pro] -+ [LifterLMS Office Hours][oh] - -#### **Save Big with a Bundle** - -_Save money while unlocking the full potential of your learning platform_ - -+ [Infinity Bundle][infinity] -+ [Universe Bundle][universe] - - -# **Give LifterLMS a Try** - -_Try LifterLMS and the premium add-ons before investing any time_ - -+ [Try LifterLMS for $1][try] -+ [Take a Free Course][demo] - - -# **[LifterLMS Features][features]** - -_With LifterLMS and LifterLMS Add-ons you can..._ - -#### **Create Courses** - -+ Multimedia lessons -+ Quizzes -+ Course builder -+ Drip Content -+ Pre-requisites -+ Course tracks -+ Assignments (coming soon) -+ Quiz time limits -+ Student dashboard -+ Multi-instructor -+ Lesson downloads -+ Course import & export -+ Discussion areas -+ Instructional design -+ Forum integrations -+ Graphics pack -+ Course reviews - -#### **Build an Education-Based Business** - -+ Credit card payments -+ One-time payments -+ Recurring payments -+ Payment plans -+ Unlimited pricing models -+ PayPal -+ Subscriptions -+ Checkout -+ Free courses -+ Course bundles -+ Private coaching upsells -+ Coupons -+ Bulk sales -+ Affiliate ready -+ Native sales pages -+ Offline sales -+ Customizable enrollment -+ Country and currency -+ E-commerce dashboard -+ Credit card management -+ Subscription switching -+ Payment switching - -#### **Engage Your Students** - -+ Achievement bages -+ Certificates -+ Peronalized email -+ Social learning -+ Private coaching -+ Text messaging - -#### **Offer Memberships** - -+ Sitewide membership -+ Course bundles -+ Traditional memberships -+ Automatic course enrollment -+ Bulk course enrollment -+ Content restrictions -+ Members-only payment plans -+ Private group discussions -+ Members-only forums - -#### **Integrate with the Tools You Need** - -+ Payment gateways -+ Email marketing -+ Forums -+ Mobile friendly -+ Use any theme -+ Built for compatibility -+ CRMs -+ E-learning authoring tools -+ Tin Can API (xAPI) - -#### **Secure and Protect Your Content** - -+ Course protection -+ User account management and registration -+ Members-only content -+ Restricted access -+ Password management -+ Self-hosted - -#### **Own and Manage Your Platform** - -+ Detailed reporting -+ Gradebook -+ Email notifications -+ Bulk enrollments -+ Student management -+ Access management -+ Web design management -+ Branding & Typography -+ LMS Roles -+ Security -+ Require terms -+ Scaleable -+ Layout -+ Testing tools - -#### **Get Support** - -+ Technical support -+ Live office hours -+ Free training courses -+ Setup wizard -+ Detailed documentation -+ Dynamic resources -+ Demo course -+ System analyzer -+ User community -+ Developer ecosystem - -#### **Further Reading** - -+ The [LifterLMS Official Homepage][home] -+ The [LifterLMS Knowledgebase][docs] -+ The [LifterLMS Blog][blog] -+ The [LifterLMS Podcast][podcast] - - -# **Join Our Growing Community** - -When you download LifterLMS, you join a thriving community of education entrepreneurs, developers, and WordPress enthusiasts. We’re one of the fastest growing open source eLearning communities online, and you are welcome here. - -If you’re interested in contributing to LifterLMS, head over to the [LifterLMS GitHub Repository][git] to find out how you can pitch in. - -Want to add a new language to LifterLMS? Swell! You can contribute at [translate.wordpress.org][translate]. - -Also I'd like to invite you to the [LifterLMS VIP Facebook group][facebook] so you can check out what other LifterLMS users are up to and ask questions to the community. - - -[home]: https://lifterlms.com/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[docs]: https://lifterlms.com/docs/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[blog]: http://blog.lifterlms.com/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[podcast]: http://podcast.lifterlms.com/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[git]: https://github.com/gocodebox/lifterlms/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[demo]: https://demo.lifterlms.com/course/how-to-build-a-learning-management-system-with-lifterlms/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[translate]: https://translate.lifterlms.com/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[facebook]: https://www.facebook.com/groups/lifterlmsvip/ - -[anet]: https://lifterlms.com/product/authorize-net/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[dfy]: https://lifterlms.com/dfy/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[ck]: https://lifterlms.com/product/lifterlms-convertkit/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[infinity]: https://lifterlms.com/product/infinity-bundle/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[lp]: https://lifterlms.com/product/launchpad/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[mc]: https://lifterlms.com/product/mailchimp-extension/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[oh]: https://lifterlms.com/product/office-hours/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[pa]: https://lifterlms.com/product/private-areas/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[pp]: https://lifterlms.com/product/paypal-extension/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[pro]: https://lifterlms.com/product/lifterlms-pro/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[sl]: https://lifterlms.com/product/social-learning/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[stripe]: https://lifterlms.com/product/stripe-extension/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[try]: https://lifterlms.com/product/try/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[universe]: https://lifterlms.com/product/universe-bundle/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[wc]: https://lifterlms.com/product/woocommerce-extension/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale - -[features]: https://lifterlms.com/features/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[feature-lms]: https://lifterlms.com/features/lms/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[feature-ecomm]: https://lifterlms.com/features/e-commerce/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[feature-membership]: https://lifterlms.com/features/membership/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale -[feature-engagement]: https://lifterlms.com/features/engagement/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale diff --git a/_readme/faqs.md b/_readme/faqs.md deleted file mode 100644 index d2ac7dfd2d..0000000000 --- a/_readme/faqs.md +++ /dev/null @@ -1,41 +0,0 @@ -== Frequently Asked Questions == - -#### Are there any troubleshooting steps you'd suggest I try that might resolve my issue before I post a new thread? - -First, make sure that you're running the latest version of LifterLMS. And if you've got any other LifterLMS extensions or themes, make sure those are running the most current version as well. - -The most common issues we see are either plugin conflicts, theme conflicts, or outdated servers. You can test if a plugin or theme is conflicting by manually deactivating other plugins until just LifterLMS is running on your site. If the issue persists from there, revert to the default Twenty Fifteen theme. If the issue is resolved after deactivating a specific plugin or your theme, you'll know that is the source of the conflict. If it is a hosting issue, contact your web host and make sure they’re running the most current version of PHP. - -Also be sure to check out the official LifterLMS [Knowledge Base](https://lifterlms.com/docs/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale). - - -#### I'm still stuck. Where do I go to file a bug or ask a question? - -Users of the free LifterLMS should post their questions in the plugin's WordPress.org forum. If you find you're not getting support in as timely a fashion as you wish, you might want to consider purchasing a [LifterLMS Pro license](https://lifterlms.com/product/lifterlms-pro/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale). - -If you're already a LifterLMS Pro user or you have purchased one of the LifterLMS themes or extensions, you're entitled to log into your account and contact the support team directly on the [LifterLMS website](https://lifterlms.com/my-account/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale). We can provide a deeper level of support here and address your needs on a daily basis during the work week. Generally, except in times of increased support loads, we reply to all comments within 12 business hours. - - -#### LifterLMS is awesome! Can you set it all up for me? - -Yes. You can get an instant quote for the team at LifterLMS to set everything up for you through our signature Done For You service. Get an instant quote through our automated quote generation tool on the [LifterLMS website services page](https://lifterlms.com/dfy/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale). - - -#### I'm interested in LifterLMS Pro, another LifterLMS extension, or a LifterLMS theme, but there are a few questions I've got before making the purchase. Can you help me get those addressed? - -Absolutely. If you're not finding your questions answered on the product pages, you can ask your presales questions through this [contact form](https://lifterlms.com/contact/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale). You can also connect live with a member of our team [here](https://lifterlms.com/contact/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale). - - -#### What add-ons are available for LifterLMS, and where can I read more about them? - -You can find a full list of officlai LifterLMS Add-ons [here](https://lifterlms.com/store/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale) - - -#### I have a feature idea. What's the best way to tell you about it? - -We care about your feature ideas and what you have to say. You can [request a feature](https://lifterlms.com/contact/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale), [vote on existing feature requests](?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale), and checkout the [product roadmap](https://lifterlms.com/roadmap/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale). - - -#### I still have questions. Where can I find answers? - -Be sure you’ve taken the free tutorial training video course: [How to Create an Online Course with LifterLMS](http://demo.lifterlms.com/course/how-to-build-a-learning-management-system-with-lifterlms/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale). diff --git a/_readme/header.md b/_readme/header.md deleted file mode 100644 index 13def31437..0000000000 --- a/_readme/header.md +++ /dev/null @@ -1,12 +0,0 @@ -=== LifterLMS === -Contributors: thomasplevy, chrisbadgett, kathy11, lifterlms, codeboxllc -Donate link: https://lifterlms.com -Tags: learning management system, LMS, membership, elearning, online courses, quizzes, sell courses, badges, gamification, learning, Lifter, LifterLMS -Requires at least: 4.0 -Requires PHP: 5.6 -Tested up to: 4.9.5 -Stable tag: 3.17.8 -License: GPLv3 -License URI: https://www.gnu.org/licenses/gpl-3.0.html - -LifterLMS, the #1 WordPress LMS solution, makes it easy to create, sell, and protect engaging online courses. diff --git a/_readme/installation.md b/_readme/installation.md deleted file mode 100644 index 314d73c1a6..0000000000 --- a/_readme/installation.md +++ /dev/null @@ -1,34 +0,0 @@ -== Installation == - -#### Minimum System Requirements - -LifterLMS Requires - -+ PHP 5.6 or later -+ MySQL 5.6 or later -+ WordPress 4.0 or later - -Visit our [full system requirements](https://lifterlms.com/docs/minimum-system-requirements-lifterlms/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale) for additional information. - -#### Automatic Installation - -This is the simplest way to install LifterLMS as it utilizes WordPress to handle file transfers and you never need to leave the web browser or admin panel. - -1. Log in to your WordPress dashboard. -2. Navigate to Plugins -> Add New -3. In the search field type "LifterLMS" and click "Search Plugins" -4. Once you've located LifterLMS click "Install Now" -5. Once installation is complete, click "Activate" - -#### Manual Installation - -To manually install LifterLMS you'll need to download the zip file using the "Download" link on this screen. You'll then need to use FTP to manually upload the files to the proper directory on your webserver. - -Please see this [WordPress Codex document](https://codex.wordpress.org/Managing_Plugins#Manual_Plugin_Installation) for full instruction on Manual Plugin Installation. - - -#### Setup Wizard - -After installing LifterLMS for the first time you will be redirected to the Setup Wizard. This wizard will walk quickly configure LifterLMS so you can get to course creating as quickly as possible. At the conclusion you'll have the option to import a sample course. - -You can return to the setup wizard at any time by following [these steps](https://lifterlms.com/docs/rerun-lifterlms-setup-wizard/?utm_source=LifterLMS%20Plugin&utm_medium=README&utm_campaign=Readme%20to%20Sale). diff --git a/_readme/readme.txt b/_readme/readme.txt deleted file mode 100644 index b598399c34..0000000000 --- a/_readme/readme.txt +++ /dev/null @@ -1,13 +0,0 @@ -//= include ./header.md - -//= include ./description.md - -//= include ./installation.md - -//= include ./faqs.md - -//= include ./screenshots.md - -//= include ./changelog.md - -[View the full changelog](https://github.com/gocodebox/lifterlms/blob/master/CHANGELOG.md#lifterlms-changelog) diff --git a/_readme/screenshots.md b/_readme/screenshots.md deleted file mode 100644 index aed6b60253..0000000000 --- a/_readme/screenshots.md +++ /dev/null @@ -1,26 +0,0 @@ -== Screenshots == - -1. LifterLMS Courses -2. LifterLMS Pricing Tables -3. LifterLMS Checkout -4. LifterLMS Lessons -5. LifterLMS Achievement Earned -6. LifterLMS Achievement Badges -7. LifterLMS Quiz Results -8. LifterLMS Student Dashboard -9. LifterLMS Certificates -10. LifterLMS Sales Reporting -11. LifterLMS Student Reporting -12. LifterLMS Enrollment Reporting -13. LifterLMS Sidebar Widgets -14. LifterLMS Subscription Management -15. LifterLMS Settings -16. LifterLMS Course Builder -17. LifterLMS Lesson Settings -18. LifterLMS Engagements -19. LifterLMS Email Engagements -20. LifterLMS Course Access Plans -21. LifterLMS Update Upcoming Order Details -22. LifterLMS Lock Down Non LMS Content with Memberships -23. LifterLMS Membership Course Bundles and Auto Enrollment -24. LifterLMS Business to Business Bulk Enrollment Activations with Vouchers diff --git a/assets/scss/_includes/_buttons.scss b/assets/scss/_includes/_buttons.scss deleted file mode 100644 index a0fbe6d7b2..0000000000 --- a/assets/scss/_includes/_buttons.scss +++ /dev/null @@ -1,111 +0,0 @@ -.llms-button-action, -.llms-button-danger, -.llms-button-primary, -.llms-button-secondary { - border:none; - border-radius: 0; - color: $color-white; - cursor: pointer; - font-size: 16px; - font-weight: 300; - text-decoration: none; - text-shadow: none; - line-height: 1; - margin: 0; - max-width: 100%; - padding: 12px 24px; - position: relative; - transition: all .5s ease; - - &:disabled { - opacity: 0.5; - } - &:hover, &:active { - color: $color-white; - } - &:focus { - color: $color-white; - } - - &.auto { - width: auto; - } - - &.full { - display: block; - text-align: center; - width: 100%; - } - - &.square { - padding: 12px; - } - - &.small { - font-size: 13px; - padding: 8px 14px; - &.square { padding: 8px; } - } - - &.large { - font-size: 18px; - line-height: 1.2; - padding: 16px 32px; - &.square { padding: 16px; } - .fa { - left: -7px; - position: relative; - } - } - - -} - -.llms-button-primary { - background: $color-brand-blue; - &:hover, - &.clicked { - background: $color-brand-blue-dark; - } - &:focus, - &:active { - background: $color-brand-blue-light; - } -} - -.llms-button-secondary { - background: #e1e1e1; - color: #414141; - &:hover { - color: #414141; - background: darken( #e1e1e1, 8 ); - } - &:focus, - &:active { - color: #414141; - background: lighten( #e1e1e1, 4 ); - } -} - -.llms-button-action { - background: $color-brand-orange; - &:hover, - &.clicked { - background: $color-brand-orange-dark; - } - &:focus, - &:active { - background: $color-brand-orange-light; - } -} - -.llms-button-danger { - background: $color-danger; - &:hover { - background: darken( $color-danger, 8 ); - } - &:focus, - &:active { - background: lighten( $color-danger, 4 ); - } -} diff --git a/assets/scss/_includes/_extends.scss b/assets/scss/_includes/_extends.scss deleted file mode 100644 index 3ff4e48156..0000000000 --- a/assets/scss/_includes/_extends.scss +++ /dev/null @@ -1,30 +0,0 @@ -%cf, -%clearfix { - &:before, - &:after { - content: " "; - display: table; - } - - &:after { - clear: both; - } -} - - - -%llms-element { - background: $el-background; - box-shadow: $el-box-shadow; - display: block; - color: #212121; - min-height: 85px; - padding: 15px; - text-decoration: none; - position: relative; - transition: background .4s ease; - - &:hover { - background: $el-background-hover; - } -} diff --git a/assets/scss/_includes/_grid.scss b/assets/scss/_includes/_grid.scss deleted file mode 100644 index 1b790ecfb2..0000000000 --- a/assets/scss/_includes/_grid.scss +++ /dev/null @@ -1,23 +0,0 @@ -.llms-cols { - @extend %clearfix; - - .llms-col { - width: 100%; - } - - @media all and (min-width: 600px) { - [class*="llms-col-"] { - float: left; - } - - $cols: 1; - @while $cols <= 12 { - .llms-col-#{$cols} { - width: 100% / $cols; - } - $cols: $cols + 1; - } - - } - -} diff --git a/assets/scss/_includes/_llms-donut.scss b/assets/scss/_includes/_llms-donut.scss deleted file mode 100644 index a0ed634570..0000000000 --- a/assets/scss/_includes/_llms-donut.scss +++ /dev/null @@ -1,67 +0,0 @@ -.llms-donut { - - @include clearfix; - - background-color: #f1f1f1; - background-image: none; - border-radius: 50%; - color: $color-brand-pink; - height: 200px; - overflow: hidden; - position: relative; - width: 200px; - - svg { - overflow: visible !important; - pointer-events: none; - } - - svg path { - fill: none; - stroke-width: 35px; - stroke: $color-brand-pink; - } - - &.small { - height: 100px; - width: 100px; - .percentage { - font-size: 18px; - } - } - &.large { - height: 260px; - width: 260px; - .percentage { - font-size: 48px; - } - } - - .inside { - align-items: center; - background: #fff; - border-radius: 50%; - box-sizing: border-box; - display: flex; - flex-wrap: wrap; - height: 80%; - justify-content: center; - left: 50%; - position: absolute; - text-align: center; - transform: translate(-50%, -50%); - width: 80%; - top: 50%; - z-index: 3; - } - - .percentage { - line-height: 1.2; - font-size: 34px; - } - - .caption { - font-size: 50%; - } - -} diff --git a/assets/scss/_includes/_llms-form-field.scss b/assets/scss/_includes/_llms-form-field.scss deleted file mode 100644 index 946eb36b0e..0000000000 --- a/assets/scss/_includes/_llms-form-field.scss +++ /dev/null @@ -1,180 +0,0 @@ -.llms-form-fields { - @extend %clearfix; - box-sizing: border-box; - - &.flush { - .llms-form-field { - padding: 0 0 10px; - } - } -} - - .llms-form-heading { - padding: 0 10px 10px; - } - - .llms-form-field { - float: left; - padding: 0 10px 10px; - position: relative; - width: 100%; - - &.valid { - input[type="date"], input[type="time"], input[type="datetime-local"], input[type="week"], input[type="month"], input[type="text"], input[type="email"], input[type="url"], input[type="password"], input[type="search"], input[type="tel"], input[type="number"], textarea, select { - background: rgba( #83c373, .3 ); - border-color: #83c373; - } - } - - &.error, - &.invalid { - input[type="date"], input[type="time"], input[type="datetime-local"], input[type="week"], input[type="month"], input[type="text"], input[type="email"], input[type="url"], input[type="password"], input[type="search"], input[type="tel"], input[type="number"], textarea, select { - background: rgba( $color-red, .3 ); - border-color: $color-red; - } - } - - &.align-right { - text-align: right; - } - - @media screen and ( min-width: 600px ) { - $i: 1; - @while $i <= 12 { - &.llms-cols-#{$i} { - width: $i / 12 * 100%; - $i: $i + 1; - } - } - } - - &.type-hidden { padding: 0; } - - &.type-radio, - &.type-checkbox { - input, - label { - display: inline; - width: auto; - } - input { - margin-right: 5px; - } - } - - &.type-radio { - - input[type="radio"] { - position: absolute; - opacity: 0; - visibility: none; - } - - label:before { - background: #fafafa; - background-position: -24px 0; - background-repeat: no-repeat; - border-radius: 50%; - box-shadow: hsla( 0,0%,100%,.15) 0 1px 1px, inset hsla(0,0%,0%,.35) 0 0 0 1px; - content: ''; - cursor: pointer; - display: inline-block; - height: 22px; - margin-right: 5px; - position: relative; - transition: background-position .15s cubic-bezier(.8, 0, 1, 1); - top: -3px; - vertical-align: middle; - width: 22px; - z-index: 2; - } - - - - input[type="radio"]:checked + label:before { - transition: background-position .2s .15s cubic-bezier(0, 0, .2, 1); - background-position: 0 0; - background-image: radial-gradient(ellipse at center, $color-brand-blue 0%,$color-brand-blue 40%, #fafafa 45%); - } - - } - - &.type-reset, - &.type-button, - &.type-submit { - button:not(.auto) { width: 100%; } - } - - .llms-description { - font-size: 14px; - font-style: italic; - } - - .llms-required { - color: $color-red; - } - - input, textarea, select { - width: 100%; - margin-bottom: 5px; - } - - } - - - .llms-password-strength-meter { - border: 1px solid #dadada; - display: none; - font-size: 10px; - margin-top: -10px; - padding: 1px; - position: relative; - text-align: center; - - &:before { - bottom: 0; - content: ''; - left: 0; - position: absolute; - top: 0; - transition: width .4s ease; - } - - &.mismatch, - &.too-short, - &.very-weak { - border-color: #e35b5b; - &:before { - background: rgba( #e35b5b, 0.25 ); - width: 25%; - } - } - - &.too-short:before { - width: 0; - } - - &.weak { - border-color: #f78b53; - &:before { - background: rgba( #f78b53, 0.25 ); - width: 50%; - } - } - - &.medium { - border-color: #ffc733; - &:before { - background: rgba( #ffc733, 0.25 ); - width: 75%; - } - } - - &.strong { - border-color: #83c373; - &:before { - background: rgba( #83c373, 0.25 ); - width: 100%; - } - } - } diff --git a/assets/scss/_includes/_mixins.scss b/assets/scss/_includes/_mixins.scss deleted file mode 100644 index 3aa51c29d9..0000000000 --- a/assets/scss/_includes/_mixins.scss +++ /dev/null @@ -1,71 +0,0 @@ - -@mixin clearfix() { - &:before, - &:after { - content: " "; - display: table; - } - &:after { - clear: both; - } -} - -// -// Positining mixin -// -// @param [string] $position: position -// @param [list] $args (()): offsets list -// -// @source http://hugogiraudel.com/2013/08/05/offsets-sass-mixin/ -// -@mixin position($position, $args: ()) { - $offsets: top right bottom left; - position: $position; - - @each $offset in $offsets { - $index: index($args, $offset); - - @if $index { - @if $index == length($args) { - #{$offset}: 0; - } - @else { - $next: nth($args, $index + 1); - @if is-valid-length($next) { - #{$offset}: $next; - } - @else if index($offsets, $next) { - #{$offset}: 0; - } - @else { - @warn "Invalid value `#{$next}` for offset `#{$offset}`."; - } - } - } - } -} - -// -// Function checking if $value is a valid length -// @param [literal] $value: value to test -// @return [bool] -// -@function is-valid-length($value) { - $r: (type-of($value) == "number" and not unitless($value)) or (index(auto initial inherit 0, $value) != null); - @return $r; -} - -// -// Shorthands -// -@mixin absolute($args: ()) { - @include position(absolute, $args); -} - -@mixin fixed($args: ()) { - @include position(fixed, $args); -} - -@mixin relative($args: ()) { - @include position(relative, $args); -} diff --git a/assets/scss/_includes/_quiz-result-question-list.scss b/assets/scss/_includes/_quiz-result-question-list.scss deleted file mode 100644 index 8829562a6c..0000000000 --- a/assets/scss/_includes/_quiz-result-question-list.scss +++ /dev/null @@ -1,124 +0,0 @@ -.llms-quiz-attempt-results { - margin: 0; - padding: 0; - list-style-type: none; - - .llms-quiz-attempt-question { - background: #efefef; - margin: 0 0 10px; - position: relative; - - .toggle-answer { - @include clearfix(); - color: inherit; - display: block; - padding: 10px 35px 10px 10px; - text-decoration: none; - } - - &.status--waiting.correct, - &.status--waiting.incorrect, { - background: rgba( $color-orange, 0.2 ); - .llms-status-icon { - background-color: $color-orange; - } - } - - &.status--graded.correct { - background: rgba( $color-green, 0.2 ); - .llms-status-icon { - background-color: $color-green; - } - } - &.status--graded.incorrect { - background: rgba( $color-red, 0.2 ); - .llms-status-icon { - background-color: $color-red; - } - } - - .llms-question-title { - float: left; - margin: 0; - line-height: 1; - } - - .llms-points { - float: right; - line-height: 1; - } - - .llms-status-icon-tip { - position: absolute; - right: -12px; - top: -2px; - } - - .llms-status-icon { - color: rgba( 255, 255, 255, 0.65 ); - border-radius: 50%; - font-size: 30px; - height: 40px; - line-height: 40px; - text-align: center; - width: 40px; - } - - .llms-quiz-attempt-question-main { - display: none; - padding: 0 10px 10px; - - .llms-quiz-results-label { - font-weight: 700; - margin-bottom: 10px; - } - - ul.llms-quiz-attempt-answers { - margin: 0; - padding: 0; - li.llms-quiz-attempt-answer { - padding: 0; - margin: 0 0 0 30px; - &:only-child { - list-style-type: none; - margin-left: 0; - } - } - } - - img { - height: auto; - max-width: 200px; - } - - .llms-quiz-attempt-answer-section { - border-top: 2px solid rgba( #fff, 0.5 ); - margin-top: 20px; - padding-top: 20px; - &:first-child { - border-top: none; - margin-top: 0; - padding-top: 0; - } - } - - } - - &.type--picture_choice, - &.type--picture_reorder { - ul.llms-quiz-attempt-answers { - list-style-type: none; - margin: 0; - padding: 0; - - li.llms-quiz-attempt-answer { - display: inline-block; - list-style-type: none; - margin: 0; - padding: 5px; - } - } - } - - } -} diff --git a/assets/scss/_includes/_spinner.scss b/assets/scss/_includes/_spinner.scss deleted file mode 100644 index 2444d3f075..0000000000 --- a/assets/scss/_includes/_spinner.scss +++ /dev/null @@ -1,43 +0,0 @@ -.llms-spinning { - background: rgba( 250, 250, 250, 0.7 ); - bottom: 0; - display: none; - left: 0; - position: absolute; - right: 0; - top: 0; -} - -.llms-spinner { - animation: llms-spinning 1.5s linear infinite; - box-sizing: border-box; - border: 4px solid #313131; - border-radius: 50%; - height: 40px; - left: 50%; - margin-left: -20px; - margin-top: -20px; - position: absolute; - top: 50%; - width: 40px; - - &.small { - border-width: 2px; - height: 20px; - margin-left: -10px; - margin-top: -10px; - width: 20px; - } -} - -@keyframes llms-spinning{ - 0% { - transform: rotate(0deg) - } - 50% { - border-radius: 5%; - } - 100% { - transform: rotate(220deg) - } -} diff --git a/assets/scss/_includes/_tooltip.scss b/assets/scss/_includes/_tooltip.scss deleted file mode 100644 index f4bb4e0e56..0000000000 --- a/assets/scss/_includes/_tooltip.scss +++ /dev/null @@ -1,128 +0,0 @@ -[data-tip], -[data-title-default], -[data-title-active] { - - $bgcolor: #444; - - position: relative; - - &.tip--top-right { - &:before { - bottom: 100%; - left: -10px; - } - &:hover:before { - bottom: calc( 100% + 6px ); - } - &:after { - border-top-color: $bgcolor; - left: 6px; - top: 0; - } - &:hover:after { - top: -6px; - } - } - - - &.tip--top-left { - &:before { - bottom: 100%; - right: -10px; - } - &:hover:before { - bottom: calc( 100% + 6px ); - } - &:after { - border-top-color: $bgcolor; - right: 6px; - top: 0; - } - &:hover:after { - top: -6px; - } - } - - - - &.tip--bottom-left { - &:before { - top: 100%; - right: -10px; - } - &:hover:before { - top: calc( 100% + 6px ); - } - &:after { - border-bottom-color: $bgcolor; - right: 6px; - bottom: 0; - } - &:hover:after { - bottom: -6px; - } - } - - &.tip--bottom-right { - &:before { - top: 100%; - left: -10px; - } - &:hover:before { - top: calc( 100% + 6px ); - } - &:after { - border-bottom-color: $bgcolor; - left: 6px; - bottom: 0; - } - &:hover:after { - bottom: -6px; - } - } - - &:before { - background: $bgcolor; - border-radius: 4px; - color: #fff; - font-size: 13px; - line-height: 1.2; - padding: 8px; - max-width: 300px; - width: max-content; - } - &:after { - content: ''; - border: 6px solid transparent; - height: 0; - width: 0; - } - - &:before, - &:after { - opacity: 0; - transition: all 0.2s 0.1s ease; - position: absolute; - pointer-events: none; - visibility: hidden; - } - &:hover:before, - &:hover:after { - opacity: 1; - transition: all 0.2s 0.6s ease; - visibility: visible; - z-index: 99999999; - } - -} - -[data-tip] { - &:before { - content: attr(data-tip); - } -} -[data-tip].active { - &:before { - content: attr(data-tip-active); - } -} diff --git a/assets/scss/_includes/_vars.scss b/assets/scss/_includes/_vars.scss deleted file mode 100644 index 57eda78b9f..0000000000 --- a/assets/scss/_includes/_vars.scss +++ /dev/null @@ -1,69 +0,0 @@ -// ----- LifterLMS Brand Colors ----- \\ -$color-brand-dark-blue: #243c56; - -$color-brand-blue: #2295ff; -$color-brand-blue-dark: darken( $color-brand-blue, 12 ); // #0077e4 -$color-brand-blue-light: lighten( $color-brand-blue, 8 ); - -$color-brand-orange: #f8954f; -$color-brand-orange-dark: #f67d28; -$color-brand-orange-light: lighten( $color-brand-orange, 8 ); - -$color-brand-aqua: #17bebb; - -$color-brand-pink: #ef476f; - - - -// ----- name our versions of common colors ----- \\ -$color-black: #010101; -$color-green: #83c373; -$color-blue: $color-brand-blue; -$color-red: #e5554e; -$color-white: #fefefe; -$color-aqua: #35bbaa; -$color-purple: #845ef7; -$color-orange: #ff922b; - -$color-red-hover: darken($color-red,5); - - -// ----- state / action names ----- \\ -$color-success: $color-green; -$color-danger: $color-red; - - - - - - - - -$color-lightgrey: #ccc; -$color-grey: #999; -$color-darkgrey: #666; -$color-cinder: #444; -$color-lightblue: #33b1cb; -$color-darkblue: #0185a3; - - - - - - - - - - - - -$color-border: #efefef; - -$el-box-shadow: 0 1px 2px 0 rgba($color-black,0.4); -$el-background: #f1f1f1; -$el-background-hover: #eaeaea; - -$break-xsmall: 320px; -$break-small: 641px; -$break-medium: 768px; -$break-large: 1024px; diff --git a/assets/scss/_includes/vendor/_font-awesome.scss b/assets/scss/_includes/vendor/_font-awesome.scss deleted file mode 100644 index ee906a8196..0000000000 --- a/assets/scss/_includes/vendor/_font-awesome.scss +++ /dev/null @@ -1,2337 +0,0 @@ -/*! - * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */ -/* FONT PATH - * -------------------------- */ -@font-face { - font-family: 'FontAwesome'; - src: url('../fonts/fontawesome-webfont.eot?v=4.7.0'); - src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg'); - font-weight: normal; - font-style: normal; -} -.fa { - display: inline-block; - font: normal normal normal 14px/1 FontAwesome; - font-size: inherit; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -/* makes the font 33% larger relative to the icon container */ -.fa-lg { - font-size: 1.33333333em; - line-height: 0.75em; - vertical-align: -15%; -} -.fa-2x { - font-size: 2em; -} -.fa-3x { - font-size: 3em; -} -.fa-4x { - font-size: 4em; -} -.fa-5x { - font-size: 5em; -} -.fa-fw { - width: 1.28571429em; - text-align: center; -} -.fa-ul { - padding-left: 0; - margin-left: 2.14285714em; - list-style-type: none; -} -.fa-ul > li { - position: relative; -} -.fa-li { - position: absolute; - left: -2.14285714em; - width: 2.14285714em; - top: 0.14285714em; - text-align: center; -} -.fa-li.fa-lg { - left: -1.85714286em; -} -.fa-border { - padding: .2em .25em .15em; - border: solid 0.08em #eeeeee; - border-radius: .1em; -} -.fa-pull-left { - float: left; -} -.fa-pull-right { - float: right; -} -.fa.fa-pull-left { - margin-right: .3em; -} -.fa.fa-pull-right { - margin-left: .3em; -} -/* Deprecated as of 4.4.0 */ -.pull-right { - float: right; -} -.pull-left { - float: left; -} -.fa.pull-left { - margin-right: .3em; -} -.fa.pull-right { - margin-left: .3em; -} -.fa-spin { - -webkit-animation: fa-spin 2s infinite linear; - animation: fa-spin 2s infinite linear; -} -.fa-pulse { - -webkit-animation: fa-spin 1s infinite steps(8); - animation: fa-spin 1s infinite steps(8); -} -@-webkit-keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -@keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -.fa-rotate-90 { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; - -webkit-transform: rotate(90deg); - -ms-transform: rotate(90deg); - transform: rotate(90deg); -} -.fa-rotate-180 { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)"; - -webkit-transform: rotate(180deg); - -ms-transform: rotate(180deg); - transform: rotate(180deg); -} -.fa-rotate-270 { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"; - -webkit-transform: rotate(270deg); - -ms-transform: rotate(270deg); - transform: rotate(270deg); -} -.fa-flip-horizontal { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)"; - -webkit-transform: scale(-1, 1); - -ms-transform: scale(-1, 1); - transform: scale(-1, 1); -} -.fa-flip-vertical { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; - -webkit-transform: scale(1, -1); - -ms-transform: scale(1, -1); - transform: scale(1, -1); -} -:root .fa-rotate-90, -:root .fa-rotate-180, -:root .fa-rotate-270, -:root .fa-flip-horizontal, -:root .fa-flip-vertical { - filter: none; -} -.fa-stack { - position: relative; - display: inline-block; - width: 2em; - height: 2em; - line-height: 2em; - vertical-align: middle; -} -.fa-stack-1x, -.fa-stack-2x { - position: absolute; - left: 0; - width: 100%; - text-align: center; -} -.fa-stack-1x { - line-height: inherit; -} -.fa-stack-2x { - font-size: 2em; -} -.fa-inverse { - color: #ffffff; -} -/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen - readers do not read off random characters that represent icons */ -.fa-glass:before { - content: "\f000"; -} -.fa-music:before { - content: "\f001"; -} -.fa-search:before { - content: "\f002"; -} -.fa-envelope-o:before { - content: "\f003"; -} -.fa-heart:before { - content: "\f004"; -} -.fa-star:before { - content: "\f005"; -} -.fa-star-o:before { - content: "\f006"; -} -.fa-user:before { - content: "\f007"; -} -.fa-film:before { - content: "\f008"; -} -.fa-th-large:before { - content: "\f009"; -} -.fa-th:before { - content: "\f00a"; -} -.fa-th-list:before { - content: "\f00b"; -} -.fa-check:before { - content: "\f00c"; -} -.fa-remove:before, -.fa-close:before, -.fa-times:before { - content: "\f00d"; -} -.fa-search-plus:before { - content: "\f00e"; -} -.fa-search-minus:before { - content: "\f010"; -} -.fa-power-off:before { - content: "\f011"; -} -.fa-signal:before { - content: "\f012"; -} -.fa-gear:before, -.fa-cog:before { - content: "\f013"; -} -.fa-trash-o:before { - content: "\f014"; -} -.fa-home:before { - content: "\f015"; -} -.fa-file-o:before { - content: "\f016"; -} -.fa-clock-o:before { - content: "\f017"; -} -.fa-road:before { - content: "\f018"; -} -.fa-download:before { - content: "\f019"; -} -.fa-arrow-circle-o-down:before { - content: "\f01a"; -} -.fa-arrow-circle-o-up:before { - content: "\f01b"; -} -.fa-inbox:before { - content: "\f01c"; -} -.fa-play-circle-o:before { - content: "\f01d"; -} -.fa-rotate-right:before, -.fa-repeat:before { - content: "\f01e"; -} -.fa-refresh:before { - content: "\f021"; -} -.fa-list-alt:before { - content: "\f022"; -} -.fa-lock:before { - content: "\f023"; -} -.fa-flag:before { - content: "\f024"; -} -.fa-headphones:before { - content: "\f025"; -} -.fa-volume-off:before { - content: "\f026"; -} -.fa-volume-down:before { - content: "\f027"; -} -.fa-volume-up:before { - content: "\f028"; -} -.fa-qrcode:before { - content: "\f029"; -} -.fa-barcode:before { - content: "\f02a"; -} -.fa-tag:before { - content: "\f02b"; -} -.fa-tags:before { - content: "\f02c"; -} -.fa-book:before { - content: "\f02d"; -} -.fa-bookmark:before { - content: "\f02e"; -} -.fa-print:before { - content: "\f02f"; -} -.fa-camera:before { - content: "\f030"; -} -.fa-font:before { - content: "\f031"; -} -.fa-bold:before { - content: "\f032"; -} -.fa-italic:before { - content: "\f033"; -} -.fa-text-height:before { - content: "\f034"; -} -.fa-text-width:before { - content: "\f035"; -} -.fa-align-left:before { - content: "\f036"; -} -.fa-align-center:before { - content: "\f037"; -} -.fa-align-right:before { - content: "\f038"; -} -.fa-align-justify:before { - content: "\f039"; -} -.fa-list:before { - content: "\f03a"; -} -.fa-dedent:before, -.fa-outdent:before { - content: "\f03b"; -} -.fa-indent:before { - content: "\f03c"; -} -.fa-video-camera:before { - content: "\f03d"; -} -.fa-photo:before, -.fa-image:before, -.fa-picture-o:before { - content: "\f03e"; -} -.fa-pencil:before { - content: "\f040"; -} -.fa-map-marker:before { - content: "\f041"; -} -.fa-adjust:before { - content: "\f042"; -} -.fa-tint:before { - content: "\f043"; -} -.fa-edit:before, -.fa-pencil-square-o:before { - content: "\f044"; -} -.fa-share-square-o:before { - content: "\f045"; -} -.fa-check-square-o:before { - content: "\f046"; -} -.fa-arrows:before { - content: "\f047"; -} -.fa-step-backward:before { - content: "\f048"; -} -.fa-fast-backward:before { - content: "\f049"; -} -.fa-backward:before { - content: "\f04a"; -} -.fa-play:before { - content: "\f04b"; -} -.fa-pause:before { - content: "\f04c"; -} -.fa-stop:before { - content: "\f04d"; -} -.fa-forward:before { - content: "\f04e"; -} -.fa-fast-forward:before { - content: "\f050"; -} -.fa-step-forward:before { - content: "\f051"; -} -.fa-eject:before { - content: "\f052"; -} -.fa-chevron-left:before { - content: "\f053"; -} -.fa-chevron-right:before { - content: "\f054"; -} -.fa-plus-circle:before { - content: "\f055"; -} -.fa-minus-circle:before { - content: "\f056"; -} -.fa-times-circle:before { - content: "\f057"; -} -.fa-check-circle:before { - content: "\f058"; -} -.fa-question-circle:before { - content: "\f059"; -} -.fa-info-circle:before { - content: "\f05a"; -} -.fa-crosshairs:before { - content: "\f05b"; -} -.fa-times-circle-o:before { - content: "\f05c"; -} -.fa-check-circle-o:before { - content: "\f05d"; -} -.fa-ban:before { - content: "\f05e"; -} -.fa-arrow-left:before { - content: "\f060"; -} -.fa-arrow-right:before { - content: "\f061"; -} -.fa-arrow-up:before { - content: "\f062"; -} -.fa-arrow-down:before { - content: "\f063"; -} -.fa-mail-forward:before, -.fa-share:before { - content: "\f064"; -} -.fa-expand:before { - content: "\f065"; -} -.fa-compress:before { - content: "\f066"; -} -.fa-plus:before { - content: "\f067"; -} -.fa-minus:before { - content: "\f068"; -} -.fa-asterisk:before { - content: "\f069"; -} -.fa-exclamation-circle:before { - content: "\f06a"; -} -.fa-gift:before { - content: "\f06b"; -} -.fa-leaf:before { - content: "\f06c"; -} -.fa-fire:before { - content: "\f06d"; -} -.fa-eye:before { - content: "\f06e"; -} -.fa-eye-slash:before { - content: "\f070"; -} -.fa-warning:before, -.fa-exclamation-triangle:before { - content: "\f071"; -} -.fa-plane:before { - content: "\f072"; -} -.fa-calendar:before { - content: "\f073"; -} -.fa-random:before { - content: "\f074"; -} -.fa-comment:before { - content: "\f075"; -} -.fa-magnet:before { - content: "\f076"; -} -.fa-chevron-up:before { - content: "\f077"; -} -.fa-chevron-down:before { - content: "\f078"; -} -.fa-retweet:before { - content: "\f079"; -} -.fa-shopping-cart:before { - content: "\f07a"; -} -.fa-folder:before { - content: "\f07b"; -} -.fa-folder-open:before { - content: "\f07c"; -} -.fa-arrows-v:before { - content: "\f07d"; -} -.fa-arrows-h:before { - content: "\f07e"; -} -.fa-bar-chart-o:before, -.fa-bar-chart:before { - content: "\f080"; -} -.fa-twitter-square:before { - content: "\f081"; -} -.fa-facebook-square:before { - content: "\f082"; -} -.fa-camera-retro:before { - content: "\f083"; -} -.fa-key:before { - content: "\f084"; -} -.fa-gears:before, -.fa-cogs:before { - content: "\f085"; -} -.fa-comments:before { - content: "\f086"; -} -.fa-thumbs-o-up:before { - content: "\f087"; -} -.fa-thumbs-o-down:before { - content: "\f088"; -} -.fa-star-half:before { - content: "\f089"; -} -.fa-heart-o:before { - content: "\f08a"; -} -.fa-sign-out:before { - content: "\f08b"; -} -.fa-linkedin-square:before { - content: "\f08c"; -} -.fa-thumb-tack:before { - content: "\f08d"; -} -.fa-external-link:before { - content: "\f08e"; -} -.fa-sign-in:before { - content: "\f090"; -} -.fa-trophy:before { - content: "\f091"; -} -.fa-github-square:before { - content: "\f092"; -} -.fa-upload:before { - content: "\f093"; -} -.fa-lemon-o:before { - content: "\f094"; -} -.fa-phone:before { - content: "\f095"; -} -.fa-square-o:before { - content: "\f096"; -} -.fa-bookmark-o:before { - content: "\f097"; -} -.fa-phone-square:before { - content: "\f098"; -} -.fa-twitter:before { - content: "\f099"; -} -.fa-facebook-f:before, -.fa-facebook:before { - content: "\f09a"; -} -.fa-github:before { - content: "\f09b"; -} -.fa-unlock:before { - content: "\f09c"; -} -.fa-credit-card:before { - content: "\f09d"; -} -.fa-feed:before, -.fa-rss:before { - content: "\f09e"; -} -.fa-hdd-o:before { - content: "\f0a0"; -} -.fa-bullhorn:before { - content: "\f0a1"; -} -.fa-bell:before { - content: "\f0f3"; -} -.fa-certificate:before { - content: "\f0a3"; -} -.fa-hand-o-right:before { - content: "\f0a4"; -} -.fa-hand-o-left:before { - content: "\f0a5"; -} -.fa-hand-o-up:before { - content: "\f0a6"; -} -.fa-hand-o-down:before { - content: "\f0a7"; -} -.fa-arrow-circle-left:before { - content: "\f0a8"; -} -.fa-arrow-circle-right:before { - content: "\f0a9"; -} -.fa-arrow-circle-up:before { - content: "\f0aa"; -} -.fa-arrow-circle-down:before { - content: "\f0ab"; -} -.fa-globe:before { - content: "\f0ac"; -} -.fa-wrench:before { - content: "\f0ad"; -} -.fa-tasks:before { - content: "\f0ae"; -} -.fa-filter:before { - content: "\f0b0"; -} -.fa-briefcase:before { - content: "\f0b1"; -} -.fa-arrows-alt:before { - content: "\f0b2"; -} -.fa-group:before, -.fa-users:before { - content: "\f0c0"; -} -.fa-chain:before, -.fa-link:before { - content: "\f0c1"; -} -.fa-cloud:before { - content: "\f0c2"; -} -.fa-flask:before { - content: "\f0c3"; -} -.fa-cut:before, -.fa-scissors:before { - content: "\f0c4"; -} -.fa-copy:before, -.fa-files-o:before { - content: "\f0c5"; -} -.fa-paperclip:before { - content: "\f0c6"; -} -.fa-save:before, -.fa-floppy-o:before { - content: "\f0c7"; -} -.fa-square:before { - content: "\f0c8"; -} -.fa-navicon:before, -.fa-reorder:before, -.fa-bars:before { - content: "\f0c9"; -} -.fa-list-ul:before { - content: "\f0ca"; -} -.fa-list-ol:before { - content: "\f0cb"; -} -.fa-strikethrough:before { - content: "\f0cc"; -} -.fa-underline:before { - content: "\f0cd"; -} -.fa-table:before { - content: "\f0ce"; -} -.fa-magic:before { - content: "\f0d0"; -} -.fa-truck:before { - content: "\f0d1"; -} -.fa-pinterest:before { - content: "\f0d2"; -} -.fa-pinterest-square:before { - content: "\f0d3"; -} -.fa-google-plus-square:before { - content: "\f0d4"; -} -.fa-google-plus:before { - content: "\f0d5"; -} -.fa-money:before { - content: "\f0d6"; -} -.fa-caret-down:before { - content: "\f0d7"; -} -.fa-caret-up:before { - content: "\f0d8"; -} -.fa-caret-left:before { - content: "\f0d9"; -} -.fa-caret-right:before { - content: "\f0da"; -} -.fa-columns:before { - content: "\f0db"; -} -.fa-unsorted:before, -.fa-sort:before { - content: "\f0dc"; -} -.fa-sort-down:before, -.fa-sort-desc:before { - content: "\f0dd"; -} -.fa-sort-up:before, -.fa-sort-asc:before { - content: "\f0de"; -} -.fa-envelope:before { - content: "\f0e0"; -} -.fa-linkedin:before { - content: "\f0e1"; -} -.fa-rotate-left:before, -.fa-undo:before { - content: "\f0e2"; -} -.fa-legal:before, -.fa-gavel:before { - content: "\f0e3"; -} -.fa-dashboard:before, -.fa-tachometer:before { - content: "\f0e4"; -} -.fa-comment-o:before { - content: "\f0e5"; -} -.fa-comments-o:before { - content: "\f0e6"; -} -.fa-flash:before, -.fa-bolt:before { - content: "\f0e7"; -} -.fa-sitemap:before { - content: "\f0e8"; -} -.fa-umbrella:before { - content: "\f0e9"; -} -.fa-paste:before, -.fa-clipboard:before { - content: "\f0ea"; -} -.fa-lightbulb-o:before { - content: "\f0eb"; -} -.fa-exchange:before { - content: "\f0ec"; -} -.fa-cloud-download:before { - content: "\f0ed"; -} -.fa-cloud-upload:before { - content: "\f0ee"; -} -.fa-user-md:before { - content: "\f0f0"; -} -.fa-stethoscope:before { - content: "\f0f1"; -} -.fa-suitcase:before { - content: "\f0f2"; -} -.fa-bell-o:before { - content: "\f0a2"; -} -.fa-coffee:before { - content: "\f0f4"; -} -.fa-cutlery:before { - content: "\f0f5"; -} -.fa-file-text-o:before { - content: "\f0f6"; -} -.fa-building-o:before { - content: "\f0f7"; -} -.fa-hospital-o:before { - content: "\f0f8"; -} -.fa-ambulance:before { - content: "\f0f9"; -} -.fa-medkit:before { - content: "\f0fa"; -} -.fa-fighter-jet:before { - content: "\f0fb"; -} -.fa-beer:before { - content: "\f0fc"; -} -.fa-h-square:before { - content: "\f0fd"; -} -.fa-plus-square:before { - content: "\f0fe"; -} -.fa-angle-double-left:before { - content: "\f100"; -} -.fa-angle-double-right:before { - content: "\f101"; -} -.fa-angle-double-up:before { - content: "\f102"; -} -.fa-angle-double-down:before { - content: "\f103"; -} -.fa-angle-left:before { - content: "\f104"; -} -.fa-angle-right:before { - content: "\f105"; -} -.fa-angle-up:before { - content: "\f106"; -} -.fa-angle-down:before { - content: "\f107"; -} -.fa-desktop:before { - content: "\f108"; -} -.fa-laptop:before { - content: "\f109"; -} -.fa-tablet:before { - content: "\f10a"; -} -.fa-mobile-phone:before, -.fa-mobile:before { - content: "\f10b"; -} -.fa-circle-o:before { - content: "\f10c"; -} -.fa-quote-left:before { - content: "\f10d"; -} -.fa-quote-right:before { - content: "\f10e"; -} -.fa-spinner:before { - content: "\f110"; -} -.fa-circle:before { - content: "\f111"; -} -.fa-mail-reply:before, -.fa-reply:before { - content: "\f112"; -} -.fa-github-alt:before { - content: "\f113"; -} -.fa-folder-o:before { - content: "\f114"; -} -.fa-folder-open-o:before { - content: "\f115"; -} -.fa-smile-o:before { - content: "\f118"; -} -.fa-frown-o:before { - content: "\f119"; -} -.fa-meh-o:before { - content: "\f11a"; -} -.fa-gamepad:before { - content: "\f11b"; -} -.fa-keyboard-o:before { - content: "\f11c"; -} -.fa-flag-o:before { - content: "\f11d"; -} -.fa-flag-checkered:before { - content: "\f11e"; -} -.fa-terminal:before { - content: "\f120"; -} -.fa-code:before { - content: "\f121"; -} -.fa-mail-reply-all:before, -.fa-reply-all:before { - content: "\f122"; -} -.fa-star-half-empty:before, -.fa-star-half-full:before, -.fa-star-half-o:before { - content: "\f123"; -} -.fa-location-arrow:before { - content: "\f124"; -} -.fa-crop:before { - content: "\f125"; -} -.fa-code-fork:before { - content: "\f126"; -} -.fa-unlink:before, -.fa-chain-broken:before { - content: "\f127"; -} -.fa-question:before { - content: "\f128"; -} -.fa-info:before { - content: "\f129"; -} -.fa-exclamation:before { - content: "\f12a"; -} -.fa-superscript:before { - content: "\f12b"; -} -.fa-subscript:before { - content: "\f12c"; -} -.fa-eraser:before { - content: "\f12d"; -} -.fa-puzzle-piece:before { - content: "\f12e"; -} -.fa-microphone:before { - content: "\f130"; -} -.fa-microphone-slash:before { - content: "\f131"; -} -.fa-shield:before { - content: "\f132"; -} -.fa-calendar-o:before { - content: "\f133"; -} -.fa-fire-extinguisher:before { - content: "\f134"; -} -.fa-rocket:before { - content: "\f135"; -} -.fa-maxcdn:before { - content: "\f136"; -} -.fa-chevron-circle-left:before { - content: "\f137"; -} -.fa-chevron-circle-right:before { - content: "\f138"; -} -.fa-chevron-circle-up:before { - content: "\f139"; -} -.fa-chevron-circle-down:before { - content: "\f13a"; -} -.fa-html5:before { - content: "\f13b"; -} -.fa-css3:before { - content: "\f13c"; -} -.fa-anchor:before { - content: "\f13d"; -} -.fa-unlock-alt:before { - content: "\f13e"; -} -.fa-bullseye:before { - content: "\f140"; -} -.fa-ellipsis-h:before { - content: "\f141"; -} -.fa-ellipsis-v:before { - content: "\f142"; -} -.fa-rss-square:before { - content: "\f143"; -} -.fa-play-circle:before { - content: "\f144"; -} -.fa-ticket:before { - content: "\f145"; -} -.fa-minus-square:before { - content: "\f146"; -} -.fa-minus-square-o:before { - content: "\f147"; -} -.fa-level-up:before { - content: "\f148"; -} -.fa-level-down:before { - content: "\f149"; -} -.fa-check-square:before { - content: "\f14a"; -} -.fa-pencil-square:before { - content: "\f14b"; -} -.fa-external-link-square:before { - content: "\f14c"; -} -.fa-share-square:before { - content: "\f14d"; -} -.fa-compass:before { - content: "\f14e"; -} -.fa-toggle-down:before, -.fa-caret-square-o-down:before { - content: "\f150"; -} -.fa-toggle-up:before, -.fa-caret-square-o-up:before { - content: "\f151"; -} -.fa-toggle-right:before, -.fa-caret-square-o-right:before { - content: "\f152"; -} -.fa-euro:before, -.fa-eur:before { - content: "\f153"; -} -.fa-gbp:before { - content: "\f154"; -} -.fa-dollar:before, -.fa-usd:before { - content: "\f155"; -} -.fa-rupee:before, -.fa-inr:before { - content: "\f156"; -} -.fa-cny:before, -.fa-rmb:before, -.fa-yen:before, -.fa-jpy:before { - content: "\f157"; -} -.fa-ruble:before, -.fa-rouble:before, -.fa-rub:before { - content: "\f158"; -} -.fa-won:before, -.fa-krw:before { - content: "\f159"; -} -.fa-bitcoin:before, -.fa-btc:before { - content: "\f15a"; -} -.fa-file:before { - content: "\f15b"; -} -.fa-file-text:before { - content: "\f15c"; -} -.fa-sort-alpha-asc:before { - content: "\f15d"; -} -.fa-sort-alpha-desc:before { - content: "\f15e"; -} -.fa-sort-amount-asc:before { - content: "\f160"; -} -.fa-sort-amount-desc:before { - content: "\f161"; -} -.fa-sort-numeric-asc:before { - content: "\f162"; -} -.fa-sort-numeric-desc:before { - content: "\f163"; -} -.fa-thumbs-up:before { - content: "\f164"; -} -.fa-thumbs-down:before { - content: "\f165"; -} -.fa-youtube-square:before { - content: "\f166"; -} -.fa-youtube:before { - content: "\f167"; -} -.fa-xing:before { - content: "\f168"; -} -.fa-xing-square:before { - content: "\f169"; -} -.fa-youtube-play:before { - content: "\f16a"; -} -.fa-dropbox:before { - content: "\f16b"; -} -.fa-stack-overflow:before { - content: "\f16c"; -} -.fa-instagram:before { - content: "\f16d"; -} -.fa-flickr:before { - content: "\f16e"; -} -.fa-adn:before { - content: "\f170"; -} -.fa-bitbucket:before { - content: "\f171"; -} -.fa-bitbucket-square:before { - content: "\f172"; -} -.fa-tumblr:before { - content: "\f173"; -} -.fa-tumblr-square:before { - content: "\f174"; -} -.fa-long-arrow-down:before { - content: "\f175"; -} -.fa-long-arrow-up:before { - content: "\f176"; -} -.fa-long-arrow-left:before { - content: "\f177"; -} -.fa-long-arrow-right:before { - content: "\f178"; -} -.fa-apple:before { - content: "\f179"; -} -.fa-windows:before { - content: "\f17a"; -} -.fa-android:before { - content: "\f17b"; -} -.fa-linux:before { - content: "\f17c"; -} -.fa-dribbble:before { - content: "\f17d"; -} -.fa-skype:before { - content: "\f17e"; -} -.fa-foursquare:before { - content: "\f180"; -} -.fa-trello:before { - content: "\f181"; -} -.fa-female:before { - content: "\f182"; -} -.fa-male:before { - content: "\f183"; -} -.fa-gittip:before, -.fa-gratipay:before { - content: "\f184"; -} -.fa-sun-o:before { - content: "\f185"; -} -.fa-moon-o:before { - content: "\f186"; -} -.fa-archive:before { - content: "\f187"; -} -.fa-bug:before { - content: "\f188"; -} -.fa-vk:before { - content: "\f189"; -} -.fa-weibo:before { - content: "\f18a"; -} -.fa-renren:before { - content: "\f18b"; -} -.fa-pagelines:before { - content: "\f18c"; -} -.fa-stack-exchange:before { - content: "\f18d"; -} -.fa-arrow-circle-o-right:before { - content: "\f18e"; -} -.fa-arrow-circle-o-left:before { - content: "\f190"; -} -.fa-toggle-left:before, -.fa-caret-square-o-left:before { - content: "\f191"; -} -.fa-dot-circle-o:before { - content: "\f192"; -} -.fa-wheelchair:before { - content: "\f193"; -} -.fa-vimeo-square:before { - content: "\f194"; -} -.fa-turkish-lira:before, -.fa-try:before { - content: "\f195"; -} -.fa-plus-square-o:before { - content: "\f196"; -} -.fa-space-shuttle:before { - content: "\f197"; -} -.fa-slack:before { - content: "\f198"; -} -.fa-envelope-square:before { - content: "\f199"; -} -.fa-wordpress:before { - content: "\f19a"; -} -.fa-openid:before { - content: "\f19b"; -} -.fa-institution:before, -.fa-bank:before, -.fa-university:before { - content: "\f19c"; -} -.fa-mortar-board:before, -.fa-graduation-cap:before { - content: "\f19d"; -} -.fa-yahoo:before { - content: "\f19e"; -} -.fa-google:before { - content: "\f1a0"; -} -.fa-reddit:before { - content: "\f1a1"; -} -.fa-reddit-square:before { - content: "\f1a2"; -} -.fa-stumbleupon-circle:before { - content: "\f1a3"; -} -.fa-stumbleupon:before { - content: "\f1a4"; -} -.fa-delicious:before { - content: "\f1a5"; -} -.fa-digg:before { - content: "\f1a6"; -} -.fa-pied-piper-pp:before { - content: "\f1a7"; -} -.fa-pied-piper-alt:before { - content: "\f1a8"; -} -.fa-drupal:before { - content: "\f1a9"; -} -.fa-joomla:before { - content: "\f1aa"; -} -.fa-language:before { - content: "\f1ab"; -} -.fa-fax:before { - content: "\f1ac"; -} -.fa-building:before { - content: "\f1ad"; -} -.fa-child:before { - content: "\f1ae"; -} -.fa-paw:before { - content: "\f1b0"; -} -.fa-spoon:before { - content: "\f1b1"; -} -.fa-cube:before { - content: "\f1b2"; -} -.fa-cubes:before { - content: "\f1b3"; -} -.fa-behance:before { - content: "\f1b4"; -} -.fa-behance-square:before { - content: "\f1b5"; -} -.fa-steam:before { - content: "\f1b6"; -} -.fa-steam-square:before { - content: "\f1b7"; -} -.fa-recycle:before { - content: "\f1b8"; -} -.fa-automobile:before, -.fa-car:before { - content: "\f1b9"; -} -.fa-cab:before, -.fa-taxi:before { - content: "\f1ba"; -} -.fa-tree:before { - content: "\f1bb"; -} -.fa-spotify:before { - content: "\f1bc"; -} -.fa-deviantart:before { - content: "\f1bd"; -} -.fa-soundcloud:before { - content: "\f1be"; -} -.fa-database:before { - content: "\f1c0"; -} -.fa-file-pdf-o:before { - content: "\f1c1"; -} -.fa-file-word-o:before { - content: "\f1c2"; -} -.fa-file-excel-o:before { - content: "\f1c3"; -} -.fa-file-powerpoint-o:before { - content: "\f1c4"; -} -.fa-file-photo-o:before, -.fa-file-picture-o:before, -.fa-file-image-o:before { - content: "\f1c5"; -} -.fa-file-zip-o:before, -.fa-file-archive-o:before { - content: "\f1c6"; -} -.fa-file-sound-o:before, -.fa-file-audio-o:before { - content: "\f1c7"; -} -.fa-file-movie-o:before, -.fa-file-video-o:before { - content: "\f1c8"; -} -.fa-file-code-o:before { - content: "\f1c9"; -} -.fa-vine:before { - content: "\f1ca"; -} -.fa-codepen:before { - content: "\f1cb"; -} -.fa-jsfiddle:before { - content: "\f1cc"; -} -.fa-life-bouy:before, -.fa-life-buoy:before, -.fa-life-saver:before, -.fa-support:before, -.fa-life-ring:before { - content: "\f1cd"; -} -.fa-circle-o-notch:before { - content: "\f1ce"; -} -.fa-ra:before, -.fa-resistance:before, -.fa-rebel:before { - content: "\f1d0"; -} -.fa-ge:before, -.fa-empire:before { - content: "\f1d1"; -} -.fa-git-square:before { - content: "\f1d2"; -} -.fa-git:before { - content: "\f1d3"; -} -.fa-y-combinator-square:before, -.fa-yc-square:before, -.fa-hacker-news:before { - content: "\f1d4"; -} -.fa-tencent-weibo:before { - content: "\f1d5"; -} -.fa-qq:before { - content: "\f1d6"; -} -.fa-wechat:before, -.fa-weixin:before { - content: "\f1d7"; -} -.fa-send:before, -.fa-paper-plane:before { - content: "\f1d8"; -} -.fa-send-o:before, -.fa-paper-plane-o:before { - content: "\f1d9"; -} -.fa-history:before { - content: "\f1da"; -} -.fa-circle-thin:before { - content: "\f1db"; -} -.fa-header:before { - content: "\f1dc"; -} -.fa-paragraph:before { - content: "\f1dd"; -} -.fa-sliders:before { - content: "\f1de"; -} -.fa-share-alt:before { - content: "\f1e0"; -} -.fa-share-alt-square:before { - content: "\f1e1"; -} -.fa-bomb:before { - content: "\f1e2"; -} -.fa-soccer-ball-o:before, -.fa-futbol-o:before { - content: "\f1e3"; -} -.fa-tty:before { - content: "\f1e4"; -} -.fa-binoculars:before { - content: "\f1e5"; -} -.fa-plug:before { - content: "\f1e6"; -} -.fa-slideshare:before { - content: "\f1e7"; -} -.fa-twitch:before { - content: "\f1e8"; -} -.fa-yelp:before { - content: "\f1e9"; -} -.fa-newspaper-o:before { - content: "\f1ea"; -} -.fa-wifi:before { - content: "\f1eb"; -} -.fa-calculator:before { - content: "\f1ec"; -} -.fa-paypal:before { - content: "\f1ed"; -} -.fa-google-wallet:before { - content: "\f1ee"; -} -.fa-cc-visa:before { - content: "\f1f0"; -} -.fa-cc-mastercard:before { - content: "\f1f1"; -} -.fa-cc-discover:before { - content: "\f1f2"; -} -.fa-cc-amex:before { - content: "\f1f3"; -} -.fa-cc-paypal:before { - content: "\f1f4"; -} -.fa-cc-stripe:before { - content: "\f1f5"; -} -.fa-bell-slash:before { - content: "\f1f6"; -} -.fa-bell-slash-o:before { - content: "\f1f7"; -} -.fa-trash:before { - content: "\f1f8"; -} -.fa-copyright:before { - content: "\f1f9"; -} -.fa-at:before { - content: "\f1fa"; -} -.fa-eyedropper:before { - content: "\f1fb"; -} -.fa-paint-brush:before { - content: "\f1fc"; -} -.fa-birthday-cake:before { - content: "\f1fd"; -} -.fa-area-chart:before { - content: "\f1fe"; -} -.fa-pie-chart:before { - content: "\f200"; -} -.fa-line-chart:before { - content: "\f201"; -} -.fa-lastfm:before { - content: "\f202"; -} -.fa-lastfm-square:before { - content: "\f203"; -} -.fa-toggle-off:before { - content: "\f204"; -} -.fa-toggle-on:before { - content: "\f205"; -} -.fa-bicycle:before { - content: "\f206"; -} -.fa-bus:before { - content: "\f207"; -} -.fa-ioxhost:before { - content: "\f208"; -} -.fa-angellist:before { - content: "\f209"; -} -.fa-cc:before { - content: "\f20a"; -} -.fa-shekel:before, -.fa-sheqel:before, -.fa-ils:before { - content: "\f20b"; -} -.fa-meanpath:before { - content: "\f20c"; -} -.fa-buysellads:before { - content: "\f20d"; -} -.fa-connectdevelop:before { - content: "\f20e"; -} -.fa-dashcube:before { - content: "\f210"; -} -.fa-forumbee:before { - content: "\f211"; -} -.fa-leanpub:before { - content: "\f212"; -} -.fa-sellsy:before { - content: "\f213"; -} -.fa-shirtsinbulk:before { - content: "\f214"; -} -.fa-simplybuilt:before { - content: "\f215"; -} -.fa-skyatlas:before { - content: "\f216"; -} -.fa-cart-plus:before { - content: "\f217"; -} -.fa-cart-arrow-down:before { - content: "\f218"; -} -.fa-diamond:before { - content: "\f219"; -} -.fa-ship:before { - content: "\f21a"; -} -.fa-user-secret:before { - content: "\f21b"; -} -.fa-motorcycle:before { - content: "\f21c"; -} -.fa-street-view:before { - content: "\f21d"; -} -.fa-heartbeat:before { - content: "\f21e"; -} -.fa-venus:before { - content: "\f221"; -} -.fa-mars:before { - content: "\f222"; -} -.fa-mercury:before { - content: "\f223"; -} -.fa-intersex:before, -.fa-transgender:before { - content: "\f224"; -} -.fa-transgender-alt:before { - content: "\f225"; -} -.fa-venus-double:before { - content: "\f226"; -} -.fa-mars-double:before { - content: "\f227"; -} -.fa-venus-mars:before { - content: "\f228"; -} -.fa-mars-stroke:before { - content: "\f229"; -} -.fa-mars-stroke-v:before { - content: "\f22a"; -} -.fa-mars-stroke-h:before { - content: "\f22b"; -} -.fa-neuter:before { - content: "\f22c"; -} -.fa-genderless:before { - content: "\f22d"; -} -.fa-facebook-official:before { - content: "\f230"; -} -.fa-pinterest-p:before { - content: "\f231"; -} -.fa-whatsapp:before { - content: "\f232"; -} -.fa-server:before { - content: "\f233"; -} -.fa-user-plus:before { - content: "\f234"; -} -.fa-user-times:before { - content: "\f235"; -} -.fa-hotel:before, -.fa-bed:before { - content: "\f236"; -} -.fa-viacoin:before { - content: "\f237"; -} -.fa-train:before { - content: "\f238"; -} -.fa-subway:before { - content: "\f239"; -} -.fa-medium:before { - content: "\f23a"; -} -.fa-yc:before, -.fa-y-combinator:before { - content: "\f23b"; -} -.fa-optin-monster:before { - content: "\f23c"; -} -.fa-opencart:before { - content: "\f23d"; -} -.fa-expeditedssl:before { - content: "\f23e"; -} -.fa-battery-4:before, -.fa-battery:before, -.fa-battery-full:before { - content: "\f240"; -} -.fa-battery-3:before, -.fa-battery-three-quarters:before { - content: "\f241"; -} -.fa-battery-2:before, -.fa-battery-half:before { - content: "\f242"; -} -.fa-battery-1:before, -.fa-battery-quarter:before { - content: "\f243"; -} -.fa-battery-0:before, -.fa-battery-empty:before { - content: "\f244"; -} -.fa-mouse-pointer:before { - content: "\f245"; -} -.fa-i-cursor:before { - content: "\f246"; -} -.fa-object-group:before { - content: "\f247"; -} -.fa-object-ungroup:before { - content: "\f248"; -} -.fa-sticky-note:before { - content: "\f249"; -} -.fa-sticky-note-o:before { - content: "\f24a"; -} -.fa-cc-jcb:before { - content: "\f24b"; -} -.fa-cc-diners-club:before { - content: "\f24c"; -} -.fa-clone:before { - content: "\f24d"; -} -.fa-balance-scale:before { - content: "\f24e"; -} -.fa-hourglass-o:before { - content: "\f250"; -} -.fa-hourglass-1:before, -.fa-hourglass-start:before { - content: "\f251"; -} -.fa-hourglass-2:before, -.fa-hourglass-half:before { - content: "\f252"; -} -.fa-hourglass-3:before, -.fa-hourglass-end:before { - content: "\f253"; -} -.fa-hourglass:before { - content: "\f254"; -} -.fa-hand-grab-o:before, -.fa-hand-rock-o:before { - content: "\f255"; -} -.fa-hand-stop-o:before, -.fa-hand-paper-o:before { - content: "\f256"; -} -.fa-hand-scissors-o:before { - content: "\f257"; -} -.fa-hand-lizard-o:before { - content: "\f258"; -} -.fa-hand-spock-o:before { - content: "\f259"; -} -.fa-hand-pointer-o:before { - content: "\f25a"; -} -.fa-hand-peace-o:before { - content: "\f25b"; -} -.fa-trademark:before { - content: "\f25c"; -} -.fa-registered:before { - content: "\f25d"; -} -.fa-creative-commons:before { - content: "\f25e"; -} -.fa-gg:before { - content: "\f260"; -} -.fa-gg-circle:before { - content: "\f261"; -} -.fa-tripadvisor:before { - content: "\f262"; -} -.fa-odnoklassniki:before { - content: "\f263"; -} -.fa-odnoklassniki-square:before { - content: "\f264"; -} -.fa-get-pocket:before { - content: "\f265"; -} -.fa-wikipedia-w:before { - content: "\f266"; -} -.fa-safari:before { - content: "\f267"; -} -.fa-chrome:before { - content: "\f268"; -} -.fa-firefox:before { - content: "\f269"; -} -.fa-opera:before { - content: "\f26a"; -} -.fa-internet-explorer:before { - content: "\f26b"; -} -.fa-tv:before, -.fa-television:before { - content: "\f26c"; -} -.fa-contao:before { - content: "\f26d"; -} -.fa-500px:before { - content: "\f26e"; -} -.fa-amazon:before { - content: "\f270"; -} -.fa-calendar-plus-o:before { - content: "\f271"; -} -.fa-calendar-minus-o:before { - content: "\f272"; -} -.fa-calendar-times-o:before { - content: "\f273"; -} -.fa-calendar-check-o:before { - content: "\f274"; -} -.fa-industry:before { - content: "\f275"; -} -.fa-map-pin:before { - content: "\f276"; -} -.fa-map-signs:before { - content: "\f277"; -} -.fa-map-o:before { - content: "\f278"; -} -.fa-map:before { - content: "\f279"; -} -.fa-commenting:before { - content: "\f27a"; -} -.fa-commenting-o:before { - content: "\f27b"; -} -.fa-houzz:before { - content: "\f27c"; -} -.fa-vimeo:before { - content: "\f27d"; -} -.fa-black-tie:before { - content: "\f27e"; -} -.fa-fonticons:before { - content: "\f280"; -} -.fa-reddit-alien:before { - content: "\f281"; -} -.fa-edge:before { - content: "\f282"; -} -.fa-credit-card-alt:before { - content: "\f283"; -} -.fa-codiepie:before { - content: "\f284"; -} -.fa-modx:before { - content: "\f285"; -} -.fa-fort-awesome:before { - content: "\f286"; -} -.fa-usb:before { - content: "\f287"; -} -.fa-product-hunt:before { - content: "\f288"; -} -.fa-mixcloud:before { - content: "\f289"; -} -.fa-scribd:before { - content: "\f28a"; -} -.fa-pause-circle:before { - content: "\f28b"; -} -.fa-pause-circle-o:before { - content: "\f28c"; -} -.fa-stop-circle:before { - content: "\f28d"; -} -.fa-stop-circle-o:before { - content: "\f28e"; -} -.fa-shopping-bag:before { - content: "\f290"; -} -.fa-shopping-basket:before { - content: "\f291"; -} -.fa-hashtag:before { - content: "\f292"; -} -.fa-bluetooth:before { - content: "\f293"; -} -.fa-bluetooth-b:before { - content: "\f294"; -} -.fa-percent:before { - content: "\f295"; -} -.fa-gitlab:before { - content: "\f296"; -} -.fa-wpbeginner:before { - content: "\f297"; -} -.fa-wpforms:before { - content: "\f298"; -} -.fa-envira:before { - content: "\f299"; -} -.fa-universal-access:before { - content: "\f29a"; -} -.fa-wheelchair-alt:before { - content: "\f29b"; -} -.fa-question-circle-o:before { - content: "\f29c"; -} -.fa-blind:before { - content: "\f29d"; -} -.fa-audio-description:before { - content: "\f29e"; -} -.fa-volume-control-phone:before { - content: "\f2a0"; -} -.fa-braille:before { - content: "\f2a1"; -} -.fa-assistive-listening-systems:before { - content: "\f2a2"; -} -.fa-asl-interpreting:before, -.fa-american-sign-language-interpreting:before { - content: "\f2a3"; -} -.fa-deafness:before, -.fa-hard-of-hearing:before, -.fa-deaf:before { - content: "\f2a4"; -} -.fa-glide:before { - content: "\f2a5"; -} -.fa-glide-g:before { - content: "\f2a6"; -} -.fa-signing:before, -.fa-sign-language:before { - content: "\f2a7"; -} -.fa-low-vision:before { - content: "\f2a8"; -} -.fa-viadeo:before { - content: "\f2a9"; -} -.fa-viadeo-square:before { - content: "\f2aa"; -} -.fa-snapchat:before { - content: "\f2ab"; -} -.fa-snapchat-ghost:before { - content: "\f2ac"; -} -.fa-snapchat-square:before { - content: "\f2ad"; -} -.fa-pied-piper:before { - content: "\f2ae"; -} -.fa-first-order:before { - content: "\f2b0"; -} -.fa-yoast:before { - content: "\f2b1"; -} -.fa-themeisle:before { - content: "\f2b2"; -} -.fa-google-plus-circle:before, -.fa-google-plus-official:before { - content: "\f2b3"; -} -.fa-fa:before, -.fa-font-awesome:before { - content: "\f2b4"; -} -.fa-handshake-o:before { - content: "\f2b5"; -} -.fa-envelope-open:before { - content: "\f2b6"; -} -.fa-envelope-open-o:before { - content: "\f2b7"; -} -.fa-linode:before { - content: "\f2b8"; -} -.fa-address-book:before { - content: "\f2b9"; -} -.fa-address-book-o:before { - content: "\f2ba"; -} -.fa-vcard:before, -.fa-address-card:before { - content: "\f2bb"; -} -.fa-vcard-o:before, -.fa-address-card-o:before { - content: "\f2bc"; -} -.fa-user-circle:before { - content: "\f2bd"; -} -.fa-user-circle-o:before { - content: "\f2be"; -} -.fa-user-o:before { - content: "\f2c0"; -} -.fa-id-badge:before { - content: "\f2c1"; -} -.fa-drivers-license:before, -.fa-id-card:before { - content: "\f2c2"; -} -.fa-drivers-license-o:before, -.fa-id-card-o:before { - content: "\f2c3"; -} -.fa-quora:before { - content: "\f2c4"; -} -.fa-free-code-camp:before { - content: "\f2c5"; -} -.fa-telegram:before { - content: "\f2c6"; -} -.fa-thermometer-4:before, -.fa-thermometer:before, -.fa-thermometer-full:before { - content: "\f2c7"; -} -.fa-thermometer-3:before, -.fa-thermometer-three-quarters:before { - content: "\f2c8"; -} -.fa-thermometer-2:before, -.fa-thermometer-half:before { - content: "\f2c9"; -} -.fa-thermometer-1:before, -.fa-thermometer-quarter:before { - content: "\f2ca"; -} -.fa-thermometer-0:before, -.fa-thermometer-empty:before { - content: "\f2cb"; -} -.fa-shower:before { - content: "\f2cc"; -} -.fa-bathtub:before, -.fa-s15:before, -.fa-bath:before { - content: "\f2cd"; -} -.fa-podcast:before { - content: "\f2ce"; -} -.fa-window-maximize:before { - content: "\f2d0"; -} -.fa-window-minimize:before { - content: "\f2d1"; -} -.fa-window-restore:before { - content: "\f2d2"; -} -.fa-times-rectangle:before, -.fa-window-close:before { - content: "\f2d3"; -} -.fa-times-rectangle-o:before, -.fa-window-close-o:before { - content: "\f2d4"; -} -.fa-bandcamp:before { - content: "\f2d5"; -} -.fa-grav:before { - content: "\f2d6"; -} -.fa-etsy:before { - content: "\f2d7"; -} -.fa-imdb:before { - content: "\f2d8"; -} -.fa-ravelry:before { - content: "\f2d9"; -} -.fa-eercast:before { - content: "\f2da"; -} -.fa-microchip:before { - content: "\f2db"; -} -.fa-snowflake-o:before { - content: "\f2dc"; -} -.fa-superpowers:before { - content: "\f2dd"; -} -.fa-wpexplorer:before { - content: "\f2de"; -} -.fa-meetup:before { - content: "\f2e0"; -} -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - border: 0; -} -.sr-only-focusable:active, -.sr-only-focusable:focus { - position: static; - width: auto; - height: auto; - margin: 0; - overflow: visible; - clip: auto; -} diff --git a/assets/scss/admin-add-ons.scss b/assets/scss/admin-add-ons.scss deleted file mode 100644 index ed6163bcda..0000000000 --- a/assets/scss/admin-add-ons.scss +++ /dev/null @@ -1,70 +0,0 @@ -@import "_includes/vars"; -@import "_includes/mixins"; - -.llms-addons-wrap { - - @include clearfix(); - - .llms-add-on-item { - display: block; - list-style: none; - margin-bottom: 20px; - - @media only screen and ( min-width: 680px ) { - float: left; - margin-right: 20px; - width: 320px; - - .llms-add-on { - height: 320px; - } - } - - } - - .llms-add-on { - - background-color: #f5f5f5; - border: 1px solid #ddd; - box-shadow: inset 0 1px 0 rgba(255,255,255,.2), inset 0 -1px 0 rgba(0,0,0,.1); - color: #444; - display: block; - text-decoration: none; - - &:hover { - background-color: #fff; - } - - header { - margin-bottom: 0; - h4 { - color: #23282d; - font-size: 16px; - margin: 8px 8px 0; - } - img { - display: block; - max-width: 100%; - } - } - - section { - padding: 8px; - p { - margin: 0; - } - } - - footer { - padding: 0 8px 8px; - img { - border-radius: 50%; - display: inline-block; - width: 18px; - vertical-align: bottom; - } - } - - } - -} diff --git a/assets/scss/admin-setup.scss b/assets/scss/admin-setup.scss deleted file mode 100644 index 8fff9018fb..0000000000 --- a/assets/scss/admin-setup.scss +++ /dev/null @@ -1,144 +0,0 @@ -@import "_includes/vars"; - - -#llms-setup-wizard { - - background-color: #f1f1f1; - height: 100%; - left: 0; - overflow: scroll; - position: fixed; - top: 0; - width: 100%; - z-index: 777777; - -} - -.select2-container { - z-index: 7777777; -} - -.llms-setup-wrapper { - margin: 60px auto; - max-width: 640px; -} - -a.dashboard-return { - color: #aaa; - display: block; - margin-top: 10px; - text-align: center; -} - -#llms-logo { - text-align: center; - - img { - max-width: 400px; - } -} - -.llms-setup-content { - background-color: #fff; - box-shadow: 0 1px 3px rgba( 0, 0, 0, .13 ); - padding: 15px 30px; - - h1, h2, h3, h4, h5, h6 { - color: #444; - } - - a:not( .llms-button-primary ):not( .llms-button-secondary ) { - color: $color-brand-blue; - } - - p, li { - color: #666; - font-size: 16px; - } - - p.error { - color: $color-red; - text-align: center; - } - - label { - font-weight: 500; - } - - .llms-setup-actions { - margin-top: 40px; - text-align: right; - } - - .back-link { - margin-right: 10px; - } - - table { - border-bottom: 1px solid #f1f1f1; - border-collapse: collapse; - width: 100%; - } - - - td { - border-top: 1px solid #f1f1f1; - &:first-child { - padding-right: 10px; - width: 33%; - a { - // text-decoration: none; - font-size: 16px; - font-weight: 500; - } - } - } - -} - -.llms-setup-progress { - font-size: 0; - margin: 20px 0; - - li { - border-bottom: 4px solid $color-brand-blue; - color: $color-brand-blue; - display: inline-block; - font-size: 14px; - padding-bottom: 10px; - position: relative; - text-align: center; - width: 20%; - - &:after { - background: $color-brand-blue; - bottom: 0; - content: ''; - border: 4px solid $color-brand-blue; - border-radius: 100%; - height: 4px; - position: absolute; - left: 50%; - margin-left: -6px; - margin-bottom: -8px; - width: 4px; - } - - &.current { - &:after { - background: #fff; - } - } - - &.current ~ li { - border-bottom-color: #ccc; - color: #ccc; - &:after { - background: #ccc; - border-color: #ccc; - } - } - - } -} - diff --git a/assets/scss/admin.scss b/assets/scss/admin.scss deleted file mode 100644 index 3e8c9c3ac9..0000000000 --- a/assets/scss/admin.scss +++ /dev/null @@ -1,88 +0,0 @@ -// -// Main Admin CSS File -// - - -@import "_includes/vars"; -@import "_includes/extends"; -@import "_includes/buttons"; -@import "_includes/mixins"; - -@import "_includes/tooltip"; - -// grid layout for breakpoints -@import "admin/partials/grid"; - -// forms -@import "admin/modules/forms"; - -// course outline widget -@import "admin/modules/course-outline"; - -// voucher -@import "admin/modules/voucher"; - -// widgets -@import "admin/modules/widgets"; - -// icons -@import "admin/modules/icons"; - -// icons -@import "admin/modules/mb-tabs"; - -// icons -@import "admin/modules/top-modal"; - -@import "admin/modules/merge-codes"; - -// Base (mobile) -@import "admin/breakpoints/base"; - -// Larger mobile devices -@media only screen and (min-width: 481px) { - @import "admin/breakpoints/481up"; -} - -// Tablets and smaller laptops -@media only screen and (min-width: 768px) { - @import "admin/breakpoints/768up"; -} - -// Desktops -@media only screen and (min-width: 1030px) { - @import "admin/breakpoints/1030up"; -} - -// Larger Monitors and TVs -@media only screen and (min-width: 1240px) { - @import "admin/breakpoints/1240up"; -} - -@import "admin/main"; - -@import "admin/llms-table"; -@import "admin/modules/llms-order-note"; - -// metabox related -@import "admin/metaboxes/llms-metabox"; -@import "admin/metaboxes/metabox-instructors"; -@import "admin/metaboxes/metabox-orders"; -@import "admin/metaboxes/metabox-product"; -@import "admin/metaboxes/metabox-students"; -@import "admin/metaboxes/metabox-field-repeater"; -@import "admin/metaboxes/builder-launcher"; - -@import "admin/post-tables/llms_orders"; -@import "admin/post-tables/post-tables"; - -@import "admin/tabs"; -@import "admin/fonts"; -@import "admin/reporting"; - -@import "admin/quiz-attempt-review"; - -@import "_includes/llms-form-field"; -@import "_includes/vendor/_font-awesome"; - -@import "_includes/spinner"; diff --git a/assets/scss/admin/_course-builder.scss b/assets/scss/admin/_course-builder.scss deleted file mode 100644 index 1b8ca1889e..0000000000 --- a/assets/scss/admin/_course-builder.scss +++ /dev/null @@ -1,1704 +0,0 @@ -body.admin_page_llms-course-builder { - background: #fff; - - #adminmenumain { display: none; } - #wpbody-content { padding-bottom: 0; } - #wpfooter { display: none; } - - #wpcontent, #wpfooter { - margin-left: 0; - } - - // &.folded { - // .llms-course-builder { - // left: 56px; - // } - // } - - .webui-popover { - .select2-container--default { - .select2-results__group { - font-size: 16px; - } - .select2-results__option .select2-results__option { - padding-left: 2em; - } - } - - } -} - - - - -// @media (max-width: 960px) { -// body.admin_page_llms-course-builder.auto-fold { -// .llms-course-builder { -// left: 56px; -// } -// } -// } - -.wrap.lifterlms.llms-builder { - margin: 0; - padding: 0; - position: relative; - - - &.editor-active { - .llms-builder-sidebar { - padding: 10px; - width: calc( 100% - 200px ); - z-index: 3; - } - @media only screen and ( min-width: 1200px ) { - .llms-builder-main { - width: 400px; - } - .llms-builder-sidebar { - width: calc( 100% - 640px ); - } - } - @media only screen and ( min-width: 1440px ) { - .llms-builder-main { - width: calc( 100% - 780px ); - } - .llms-builder-sidebar { - width: 720px; - } - } - @media only screen and ( min-width: 1680px ) { - .llms-builder-main { - width: calc( 100% - 1000px ); - } - .llms-builder-sidebar { - width: 940px; - } - } - } - - .llms-headline { - display: inline-block; - font-weight: 300; - margin: 0; - padding: 0; - transition: width 0.3s ease-in-out; - vertical-align: middle; - } - - .llms-builder-main { - padding: 20px 20px 20px 0; - position: relative; - width: calc( 100% - 340px ); - z-index: 2; - - .llms-action-icons { - display: inline-block; - left: -20px; - opacity: 0; - position: relative; - transition: left 0.2s ease, opacity 0.2s ease; - vertical-align: middle; - } - .llms-builder-header:hover > .llms-action-icons, - .llms-builder-header .llms-action-icons.static { - left: 0; - opacity: 1; - } - - /* - - - /$$$$$$$ /$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$$ /$$$$$$ - /$$_____/ /$$__ $$| $$ | $$ /$$__ $$ /$$_____/ /$$__ $$ - | $$ | $$ \ $$| $$ | $$| $$ \__/| $$$$$$ | $$$$$$$$ - | $$ | $$ | $$| $$ | $$| $$ \____ $$| $$_____/ - | $$$$$$$| $$$$$$/| $$$$$$/| $$ /$$$$$$$/| $$$$$$$ - \_______/ \______/ \______/ |__/ |_______/ \_______/ - */ - - .llms-course-header { - position: relative; - z-index: 1; - } - - - /* - /$$ /$$ - | $$ |__/ - /$$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$ /$$ /$$$$$$ /$$$$$$$ /$$$$$$$ - /$$_____/ /$$__ $$ /$$_____/|_ $$_/ | $$ /$$__ $$| $$__ $$ /$$_____/ - | $$$$$$ | $$$$$$$$| $$ | $$ | $$| $$ \ $$| $$ \ $$| $$$$$$ - \____ $$| $$_____/| $$ | $$ /$$| $$| $$ | $$| $$ | $$ \____ $$ - /$$$$$$$/| $$$$$$$| $$$$$$$ | $$$$/| $$| $$$$$$/| $$ | $$ /$$$$$$$/ - |_______/ \_______/ \_______/ \___/ |__/ \______/ |__/ |__/|_______/ - */ - ul.llms-sections { - box-shadow: 0 0 0 3px transparent; - min-height: 60px; - padding: 10px 0; - transition: box-shadow 0.6s ease, min-height 0.2s ease; - &.dragging { - box-shadow: 0 0 0 3px $color-brand-blue; - } - } - - li.llms-section { - background: #fff; - margin: 0; - padding: 20px 20px 20px 40px; - - &.expanded { - .llms-lessons { overflow: visible; } - } - &.selected { - .llms-drag-utility.drag-section { - border-color: $color-brand-blue; - } - > .llms-builder-header .llms-headline { - font-weight: 400; - color: $color-brand-blue; - } - } - - } - - // tree line - li.llms-section:before { - background: #ccc; - bottom: 0; - content: ''; - left: 19px; - position: absolute; - top: 0; - width: 2px; - } - - li.llms-section:first-child:before { - top: 30px; - } - - li.llms-section:last-child:before { - bottom: 55px; - } - - li.llms-section.expanded:last-child:before { - bottom: 86px; - } - - /* - /$$ - | $$ - | $$ /$$$$$$ /$$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$$ - | $$ /$$__ $$ /$$_____//$$_____/ /$$__ $$| $$__ $$ /$$_____/ - | $$| $$$$$$$$| $$$$$$| $$$$$$ | $$ \ $$| $$ \ $$| $$$$$$ - | $$| $$_____/ \____ $$\____ $$| $$ | $$| $$ | $$ \____ $$ - | $$| $$$$$$$ /$$$$$$$//$$$$$$$/| $$$$$$/| $$ | $$ /$$$$$$$/ - |__/ \_______/|_______/|_______/ \______/ |__/ |__/|_______/ - */ - ul.llms-lessons { - box-shadow: 0 0 0 3px transparent; - height: 0; - margin: 10px 0 0; - overflow: hidden; - padding: 10px 0; - transition: box-shadow 0.6s ease, min-height 0.2s ease; - &.dragging { - box-shadow: 0 0 0 3px $color-brand-blue; - min-height: 60px; - } - &.expanded, // added via backbone view events - &.drag-expanded { // added only during dragover events and ignores model attrs - height: auto; - li.llms-lesson { - pointer-events: auto; - visibility: visible; - } - } - - } - - li.llms-lesson { - background: #fff; - margin: 0; - padding: 10px 20px 10px 30px; - position: relative; - pointer-events: none; - visibility: hidden; - - &.selected { - .llms-drag-utility.drag-lesson { - border-color: $color-brand-blue; - } - > .llms-builder-header .llms-headline { - font-weight: 400; - color: $color-brand-blue; - } - } - - } - - // line on left of each lesson - li.llms-lesson:before { - background: #ccc; - content: ''; - height: 2px; - left: -20px; - position: absolute; - top: 20px; - width: 30px; - } - - - /* - /$$ /$$ /$$ /$$ - | $$ | $$ | $$| $$ - /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ | $$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$$| $$ /$$$$$$ /$$$$$$$ - /$$__ $$ /$$__ $$|____ $$ /$$__ $$ | $$__ $$ |____ $$| $$__ $$ /$$__ $$| $$ /$$__ $$ /$$_____/ - | $$ | $$| $$ \__/ /$$$$$$$| $$ \ $$ | $$ \ $$ /$$$$$$$| $$ \ $$| $$ | $$| $$| $$$$$$$$| $$$$$$ - | $$ | $$| $$ /$$__ $$| $$ | $$ | $$ | $$ /$$__ $$| $$ | $$| $$ | $$| $$| $$_____/ \____ $$ - | $$$$$$$| $$ | $$$$$$$| $$$$$$$ | $$ | $$| $$$$$$$| $$ | $$| $$$$$$$| $$| $$$$$$$ /$$$$$$$/ - \_______/|__/ \_______/ \____ $$ |__/ |__/ \_______/|__/ |__/ \_______/|__/ \_______/|_______/ - /$$ \ $$ - | $$$$$$/ - \______/ - */ - li.llms-section .llms-drag-utility { - background: #fff; - border: 2px solid #ccc; - border-radius: 50%; - height: 10px; - left: 13px; - position: absolute; - top: 24px; - width: 10px; - } - - li.llms-lesson .llms-drag-utility { - height: 6px; - left: 5px; - top: 16px !important; - width: 6px; - } - - .llms-section:hover > .llms-drag-utility, - .llms-lesson:hover > .llms-drag-utility { - border-color: #fff; - cursor: move; - &:hover:after { - color: $color-brand-blue; - } - &:after { - background: #fff; - content: '\00b7\00b7\A\00b7\00b7\A\00b7\00b7'; - color: #ccc; - display: block; - font-size: 36px; - height: 29px; - letter-spacing: -1px; - line-height: 8px; - left: -7px; - position: absolute; - text-align: center; - top: -12px; - width: 23px; - } - } - - /* - /$$ /$$ /$$ - | $$ | $$ | $$ - /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ | $$$$$$$ | $$ /$$$$$$ - /$$_____/ /$$__ $$ /$$__ $$|_ $$_/ |____ $$| $$__ $$| $$ /$$__ $$ - | $$$$$$ | $$ \ $$| $$ \__/ | $$ /$$$$$$$| $$ \ $$| $$| $$$$$$$$ - \____ $$| $$ | $$| $$ | $$ /$$ /$$__ $$| $$ | $$| $$| $$_____/ - /$$$$$$$/| $$$$$$/| $$ | $$$$/| $$$$$$$| $$$$$$$/| $$| $$$$$$$ - |_______/ \______/ |__/ \___/ \_______/|_______/ |__/ \_______/ - */ - li.llms-section, - li.llms-lesson { - &.ui-sortable-helper, - &.ui-draggable-dragging { - border: 1px solid #ccc; - background: #fff; - transform: rotate( 2deg ); - visibility: visible !important; - z-index: 999; - - // hide tree line on the helper - &:before { display: none; } - - // prevent action icon hover display - .llms-action-icons, - .llms-builder-header:hover > .llms-action-icons { - display: none; - } - } - - &.llms-sortable-placeholder { - border: 3px dashed $color-brand-blue; - background: rgba( $color-brand-blue, 0.3 ); - margin: 0 10px; - padding: 5px; - &:before { display: none; } - } - } - - ul.llms-sections > li.llms-lesson.ui-draggable-dragging .llms-drag-utility { - position: relative; - &:after { - left: -35px; - top: -28px; - } - } - - } - - /* - /$$ /$$ /$$ /$$ /$$ - | $$|__/ | $$ | $$ | $$ - /$$$$$$ /$$$$$$$ /$$ /$$$$$$ /$$$$$$ | $$$$$$$ | $$ /$$$$$$ - /$$__ $$ /$$__ $$| $$|_ $$_/ |____ $$| $$__ $$| $$ /$$__ $$ - | $$$$$$$$| $$ | $$| $$ | $$ /$$$$$$$| $$ \ $$| $$| $$$$$$$$ - | $$_____/| $$ | $$| $$ | $$ /$$ /$$__ $$| $$ | $$| $$| $$_____/ - | $$$$$$$| $$$$$$$| $$ | $$$$/| $$$$$$$| $$$$$$$/| $$| $$$$$$$ - \_______/ \_______/|__/ \___/ \_______/|_______/ |__/ \_______/ - */ - - .llms-input-wrapper { - position: relative; - } - - .llms-input-formatting.ql-container { - font-size: inherit; - font-family: inherit; - .ql-editor.ql-blank::before { - color: #a0a0a0; - left: 8px; - right: 8px; - } - .ql-editor { - p { - font-size: inherit; - line-height: 1; - } - } - .ql-tooltip { - z-index: 1; - } - } - - .llms-input, - .llms-input-formatting .ql-editor { - border: none; - border-bottom: 2px dotted transparent; - box-shadow: none; - cursor: text; - display: inline-block; - font-size: inherit; - font-weight: 500; - height: auto; - line-height: 1; - margin: 0 8px; - min-width: 60px; - padding: 0; - transition: border 0.2s ease, box-shadow 0.2s ease; - &:empty:before { - color: #a0a0a0; - content: attr( data-placeholder ); - } - &:hover { - border-bottom-color: $color-brand-blue; - } - &[disabled] { - cursor: not-allowed; - &:hover { - border-bottom-color: transparent; - } - } - &:focus { - background: #fff; - box-shadow: 0 0 0 4px #fff, 0 0 0 6px $color-brand-blue; - border-bottom: none; - outline: none; - } - b, strong { - font-weight: 700; - } - &.standard { - border: 1px solid #e6e6e6; - margin: 2px; - padding: 5px 3px; - &:hover { - border-color: #d6d6d6; - } - &:focus { - box-shadow: 0 0 0 2px $color-brand-blue; - } - } - &.permalink { - display: none; - } - } - - .llms-input-formatting .ql-editor { - padding: 0 1px; - } - - .llms-label { - font-weight: 500; - } - - // .llms-editable-image, - // .llms-editable-video, - // .llms-editable-editor { - // } - - .llms-editable-editor { - .llms-label { - float: left; - margin-right: 10px; - position: relative; - top: 10px; - } - textarea { - border: none; - padding: 10px; - display: block; - width: 100%; - } - } - - .llms-editable-image { - button.llms-add-image { - width: 130px; - } - .llms-image { - display: inline-block; - position: relative; - &:hover .llms-action-icon { - opacity: 1; - } - .llms-action-icon { - color: #fff; - font-size: 24px; - opacity: 0; - padding: 0; - position: absolute; - transition: opacity 0.2s ease; - right: 3px; - top: 1px; - z-index: 1; - } - img { - display: block; - height: 100px; - max-width: 100%; - width: auto; - } - } - } - - .llms-settings-field, - .llms-editable-toggle-group { - background: #f4f4f4; - padding: 10px; - position: relative; - margin: 0 1px; - - .llms-switch { - display: block; - width: 100%; - @include clearfix; - - .llms-label { - width: calc( 100% - 34px ); - } - } - - .llms-editable-image, - .llms-editable-video, - .llms-editable-editor { - margin-top: 2px; - } - - .llms-input.standard { - display: block; - width: 100%; - &.two-digits, - &.three-digits, - &.four-digits { - display: inline-block; - } - } - - } - - .llms-editable-number { - .llms-input { - color: #888; - min-width: 30px; - text-align: right; - &.two-digits { - width: 30px; - } - &.three-digits { - width: 40px; - } - &.four-digits { - width: 60px; - } - } - small { - color: #888; - text-transform: uppercase; - } - } - - .llms-model-settings { - .llms-settings-group-header { - .fa-caret-square-o-up { display: block; } - .fa-caret-square-o-down { display: none; } - } - &.hidden { - .llms-settings-group-header { - .fa-caret-square-o-up { display: none; } - .fa-caret-square-o-down { display: block; } - } - .llms-settings-group-body { display: none; } - } - } - - .llms-settings-group-header { - @include clearfix(); - .llms-settings-group-title { - display: inline-block; - font-size: 16px; - font-weight: 300; - margin: 0 5px; - padding: 0; - } - .llms-settings-group-toggle { - float: right; - font-size: 18px; - padding: 2px; - } - } - - .llms-settings-group-body { - margin-top: 5px; - } - - .llms-settings-row { - display: flex; - flex-wrap: wrap; - margin: 2px 0; - - .llms-settings-field, - .llms-editable-toggle-group { - flex: 1; - &:first-child { - margin-left: 0; - } - &:last-child { - margin-right: 0; - } - } - - .llms-breaker { - margin: 2px 0; - width: 100%; - } - } - - .llms-editable-select { - margin: 2px 0; - .select2-container--default.select2-container--focus .select2-selection--multiple { - border-color: #aaa; - } - } - - .llms-editable-radio { - label { - display: block; - } - &.has-images { - input { display: none; } - label { - display: inline-block; - margin: 0 3px; - } - label > span { - transition: background 0.2s ease; - display: inline-block; - padding: 3px; - } - img { display: block; } - input:checked + span { - background: $color-brand-blue; - } - } - } - - /* - /$$ - |__/ - /$$ /$$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$$ - | $$ /$$_____/ /$$__ $$| $$__ $$ /$$_____/ - | $$| $$ | $$ \ $$| $$ \ $$| $$$$$$ - | $$| $$ | $$ | $$| $$ | $$ \____ $$ - | $$| $$$$$$$| $$$$$$/| $$ | $$ /$$$$$$$/ - |__/ \_______/ \______/ |__/ |__/|_______/ - */ - .llms-action-icon { - color: #aaa; - display: inline-block; - font-size: 16px; - padding: 0 5px; - text-decoration: none; - &:hover { - color: $color-brand-blue; - &.danger { color: $color-danger; } - } - &.circle { - border: 2px solid #aaa; - border-radius: 50%; - font-size: 9px; - height: 8px; - line-height: 1; - padding: 5px; - text-align: center; - width: 8px; - &:hover { - border-color: $color-brand-blue; - &.danger { - border-color: $color-danger; - } - } - } - } - - ul.llms-info-list { - @include clearfix(); - margin: 0; - padding: 0; - li.llms-info-item { - color: #aaa; - font-size: 16px; - margin: 0; - padding: 10px; - float: left; - &.active, - &.active .llms-action-icon { - color: $color-brand-blue; - } - .llms-action-icon { - margin: -10px; - padding: 10px; - } - } - - } - - /* - /$$ /$$ /$$ - |__/ | $$ | $$ - /$$$$$$$ /$$ /$$$$$$$ /$$$$$$ | $$$$$$$ /$$$$$$ /$$$$$$ - /$$_____/| $$ /$$__ $$ /$$__ $$| $$__ $$ |____ $$ /$$__ $$ - | $$$$$$ | $$| $$ | $$| $$$$$$$$| $$ \ $$ /$$$$$$$| $$ \__/ - \____ $$| $$| $$ | $$| $$_____/| $$ | $$ /$$__ $$| $$ - /$$$$$$$/| $$| $$$$$$$| $$$$$$$| $$$$$$$/| $$$$$$$| $$ - |_______/ |__/ \_______/ \_______/|_______/ \_______/|__/ - */ - .llms-builder-sidebar { - background: #e6e6e6; - bottom: 0; - overflow: hidden; - padding: 20px; - position: fixed; - transition: width 0.3s ease-in-out; - top: 32px; - right: 0; - width: 280px; - z-index: 1; - - .llms-utilities { - - ul, li { - margin: 0; - padding: 0; - } - - ul { - display: flex; - li { - flex: 1; - margin-right: 5px; - &:last-child { - margin-right: 0; - } - } - } - - - a.llms-utility { - background: #efefef; - border-radius: 4px; - display: block; - overflow: hidden; - padding: 4px; - position: relative; - text-align: center; - - &:hover { - background: #fefefe; - } - - .fa { - background: #848484; - position: absolute; - left: 0; - top: 0; - padding: 7px; - color: #fff; - } - } - - } - - .llms-sidebar-headline { - margin: 0 0 10px; - font-size: 22px; - font-weight: 300; - letter-spacing: 2px; - text-transform: uppercase; - } - - .llms-elements-list { - margin-bottom: 40px; - li { - margin-bottom: 10px; - } - } - - .llms-utility { - color: #444; - text-decoration: none; - } - - .llms-element-button { - - background: $color-brand-blue; - border-radius: 4px; - border: none; - color: #fff; - cursor: pointer; - display: block; - margin: 0; - overflow: hidden; - padding: 17px 20px; - position: relative; - transition: background 0.2s ease, color 0.2s ease; - text-align: center; - width: 100%; - - &:hover { - background: $color-brand-blue-dark; - } - - &.secondary { - background: #efefef; - color: #444; - &:hover { - background: #fefefe; - } - .fa { - background: #848484; - } - } - - .fa { - background: $color-brand-dark-blue; - border-radius: 4px 0 0 4px; - color: #fff; - display: block; - font-size: 20px; - padding: 15px 20px; - position: absolute; - top: 0; - left: 0; - } - - &[disabled="disabled"] { - opacity: 0.4; - } - - &.small { - - padding: 8px 10px 8px 46px; - .fa { - font-size: 15px; - padding: 9px 10px; - width: 20px; - } - - } - - &.right { - - &.small { - padding-left: 10px; - padding-right: 46px; - } - - .fa { - border-radius: 0 4px 4px 0; - left: auto; - right: 0; - } - - } - - } - - - - .llms-editor { - height: 100%; - min-height: 100%; - position: relative; - } - - // .llms-builder-close-editor { - // background: $color-brand-blue; - // border: none; - // border-radius: 50%; - // color: #fff; - // cursor: pointer; - // display: inline-block; - // font-size: 18px; - // height: 30px; - // margin: 0; - // position: absolute; - // right: 0; - // text-align: center; - // top: 3px; - // width: 30px; - // z-index: 3; - // } - - .llms-editor-nav { - background: #b0b0b0; - font-size: 0; - margin: -10px -10px 10px -10px; - position: relative; - z-index: 2; - - .llms-editor-menu { - list-style-type: none; - margin: 0; - padding: 0; - position: relative; - - .llms-editor-menu-item { - display: inline-block; - margin: 0; - padding: 0; - - &.right { - float: right; - } - - > .llms-editor-menu { - display: none; - &:before { - border: 8px solid transparent; - border-left-color: #cacaca; - content: ''; - position: absolute; - top: 11px; - left: 0; - } - - .llms-editor-menu-item:hover > a, - .llms-editor-menu-item.active > a { - background: #dfdfdf; - } - - } - - &:hover > a, - &.active > a { - background: #cacaca; - } - - &.active > a { - box-shadow: inset 0 -3px 0 $color-brand-blue; - &:focus { - box-shadow: inset 0 -3px 0 $color-brand-blue; - } - } - - &.active > .llms-editor-menu { - display: inline-block; - } - - a { - color: #444; - display: inline-block; - padding: 13px 20px; - text-decoration: none; - transition: background 0.2s ease; - font-size: 14px; - &:focus { - box-shadow: inset 0 0 0 2px $color-brand-blue; - } - } - - } - } - } - - .llms-editor-tab { - display: none; - height: calc( 100% - 90px ); - overflow: scroll; - position: relative; - z-index: 1; - &.active { - display: block; - - &.tab--quiz { - - display: flex; - flex-direction: column; - - .llms-quiz-questions { - flex: 1; - overflow: scroll; - - // groups - .llms-quiz-questions { - overflow: visible; - } - } - - } - } - - } - - - // .llms-builder-editor { - - // opacity: 0; - // margin: 10px 0; - // transition: opacity 0.2s linear; - - // &.ready { - // opacity: 1; - // } - - // textarea { - // border: none; - // display: block; - // width: 100%; - // } - // } - - .llms-builder-save { - - bottom: 10px; - left: 10px; - position: absolute; - right: 10px; - z-index: 1; - - .llms-builder-error { - background: $color-danger; - border-radius: 4px; - color: #fff; - display: inline-block; - font-style: italic; - padding: 5px 15px 7px 25px; - margin: 0 0 10px; - - li { - margin: 0; - padding: 0; - } - - } - - .llms-save { - width: 75%; - } - .llms-exit { - width: 23%; - } - - button { - position: relative; - i { - position: absolute; - left: 10px; - top: 10px; - - .llms-spinner { - border-color: #fff; - } - } - } - button[data-status] .llms-status-indicator { display: none; } - button[data-status="saved"] .status--saved { display: block; } - button[data-status="unsaved"] .status--unsaved { display: block; } - button[data-status="saving"] .status--saving { display: block; } - button[data-status="error"] .status--error { display: block; } - - } - - } - - - /* - /$$ - | $$ - /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$ - /$$_____/ /$$__ $$ |____ $$ /$$__ $$ /$$_____/| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ /$$__ $$| $$ /$$//$$__ $$ /$$__ $$ - | $$$$$$ | $$$$$$$$ /$$$$$$$| $$ \__/| $$ | $$ \ $$ | $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ \ $$/$$/| $$$$$$$$| $$ \__/ - \____ $$| $$_____/ /$$__ $$| $$ | $$ | $$ | $$ | $$ | $$| $$ | $$| $$ | $$| $$ | $$ \ $$$/ | $$_____/| $$ - /$$$$$$$/| $$$$$$$| $$$$$$$| $$ | $$$$$$$| $$ | $$ | $$$$$$$/| $$$$$$/| $$$$$$$/| $$$$$$/ \ $/ | $$$$$$$| $$ - |_______/ \_______/ \_______/|__/ \_______/|__/ |__/ | $$____/ \______/ | $$____/ \______/ \_/ \_______/|__/ - | $$ | $$ - | $$ | $$ - |__/ |__/ - */ - - .select2-container { - z-index: 99999999; - } - - .select2-results__option { - padding: 0; - } - - .select2-container--default .select2-results__option--highlighted[aria-selected] { - background: $color-brand-blue; - .llms-existing-action { - color: #fff; - } - } - - .llms-existing-lesson-result { - - align-items: center; - display: flex; - padding: 5px 5px 5px 0; - - .llms-existing-info { - flex: 6; - - h4, h5 { - margin: 0; - } - - h4 { - font-weight: 400; - } - - h5 { - font-weight: 300; - } - } - - .llms-existing-action { - color: $color-brand-blue; - flex: 1; - text-align: center; - - .fa { - display: block; - font-size: 30px; - } - - small { - text-transform: uppercase; - } - - } - - - } - - - /* - /$$ - |__/ - /$$$$$$ /$$ /$$ /$$ /$$$$$$$$ - /$$__ $$| $$ | $$| $$|____ /$$/ - | $$ \ $$| $$ | $$| $$ /$$$$/ - | $$ | $$| $$ | $$| $$ /$$__/ - | $$$$$$$| $$$$$$/| $$ /$$$$$$$$ - \____ $$ \______/ |__/|________/ - | $$ - | $$ - |__/ - */ - - .llms-quiz-empty { - margin: 100px auto; - text-align: center; - - p { font-size: 18px; } - button.llms-element-button { - max-width: 320px; - margin: 0 auto; - } - - } - - - .llms-model-header, - .llms-model-settings { - background: #fff; - padding: 10px; - @include clearfix(); - } - - .llms-editor-tab.tab--quiz { - .llms-model-header { - .llms-model-title { - width: calc( 100% - 310px ); - } - .llms-quiz-points { - float: left; - margin-right: 10px; - width: 100px; - } - } - } - - .llms-model-header { - border-bottom: 5px solid #e6e6e6; - - .llms-model-title { - float: left; - margin-right: 10px; - width: calc( 100% - 200px ); - .llms-input { - width: calc( 100% - 65px ); - } - } - .llms-model-status.llms-switch { - float: left; - margin-right: 10px; - position: relative; - text-align: right; - top: -2px; - width: 100px; - } - .llms-action-icons { - float: left; - position: relative; - text-align: right; - width: 80px; - z-index: 1; - .fa { - max-width: 15px; - } - } - - .llms-model-settings { - padding: 0; - } - - } - - .llms-model-header + .llms-model-settings.active { - margin-top: -10px; - } - - .llms-model-settings { - clear: both; - display: none; - - &.active { - display: block; - margin-top: 10px; - } - } - - .llms-quiz-footer { - display: flex; - button.llms-element-button { - flex: 1; - margin: 0 5px; - &:first-child { margin-left: 0; } - &:last-child { margin-right: 0; } - &.llms-show-question-bank { - flex: 2; - } - } - } - - /* - /$$ /$$ /$$ /$$ - | $$ |__/ | $$ | $$ - /$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$$ /$$$$$$ /$$ /$$$$$$ /$$$$$$$ | $$$$$$$ /$$$$$$ /$$$$$$$ | $$ /$$ - /$$__ $$| $$ | $$ /$$__ $$ /$$_____/|_ $$_/ | $$ /$$__ $$| $$__ $$ | $$__ $$ |____ $$| $$__ $$| $$ /$$/ - | $$ \ $$| $$ | $$| $$$$$$$$| $$$$$$ | $$ | $$| $$ \ $$| $$ \ $$ | $$ \ $$ /$$$$$$$| $$ \ $$| $$$$$$/ - | $$ | $$| $$ | $$| $$_____/ \____ $$ | $$ /$$| $$| $$ | $$| $$ | $$ | $$ | $$ /$$__ $$| $$ | $$| $$_ $$ - | $$$$$$$| $$$$$$/| $$$$$$$ /$$$$$$$/ | $$$$/| $$| $$$$$$/| $$ | $$ | $$$$$$$/| $$$$$$$| $$ | $$| $$ \ $$ - \____ $$ \______/ \_______/|_______/ \___/ |__/ \______/ |__/ |__/ |_______/ \_______/|__/ |__/|__/ \__/ - | $$ - | $$ - |__/ - */ - - .llms-quiz-tools { - display: none; - width: 100%; - position: relative; - - // .llms-quiz-tools-search { - // padding: 0 10px; - // margin-bottom: 15px; - - // .fa { - // color: #888; - // font-size: 16px; - // } - - // input[type="search"] { - // background: inherit; - // border: none; - // border-bottom: 1px solid #bbb; - // box-shadow: none; - // font-size: 16px; - // margin: 8px 0 0; - // padding: 2px 5px; - // width: calc( 100% - 200px ); - - // &:focus { - // border-bottom-color: $color-brand-blue; - // } - // } - - // } - - } - - ul.llms-question-bank { - - list-style-type: none; - margin: 0; - padding: 0; - @include clearfix; - - li.llms-question-bank-header { - clear: both; - padding-top: 20px; - &:first-child { - padding-top: 0; - } - h4 { - font-size: 20px; - margin: 10px 5px; - } - } - - li.llms-question-type { - box-sizing: border-box; - float: left; - margin: 0; - padding: 3px; - width: 33.3333%; - transition: opacity 0.3s ease-in-out; - - &.filtered { - opacity: 0.3; - } - - .llms-type-unavailable { - display: block; - position: relative; - text-decoration: none; - .llms-element-button { - opacity: 0.5; - pointer-events: none; - } - } - - } - - } - - /* - /$$ /$$ /$$ - |__/ | $$ |__/ - /$$$$$$ /$$ /$$ /$$ /$$$$$$$$ /$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$$ /$$$$$$ /$$ /$$$$$$ /$$$$$$$ /$$$$$$$ - /$$__ $$| $$ | $$| $$|____ /$$/ /$$__ $$| $$ | $$ /$$__ $$ /$$_____/|_ $$_/ | $$ /$$__ $$| $$__ $$ /$$_____/ - | $$ \ $$| $$ | $$| $$ /$$$$/ | $$ \ $$| $$ | $$| $$$$$$$$| $$$$$$ | $$ | $$| $$ \ $$| $$ \ $$| $$$$$$ - | $$ | $$| $$ | $$| $$ /$$__/ | $$ | $$| $$ | $$| $$_____/ \____ $$ | $$ /$$| $$| $$ | $$| $$ | $$ \____ $$ - | $$$$$$$| $$$$$$/| $$ /$$$$$$$$ | $$$$$$$| $$$$$$/| $$$$$$$ /$$$$$$$/ | $$$$/| $$| $$$$$$/| $$ | $$ /$$$$$$$/ - \____ $$ \______/ |__/|________/ \____ $$ \______/ \_______/|_______/ \___/ |__/ \______/ |__/ |__/|_______/ - | $$ | $$ - | $$ | $$ - |__/ |__/ - */ - ul.llms-quiz-questions { - - margin: 10px 3px; - padding: 5px; - transition: box-shadow 0.6s ease; - - &.dragging { - box-shadow: 0 0 0 3px $color-brand-blue; - } - - &:empty:before { - background: #fff; - content: attr(data-empty-msg); - display: block; - font-size: 18px; - margin: 0 auto; - padding: 100px 0; - text-align: center; - } - - li.llms-question { - - background: #fff; - margin: 0 0 3px; - padding: 15px 12px 10px; - - &:hover { - > .llms-builder-header .llms-action-icons { - opacity: 1; - pointer-events: auto; - } - } - - // groups - ul.llms-quiz-questions { - margin-left: 12px; - .llms-question { - border-bottom: 2px solid #e6e6e6; - } - &:empty:before { - content: attr(data-empty-msg); - display: block; - font-size: 18px; - text-align: center; - margin: 20px auto; - } - li.llms-question.llms-sortable-placeholder.qtype--group { - display: none !important; - } - } - - .llms-builder-header { - @include clearfix; - > * { - float: left; - } - } - - .llms-question-body { - display: none; - &.active { - display: block; - } - } - - .llms-data-stamp { - background: $color-brand-blue; - border-radius: 4px; - color: #fff; - cursor: move; - font-size: 90%; - margin-top: -5px; - padding: 4px 10px 6px; - - small, .fa { - line-height: 1.2; - vertical-align: middle; - } - - .fa { - margin-right: 4px; - } - - } - - .llms-headline { - width: calc( 100% - 90px - 80px - 55px ); - .ql-editor { - width: calc( 100% - 16px ); - } - } - - .llms-action-icons { - width: 80px; - opacity: 0; - pointer-events: none; - } - - .llms-question-points { - width: 90px; - } - - .llms-question-features { - margin: 10px 0 0; - &:last-child { - margin: 0; - } - .llms-switch { - margin-right: 15px; - } - } - - .llms-editable-video { - position: relative; - z-index: 1; - } - - } - - .llms-question-choices-wrapper { - background: #f4f4f4; - margin: 2px 1px; - padding: 10px; - } - - .llms-question-choices-list-header { - @include clearfix; - margin-bottom: 10px; - - .llms-switch { - float: right; - text-align: right; - width: 260px; - } - } - - ul.llms-question-choices { - border: 3px solid #f4f4f4; - margin: -3px; - padding: 0; - transition: box-shadow 0.6s ease; - - &.dragging { - box-shadow: 0 0 0 3px $color-brand-blue; - } - - &.multi-choices li.llms-question-choice .llms-choice-id span { - border-radius: 4px; - } - - } - - li.llms-question-choice { - margin: 0 0 5px; - padding: 0; - &:last-child { margin-bottom: 0; } - - .llms-choice-id { - - input[type="checkbox"] { - display: none; - } - - input[type="checkbox"]:checked + .llms-marker { - background: $color-green; - } - - .llms-marker { - border-radius: 50%; - background: #d0d0d0; - box-shadow: inset 0 0 1px #848484; - color: #444; - display: inline-block; - font-size: 16px; - height: 20px; - line-height: 20px; - padding: 5px; - position: relative; - text-align: center; - transition: background 0.1s ease; - width: 20px; - - .fa { - left: 7px; - opacity: 0; - position: absolute; - top: 7px; - } - &.selectable:hover { - b { opacity: 0 } - .fa { opacity: 1; } - } - - } - - } - - .llms-input-wrapper, - .llms-editable-image { - display: inline-block; - // action icons width, label width, ul margins - width: calc( 100% - 55px - 35px - 5px ); - } - - .llms-input { - width: calc( 100% - 16px ); - } - - .llms-editable-image .llms-image { - vertical-align: middle; - img { - height: 50px; - } - } - - .llms-action-icons { - display: inline-block; - opacity: 1; - pointer-events: auto; - text-align: right; - width: 55px; - } - - } - - li.llms-question-choice.llms-sortable-placeholder { - border: 3px dashed $color-brand-blue !important; - background: rgba( $color-brand-blue, 0.3 ); - } - - li.llms-question-choice.ui-sortable-helper { - border: 1px solid #ccc; - background: #fff; - padding: 10px; - transform: rotate( 2deg ); - z-index: 999; - } - - li.llms-question.ui-sortable-helper, - li.llms-question.ui-draggable-dragging { - border: 1px solid #ccc; - background: #fff; - transform: rotate( 2deg ); - z-index: 999; - } - - li.llms-question.llms-sortable-placeholder { - border: 3px dashed $color-brand-blue !important; - background: rgba( $color-brand-blue, 0.3 ); - } - - } - - - .llms-switch { - display: inline-block; - float: none; - width: auto; - - input[type="checkbox"] { - display: none; - } - - input[type="checkbox"]:checked + .llms-switch-slider { - background: $color-green; - } - - input[type="checkbox"]:checked + .llms-switch-slider:after { - transform: translateX( 14px ); - } - - .llms-label { - display: inline-block; - vertical-align: top; - } - - .llms-switch-slider { - background: #e0e0e0; - border-radius: 8px; - display: inline-block; - height: 16px; - margin-top: 2px; - position: relative; - transition: background 0.2s ease; - vertical-align: top; - width: 30px; - - &:after { - background: #fff; - border-radius: 8px; - content: ''; - display: block; - height: 12px; - left: 2px; - position: relative; - transition: transform 0.2s ease; - top: 2px; - width: 12px; - } - - } - - } - -} - - - -// .llms-builder-tools { -// background: #cecece; -// flex: 1; -// position: relative; -// padding: 40px 20px 80px; - - -// footer { - -// bottom: 0; -// left: 0; -// padding: 20px; -// position: absolute; -// right: 0; - -// .save-status { -// font-style: italic; -// line-height: 20px; -// margin: 0; -// z-index: 1; -// .unsaved, .saving { -// display: none; -// } -// &[data-status="saving"] { -// .saving { -// display: block; -// } -// } -// } - -// #llms-spinner-el { -// display: inline-block; -// margin-right: 5px; -// height: 20px; -// position: relative; -// vertical-align: middle; -// width: 20px; -// .llms-spinning { -// background: transparent; -// } -// } - -// } - -// } - - - diff --git a/assets/scss/admin/_fonts.scss b/assets/scss/admin/_fonts.scss deleted file mode 100644 index d2b834e87e..0000000000 --- a/assets/scss/admin/_fonts.scss +++ /dev/null @@ -1,8 +0,0 @@ -#llms-options-page-contents { - h2 { - color: #999; - font-weight: 500; - letter-spacing: 2px; - border-bottom: 1px solid #999; - } -} diff --git a/assets/scss/admin/_llms-table.scss b/assets/scss/admin/_llms-table.scss deleted file mode 100644 index 435e25496d..0000000000 --- a/assets/scss/admin/_llms-table.scss +++ /dev/null @@ -1,191 +0,0 @@ -.llms-table-wrap { - position: relative; -} - -.llms-table-header { - padding: 0 10px; - margin-bottom: 10px; - - @include clearfix(); - - h2 { - padding: 0; - display: inline-block; - line-height: 1; - margin: 0; - vertical-align: middle; - } - - .llms-table-search, - .llms-table-filters { - float: right; - padding-left: 10px; - } - - .llms-table-search input { - margin: 0; - padding: 5px; - } - -} - -.llms-table { - - border: 1px solid #cecece; - border-collapse: collapse; - width: 100%; - - td, th { - border-bottom: 1px solid #cecece; - font-size: 95%; - padding: 4px; - text-align: center; - - &.expandable.closed { - display: none; - } - - .llms-button-primary, - .llms-button-secondary, - .llms-button-action, - .llms-button-danger { - display: inline-block; - } - - } - - thead th, - tfoot th { - background-color: #eaeaea; - font-weight: 500; - - a.llms-sortable { - // display: block; - padding-right: 16px; - position: relative; - text-decoration: none; - width: 100%; - &.active { - // show the current sorted when a sort is active - &[data-order="DESC"] .asc { opacity: 1; } - &[data-order="ASC"] .desc { opacity: 1; } - } - // show the opposite on hover - &:hover { - &[data-order="DESC"] { - .asc { opacity: 0; } - .desc { opacity: 1; } - } - &[data-order="ASC"] { - .asc { opacity: 1; } - .desc { opacity: 0; } - } - } - .dashicons { - color: #444; - font-size: 16px; - height: 16px; - opacity: 0; - position: absolute; - width: 16px; - } - } - } - - tfoot th { - border-bottom: none; - - .llms-table-export { - float: left; - } - - .llms-table-pagination { - float: right; - } - - } - - &.zebra tbody tr:nth-child( even ) { - th, td { background-color: #fafafa; } - } - - &.zebra tbody tr:nth-child( odd ) { - th, td { background-color: #fff; } - } - - &.text-left { - td, th { - text-align: left; - } - } - - &.size-large { - td, th { - font-size: 105%; - padding: 8px; - } - } - - .llms-action-icon { - color: #777; - text-decoration: none; - - .tooltip { - cursor: pointer; - } - - &:hover { - color: $color-blue; - } - - &.danger:hover { - color: $color-danger; - } - } - - .llms-table-page-count { - font-size: 11px; - font-weight: 300; - padding: 0 5px; - } - -} - -// progress bars within the tables -.llms-table-progress { - background: #eee; - height: 16px; - position: relative; - .llms-table-progress-text { - font-size: 11px; - line-height: 16px; - position: absolute; - right: 4px; - top: 0; - } - .llms-table-progress-inner { - background: $color-brand-blue; - height: 100%; - } -} - - -.llms-table.llms-gateway-table { - .status { - .fa { - color: $color-brand-blue; - font-size: 22px; - } - } - .sort { - cursor: move; - text-align: center; - width: 10px; - } -} - -.llms-gb-table-notifications { - th, td { - text-align: left; - } -} diff --git a/assets/scss/admin/_main.scss b/assets/scss/admin/_main.scss deleted file mode 100644 index ad979a9ebc..0000000000 --- a/assets/scss/admin/_main.scss +++ /dev/null @@ -1,450 +0,0 @@ -.dad-list, .dad-list .title { - border: 1px solid #dfdfdf; -} -.dad-list tr { - cursor: move; -} -.newTasks{ - padding:3px; - border:1px solid #888; - -moz-border-radius:3px; - -webkit-border-radius: 3px; - border-radius:3px; -} -.widefat th, .widefat td { -overflow: visible; -} - -// todo determine if this is necessary still -// .title { -// padding: 10px; -// line-height: 1; -// border-color: gray; -// background-color: #f1f1f1; -// border: 1px solid #f1f1f1; -// margin: 0; -// position: relative; -// } -.title .order { - margin-right: 10px; - font-weight: bold; -} -.myicon:before { - content: "\2605"; - display: inline-block; - -webkit-font-smoothing: antialiased; - font: normal 20px/1 'dashicons'; - vertical-align: top; -} -i.section-dismiss { - font-size: 2em; - position: absolute; - right: 16px; - top: 12px; - color: rgba(88, 88, 91, 0.6); - cursor: pointer; -} -i.section-dismiss:hover { - cursor: pointer; - color: #d54e21; -} -.section-content { - padding: 10px; - line-height: 1; - border: 1px solid #dfdfdf; - position: relative; -} -.section-content:hover { - background-color: #f9f9f9; -} -.section { - margin-top: 20px; - margin-bottom: 20px; -} -#syllabus { - position: relative; - min-height: 100px; -} -#syllabus .add-lesson { - margin: 10px 0 16px 10px; -} -.deleteBtn { - color: rgba(88, 88, 91, 0.6); - font-size: 2em; - cursor: pointer; - margin-top: -6px; -} -.deleteBtn:hover { - cursor: pointer; - color: #d54e21; -} -// .select, .input { -// width: 300px; -// } -#post_course_difficulty { - min-width: 200px; -} -#_video-embed, #_audio-embed { - width: 100%; -} -.clear { - clear: both; - width: 100%; -} -.llms-large-text { - min-height: 100px; -} -#spinner { - width: 20px; - height: 20px; - margin-left: 4px; - margin-top: 5px; - display: inline-block; -} -table.dad-list tr th:nth-child(2) { - width: 50px; -} -table.dad-list tr td:nth-child(2) { - text-align: right; - padding-right: 16px; - padding-top: 14px; -} -.meta-box-sortables .course-section select { - width:75%; -} -#addNewSection { - margin-bottom: 16px; -} - -.courses { - background: #000; -} - -.llms_certificate_default_image, .llms_certificate_image { - width: 300px; -} - -.llms_achievement_default_image, .llms_achievement_image { - width: 120px; -} -.llms-access-level { - width: 100%; - margin-bottom: 6px; -} -.llms-access-levels { - min-height: 42px; - overflow: auto; - padding: .9em; - border: 1px solid #dfdfdf; - background-color: #fdfdfd; -} -.llms_access_options { - padding: 10px; -} -.llms-access-option { - padding:10px 10px 10px 13px; -} -.llms-access-level:last-child { - margin-bottom: 0; -} -.llms-access-levels-title { - padding-bottom: 10px; - display: block; - width: 100%; - font-weight: bold; -} -.toplevel_page_lifterlms img { - height: 18px; - width: 18px; -} -.llms-lesson-list { - margin: 0; - ul { - margin-left: 10px; - li { - margin-top: 6px; - a { - color: $color-blue; - } - } - } -} -.llms-lesson-list a { - text-decoration: none; -} -.llms-lesson-list span { - margin-left: 10px; -} -.course-section { -} -select[disabled] { - color:#000; - border: transparent; - background: none; --moz-appearance: checkbox-container; - -webkit-appearance: none; - -ms-appearance: none; - appearance: none; - text-indent: 1px; - text-overflow: ''; - box-shadow: none; - background: none; - margin-top: -4px; -} -select[disabled]::-ms-expand { - display: none; -} - -.section-placeholder { - height: 200px; - width: 100%; -} -.sortable-placeholder { - border-left: 2px solid #4999DA; - margin: 0 0 0.75rem 0; - position: relative; - z-index: 6; - visibility: visible; - background: #f4f9fb; -} -#syllabus .placeholder { - height: 46px; - - border:10px solid #4999DA; - background: #f4f9fb; - //margin: 0 0 0.75rem 0; - //position: relative; - //z-index: 6; - visibility: visible; -} -/*we really need to create a helper function to style the dragged element but for v1 I'm not worried about it*/ -.ui-sortable-helper { - background-color: #fff; - border: 1px solid #ccc; -} -// .placeholder { -// background: #f3f3f3; -// visibility: visible; -// } -.list_item td{ - position: relative; -} - -.course-section .title .llms-fa-move-lesson { - position: absolute; - font-size: 20px; - right: 60px; - color: rgba(88, 88, 91, 0.6); - top: 14px; - cursor: move; -} -.course-section .title .llms-fa-edit-lesson { - position: absolute; - font-size: 20px; - right: 104px; - color: rgba(88, 88, 91, 0.6); - top: 14px; - cursor: pointer; -} - -.course-section .title .llms-fa-edit-lesson:hover { - color: #009af7; -} -.course-section .title .llms-fa-move-lesson:hover { - color: #009af7; -} -.course-section .title .llms-fa-move-lesson:active { - color: #009af7; -} -.course-section .title .llms-fa-edit-lesson:active { - color: #009af7; -} - - -tbody tr td .llms-fa-move-lesson { - position: absolute; - font-size: 20px; - right: 60px; - color: rgba(88, 88, 91, 0.6); - top: 10px; - cursor: move; -} -tbody tr td .llms-fa-move-lesson:hover { - color: #009af7; -} -tbody tr td .llms-fa-move-lesson:active { - color: #009af7; -} -tbody tr td .llms-fa-edit-lesson { - position: absolute; - font-size: 20px; - right: 104px; - color: rgba(88, 88, 91, 0.6); - top: 11px; - cursor: pointer; -} -tbody tr td .llms-fa-edit:hover { - color: #009af7; - cursor: pointer; -} -tbody tr td .llms-fa-edit:active { - color: #009af7; -} - -tbody tr td .llms-fa-move { - position: absolute; - font-size: 20px; - right: 60px; - color: rgba(88, 88, 91, 0.6); - top: 10px; - cursor: move; -} -tbody tr td .llms-fa-move:hover { - color: #009af7; -} -tbody tr td .llms-fa-move:active { - color: #009af7; -} -tbody tr td .llms-fa-edit { - position: absolute; - font-size: 20px; - right: 104px; - color: rgba(88, 88, 91, 0.6); - top: 11px; - cursor: pointer; -} -tbody tr td .llms-fa-edit-lesson:hover { - color: #009af7; - cursor: pointer; -} -tbody tr td .llms-fa-edit-lesson:active { - color: #009af7; -} - -#llms-single-options { - position: relative; - padding: 10px 0; -} - -.llms-single-options table textarea { - width: 96%; - margin: 8px; -} -.option-text { - width: 100%; - margin-top: 10px; -} -.deleteBtn.single-option-delete { - position: absolute; - font-size: 2em; - right: 14px; - color: rgba(88, 88, 91, 0.6); - top: 14px; -} -.single-option-delete:hover { - cursor: pointer; - color: #d54e21; -} -td.llms-table-select, th.llms-table-select { - width: 70%; - select { - width: 100%; - } -} - -.llms-meta-select { - width: 100%; -} - -//these need to go in infusionsoft plugin -.llmsis_cycle { - width: 100%; - float: none; - margin-top: 10px; -} -#llmis-add-new-sub { - margin-bottom: 20px; - margin-left: 10px; -} - -.title -{ - background-color: inherit; - border: inherit; -} - -div[id^="lifterlms-"] .inside { - overflow: visible; -} - -.llms-admin-notice { - position: relative; - .notice-dismiss { - text-decoration: none; - } -} - - - - - -.llms-button-action, -.llms-button-danger, -.llms-button-primary, -.llms-button-secondary { - &.small .dashicons { - font-size: 13px; - height: 13px; - width: 13px; - } -} - - -a.llms-view-as { - line-height: 2; - margin-right: 8px; -} - -.llms-image-field-preview { - max-height: 80px; - vertical-align: middle; - width: auto; -} - -.llms-image-field-remove { - &.hidden { display: none; } -} - -.llms-log-viewer { - background: #fff; - border: 1px solid #e5e5e5; - box-shadow: 0 1px 1px rgba(0,0,0,.04); - margin: 20px 0; - padding: 25px; - - pre { - font-family: monospace; - margin: 0; - padding: 0; - white-space: pre-wrap; - } -} - -.llms-status--tools { - .llms-table { - background: #fff; - border: 1px solid #e5e5e5; - box-shadow: 0 1px 1px rgba(0,0,0,.04); - td, th { - padding: 10px; - vertical-align: top; - } - th { - width: 28%; - } - p { - margin: 0 0 10px; - } - } -} - diff --git a/assets/scss/admin/_quiz-attempt-review.scss b/assets/scss/admin/_quiz-attempt-review.scss deleted file mode 100644 index a4b7d85f41..0000000000 --- a/assets/scss/admin/_quiz-attempt-review.scss +++ /dev/null @@ -1,23 +0,0 @@ -.llms-remarks { - - .llms-remarks-field { - height: 120px; - width: 100%; - } - - input[type="number"] { - width: 60px; - } - - -} - - -button[name="llms_quiz_attempt_action"] { - .save { display: none; } - &.grading { - .default { display: none }; - .save { display: inline; } - } -} - diff --git a/assets/scss/admin/_reporting.scss b/assets/scss/admin/_reporting.scss deleted file mode 100644 index 6392869e35..0000000000 --- a/assets/scss/admin/_reporting.scss +++ /dev/null @@ -1,319 +0,0 @@ -.llms-reporting.wrap { - - .llms-options-page-contents { - background: $color-white; - padding: 20px; - } - - .llms-reporting-nav { - margin: 20px 0; - .llms-nav-tab-wrapper { - margin: 0; - } - } - - .llms-stab-title { - color: $color-brand-dark-blue; - font-size: 36px; - font-weight: 300; - margin-bottom: 20px; - } - - td.id a { - text-decoration: none; - } - - th.name, td.name, - th.title, td.title { text-align: left; } - - th.section-title { - background: #eaeaea; - text-align: left; - } - - td.questions-table { - text-align: left; - - .correct, - .question, - .selected { - text-align: left; - max-width: 300px; - - img { - height: auto; - max-width: 64px; - } - } - } - - table.quiz-attempts { - margin-bottom: 40px; - } - - &.tab--enrollments, - &.tab--sales { - - .llms-options-page-contents { - background: none; - padding: 0; - } - - .llms-nav-item.llms-analytics-form { - color: #414141; - font-size: 13px; - padding: 6px 14px; - - input { - border: 0; - font-size: 13px; - margin: 0; - padding: 3px 6px; - vertical-align: middle; - } - - .select2-container { - input { - width: 100% !important; - } - } - } - - .button.small { - height: 23px; - line-height: 23px; - } - - - .llms-analytics-filters { - display: none; - - .llms-nav-item { - box-sizing: border-box; - width: 100%; - - label { - display: block; - } - } - - .button { - float: right; - } - - } - } - -} - - -.llms-reporting-tab { - - h1, h2, h3, h4, h5, h6 { - margin: 0; - a { - color: $color-brand-dark-blue; - text-decoration: none; - &:hover { - color: $color-brand-blue; - } - } - } - - - .llms-reporting-header { - - .llms-reporting-header-img { - border-radius: 50%; - display: inline-block; - margin-right: 10px; - overflow: hidden; - vertical-align: middle; - img { - display: block; - max-height: 64px; - width: auto; - } - } - - .llms-reporting-header-info { - display: inline-block; - vertical-align: middle; - - } - - } - -} - -.llms-reporting-breadcrumbs { - margin-bottom: 15px; - a { - color: $color-brand-blue; - text-decoration: none; - &:hover { - color: $color-brand-blue-dark; - } - &:after { - content: ' > '; - color: #555; - } - - &:last-child { - color: $color-brand-dark-blue; - &:after { display: none;} - } - } -} - -#llms-students-table .name { - text-align: left; -} - -.llms-reporting-tab-content { - display: flex; - - > header { - @include clearfix; - } - - h3 { - margin-bottom: 20px; - } - - .llms-reporting-tab-filter { - float: right; - position: relative; - margin-right: 0.75em; - width: 180px; - top: -3px; - } - - - .llms-reporting-tab-main { - flex: 3; - } - .llms-reporting-tab-side { - flex: 1; - margin-left: 20px; - } - - > .llms-table-wrap { - flex: 1; - } - -} - - -.llms-reporting-widgets { - @include clearfix; -} - -.llms-reporting-widget { - - border-top: 4px solid $color-brand-blue; - background: #fafafa; - margin-bottom: 0.75em; - padding: 18px 15px 15px; - @include clearfix; - - .fa { - color: #555; - float: left; - font-size: 32px; - margin-right: 10px; - } - - .llms-reporting-widget-data { - line-height: 0.8; - } - - strong { - color: #333; - font-size: 20px; - } - - &.llms-reporting-student-address { - strong { - line-height: 1.1; - } - } - - sup, - .llms-price-currency-symbol { - font-size: 75%; - position: relative; - top: -4px; - vertical-align: baseline; - } - - small { - color: #888; - &.compare { - margin-left: 5px; - &.positive { - color: $color-green; - } - &.negative { - color: $color-red; - } - } - } -} - - -.llms-reporting-event { - border-left: 4px solid #555; - background: #fafafa; - font-size: 11px; - line-height: 1.2; - margin-bottom: 0.75em; - padding: 10px; - @include clearfix; - - &.color--blue { - border-left-color: $color-blue; - } - - &.color--green, - &._enrollment_trigger, - &._is_complete.yes { - border-left-color: $color-green; - } - - &.color--purple, - &._status.enrolled { - border-left-color: $color-purple; - } - - &.color--red, - &._status.expired, - &._status.cancelled { - border-left-color: $color-red; - } - &.color--orange, - &._achievement_earned, - &._certificate_earned, - &._email_sent { - border-left-color: $color-orange; - } - - time { - color: #888; - } - - .llms-student-avatar { - margin-left: 10px; - float: right; - } - - a { - text-decoration: none; - color: inherit; - } - - -} - -@import "../_includes/quiz-result-question-list"; - diff --git a/assets/scss/admin/_tabs.scss b/assets/scss/admin/_tabs.scss deleted file mode 100644 index d7143c6089..0000000000 --- a/assets/scss/admin/_tabs.scss +++ /dev/null @@ -1,105 +0,0 @@ -.llms-nav-tab-wrapper { - background: $color-blue; - margin: 20px 0; - - &.llms-nav-secondary { - background: #e1e1e1; - - .llms-nav-item { - margin: 0; - - .llms-nav-link:hover, - &.llms-active .llms-nav-link { - background: darken( #e1e1e1, 8 ); - } - - } - - .llms-nav-link { - color: #414141; - font-size: 13px; - padding: 8px 14px; - - .dashicons { - font-size: 15px; - height: 15px; - width: 15px; - } - } - - } - - &.llms-nav-text { - background: inherit; - .llms-nav-item { - background: inherit; - &:last-child:after { - display: none; - } - &:after { - content: '|'; - display: inline-block; - margin: 0 3px 0 0; - } - .llms-nav-link:hover, - &.llms-active .llms-nav-link { - background: inherit; - color: $color-brand-blue; - text-decoration: underline; - } - .llms-nav-link { - color: $color-brand-dark-blue; - display: inline-block; - letter-spacing: 0; - margin: 0; - padding: 0; - text-transform: none; - } - } - } - - .llms-nav-items { - @include clearfix; - margin: 0; - } - - .llms-nav-item { - margin: 0; - - .llms-nav-link:hover { - background: $color-brand-blue-dark; - } - &.llms-active .llms-nav-link { - background: $color-brand-dark-blue; - } - - &.llms-active .llms-nav-link { - font-weight: 400; - } - - @media only screen and (min-width: 768px) { - float: left; - - &.llms-nav-item-right { - float: right; - } - } - - } - - .llms-nav-link { - - color: #fff; - cursor: pointer; - display: block; - font-weight: 300; - font-size: 14px; - letter-spacing: 1px; - padding: 9px 18px; - text-align: center; - text-decoration: none; - text-transform: uppercase; - transition: all .3s ease; - - } -} diff --git a/assets/scss/admin/breakpoints/_1030up.scss b/assets/scss/admin/breakpoints/_1030up.scss deleted file mode 100644 index a8d75e1ec4..0000000000 --- a/assets/scss/admin/breakpoints/_1030up.scss +++ /dev/null @@ -1,76 +0,0 @@ -/****************************************************************** - -Desktop Stylsheet - -******************************************************************/ - -//option page tab menu -.llms-nav-tab { - display: inline-block; - width: 33.333%; -} -.llms-nav-tab-settings { - display: inline-block; - width: 25%; -} - -//select box form wrapper -#llms-form-wrapper { - .llms-select { - display: inline-block; - width: 47.5%; - &:first-child { - margin-right: 5%; - } - - }.llms-filter-options { - display: inline-block; - width: 47.5%; - - &.date-filter { - margin-right: 5%; - }.llms-date-select { - margin-bottom: 0; - } - - }.llms-date-select { - width: 47.5%; - - &:first-child { - margin-right: 5% - } - - } -} - -.llms-widget-row { - @include clearfix; - .llms-widget-1-5 { - vertical-align: top; - width: 20%; - float: left; - box-sizing: border-box; - padding: 0 5px; - } - .llms-widget-1-4 { - vertical-align: top; - width: 25%; - float: left; - box-sizing: border-box; - padding: 0 5px; - } - .llms-widget-1-3 { - width: 33.3%; - float: left; - box-sizing: border-box; - padding: 0 5px; - } - .llms-widget-1-2 { - width: 50%; - float: left; - box-sizing: border-box; - padding: 0 5px; - vertical-align: top; - } - -} diff --git a/assets/scss/admin/breakpoints/_1240up.scss b/assets/scss/admin/breakpoints/_1240up.scss deleted file mode 100644 index 1712dcfe66..0000000000 --- a/assets/scss/admin/breakpoints/_1240up.scss +++ /dev/null @@ -1,11 +0,0 @@ -/****************************************************************** - -large Monitor Stylsheet - -******************************************************************/ - -.llms-nav-tab-filters, -.llms-nav-tab-settings { - float: left; - width: 12.5%; -} diff --git a/assets/scss/admin/breakpoints/_481up.scss b/assets/scss/admin/breakpoints/_481up.scss deleted file mode 100644 index 05e7bc2f76..0000000000 --- a/assets/scss/admin/breakpoints/_481up.scss +++ /dev/null @@ -1,15 +0,0 @@ -/****************************************************************** - -Larger Phones - -******************************************************************/ - -//select box form wrapper -#llms-form-wrapper { - - .llms-checkbox { - width: 33%; - //text-align: center; - - } -} diff --git a/assets/scss/admin/breakpoints/_768up.scss b/assets/scss/admin/breakpoints/_768up.scss deleted file mode 100644 index c5937b9757..0000000000 --- a/assets/scss/admin/breakpoints/_768up.scss +++ /dev/null @@ -1,73 +0,0 @@ -/****************************************************************** - -Tablets and small computers - -******************************************************************/ - -ul.tabs li{ - display: inline-block; - } - -//option page tab menu -.llms-nav-tab { - display: inline-block; - width: 33%; -} -.llms-nav-tab-settings { - display: inline-block; - width: 25%; -} - -//select box form wrapper -#llms-form-wrapper { - .llms-select { - width: 50%; - max-width: 500px; - - }.llms-filter-options { - width: 50%; - //display: inline-block; - max-width: 500px; - - }.llms-date-select { - width: 47.5%; - - &:first-child { - margin-right: 5% - } - - } -} - -.llms-widget { - input[type="text"], - input[type="password"], - input[type="datetime"], - input[type="datetime-local"], - input[type="date"], - input[type="month"], - input[type="time"], - input[type="week"], - input[type="number"], - input[type="email"], - input[type="url"], - input[type="search"], - input[type="tel"], - input[type="color"], - select, - textarea, { - width: 50%; - - &.medium { width: 30%; } - &.small { width: 20%; } - &.tiny { width: 10%; } - } - - .form-table th { - width: 140px; - } - -} - - - diff --git a/assets/scss/admin/breakpoints/_base.scss b/assets/scss/admin/breakpoints/_base.scss deleted file mode 100644 index 4e196a12a8..0000000000 --- a/assets/scss/admin/breakpoints/_base.scss +++ /dev/null @@ -1,93 +0,0 @@ -/****************************************************************** - -Base Mobile - -******************************************************************/ - -.llms-nav-tab, -.llms-nav-tab-filters { - display: block; - width: 100%; -} - -form.llms-nav-tab-filters.full-width { - width: 100%; - - label { - display: inline-block; - width: 10%; - text-align: left; - } - - .select2-container { - width: 85% !important; - } -} - -.llms-nav-tab-settings { - display: block; - width: 100%; -} - -//select box form wrapper -#llms-form-wrapper { - .llms-select { - width: 100%; - margin-bottom: 20px; - - }.llms-checkbox { - display: inline-block; - width: 100%; - text-align: left; - - }.llms-filter-options { - width: 100%; - //margin-bottom: 20px; - - }.llms-date-select { - width: 100%; - display: inline-block; - margin-bottom: 20px; - input[type="text"] { - width: 100%; - } - - }.llms-search-button { - //display: inline-block; - //width: 30%; - #llms-search-button { - - //float: right; - } - - } - -} - -// .llms-widget-full { -// &.top { -// margin-top: 20px; -// } -// } -// .llms-widget { -// .form-table td { -// padding: 15px 0; -// ul { margin: 5px 0 0; } - - -// .conditional-field { -// display: none; -// margin-left: 25px; -// } -// .conditional-radio:checked ~ .conditional-field { -// display: block; -// } - - -// } -// } - -ul.tabs li{ - display: block; - } - diff --git a/assets/scss/admin/metaboxes/_builder-launcher.scss b/assets/scss/admin/metaboxes/_builder-launcher.scss deleted file mode 100644 index 2704fe7895..0000000000 --- a/assets/scss/admin/metaboxes/_builder-launcher.scss +++ /dev/null @@ -1,5 +0,0 @@ -.llms-builder-launcher { - .llms-button-primary { - box-sizing: border-box; - } -} diff --git a/assets/scss/admin/metaboxes/_llms-metabox.scss b/assets/scss/admin/metaboxes/_llms-metabox.scss deleted file mode 100644 index 9d1ce3b059..0000000000 --- a/assets/scss/admin/metaboxes/_llms-metabox.scss +++ /dev/null @@ -1,176 +0,0 @@ -#poststuff .llms-metabox { - - @extend %cf; - padding: 5px; - - h2, h3, h6 { - font-weight: 300; - margin: 0; - padding: 0; - } - - h2 { - font-size: 22px; - } - - h3 { - color: #777; - font-size: 16px; - } - - h4 { - border-bottom: 1px solid #e5e5e5; - padding: 0; - margin: 0; - } - - .llms-transaction-test-mode { - background: #ffffd7; - font-style: italic; - left: 0; - padding: 2px; - position: absolute; - right: 0; - top: 0; - text-align: center; - } - - .llms-error { - color: $color-red; - font-style: italic; - } - - a.llms-editable { - color: $color-grey; - text-decoration: none; - &:hover { - color: $color-brand-blue; - } - } - - h4 a.llms-editable { float: right; } - -} - -.llms-metabox-section { - background: #fff; - margin-top: 25px; - position: relative; - - &.no-top-margin { - margin-top: 0; - } - - .llms-metabox-field { - margin: 15px 0; - position: relative; - label { - color: #777; - display: block; - margin-bottom: 5px; - font-weight: 500; - vertical-align: baseline; - } - - select, - textarea, - input[type="text"], - input[type="number"] { - width: 100%; - } - - input.md-text { - width: 105px; - } - - input.sm-text { - width: 45px; - } - - - .llms-datetime-field { - - .llms-date-input { - width: 95px; - } - .llms-time-input { - width: 45px; - } - em { - font-style: normal; - padding: 0 3px; - } - - } - - } - - -} - -.llms-collapsible { - - @extend %clearfix; - - border: 1px solid #e5e5e5; - position: relative; - margin-top: 0; - margin-bottom: -1px; - - &:last-child { - margin-bottom: 0; - } - - &.opened .llms-collapsible-header { - .dashicons-arrow-down { - display: none; - } - .dashicons-arrow-up { - display: inline; - } - } - - .llms-collapsible-header { - @extend %clearfix; - padding: 10px; - - h3 { - color: #777; - margin: 0; - font-size: 16px; - } - - .dashicons-arrow-up { - display: inline; - } - .dashicons-arrow-up { - display: none; - } - - a { - text-decoration: none; - } - - .dashicons { - color: #777; - cursor: pointer; - transition: color .4s ease; - &:hover { - color: #069cb5; - } - - &.dashicons-trash:hover, - &.dashicons-no:hover { - color: $color-danger; - } - } - - } - - .llms-collapsible-body { - @extend %clearfix; - display: none; - padding: 10px; - } - -} diff --git a/assets/scss/admin/metaboxes/_metabox-field-repeater.scss b/assets/scss/admin/metaboxes/_metabox-field-repeater.scss deleted file mode 100644 index 439a4e6849..0000000000 --- a/assets/scss/admin/metaboxes/_metabox-field-repeater.scss +++ /dev/null @@ -1,37 +0,0 @@ -// ahhhhhhhh -.llms-mb-container .tab-content ul:not(.select2-selection__rendered).llms-mb-repeater-fields > li.llms-mb-list { - border-bottom: none; - padding: 0 0 10px; -} - -.llms-mb-list.repeater { - - .llms-repeater-rows { - position: relative; - margin-top: 10px; - min-height: 10px; - - &.dragging { - background: #efefef; - box-shadow: inset 0 0 0 1px #e5e5e5; - } - } - - .llms-repeater-row { - background: #fff; - } - - .llms-mb-repeater-fields { - - } - - .llms-mb-repeater-footer { - text-align: right; - margin-top: 20px; - } - - .tmce-active .wp-editor-area { - color: #32373c; // wp core default color - } - -} diff --git a/assets/scss/admin/metaboxes/_metabox-instructors.scss b/assets/scss/admin/metaboxes/_metabox-instructors.scss deleted file mode 100644 index f03294ceed..0000000000 --- a/assets/scss/admin/metaboxes/_metabox-instructors.scss +++ /dev/null @@ -1,9 +0,0 @@ -._llms_instructors_data.repeater { - .llms-repeater-rows .llms-repeater-row:first-child { - .llms-repeater-remove { display: none; } - } - - .llms-mb-list { - padding: 0 5px !important; - } -} diff --git a/assets/scss/admin/metaboxes/_metabox-orders.scss b/assets/scss/admin/metaboxes/_metabox-orders.scss deleted file mode 100644 index 3bf3063607..0000000000 --- a/assets/scss/admin/metaboxes/_metabox-orders.scss +++ /dev/null @@ -1,45 +0,0 @@ -.post-type-llms_order #post-body-content { display: none; } -#lifterlms-order-details { - .handlediv, - .handlediv.button-link, - .hndle.ui-sortable-handle { display: none;} - .inside { - padding: 20px; - margin-top: 0; - - } -} - -// failed transaction color -.llms-table tbody tr.llms-txn-failed td { - background-color: rgba( $color-red, 0.5 ); - border-bottom-color: rgba( $color-red, 0.5 ); -} - -// refunded transaction color -.llms-table tbody tr.llms-txn-refunded td { - background-color: rgba( orange, 0.5 ); - border-bottom-color: rgba( orange, 0.5 ); -} - -.llms-txn-refund-form, -.llms-manual-txn-form { - .llms-metabox-section { - margin-top: 0; - } - .llms-metabox-field { - text-align: right; - input { - &[type="number"] { max-width: 100px; } - &[type="text"] { max-width: 340px; } - - } - } -} - -.llms-manual-txn-form { - background-color: #eaeaea; - .llms-metabox-section { - background-color: #eaeaea; - } -} diff --git a/assets/scss/admin/metaboxes/_metabox-product.scss b/assets/scss/admin/metaboxes/_metabox-product.scss deleted file mode 100644 index 0e84dc5213..0000000000 --- a/assets/scss/admin/metaboxes/_metabox-product.scss +++ /dev/null @@ -1,48 +0,0 @@ -#llms-new-access-plan-model { - display: none; -} - -#llms-delete-plan-modal { - .llms-button-danger { - display: block; - margin: 0 auto; - text-align: center; - width: 60px; - } -} - -.llms-access-plans { - @extend %clearfix; - margin-top: 25px; - - > p { display: none; } - > p:last-child { display: block; } - - &.dragging { - background: #efefef; - box-shadow: inset 0 0 0 1px #e5e5e5; - } - -} - -.llms-access-plan { - - .llms-plan-link, - [data-controller] { - display: none; - } - - &:hover, - &.opened { - .llms-plan-link { - display: inline-block; - } - } - - - - .llms-metabox-field { - margin: 5px 0; - } - -} diff --git a/assets/scss/admin/metaboxes/_metabox-students.scss b/assets/scss/admin/metaboxes/_metabox-students.scss deleted file mode 100644 index 7b0aef36ef..0000000000 --- a/assets/scss/admin/metaboxes/_metabox-students.scss +++ /dev/null @@ -1,15 +0,0 @@ -.llms-metabox-students { - .llms-table { - tr .name { - text-align: left; - } - } - - .llms-add-student:hover { - color: $color-green; - } - .llms-remove-student:hover { - color: $color-red; - } - -} diff --git a/assets/scss/admin/modules/_course-outline.scss b/assets/scss/admin/modules/_course-outline.scss deleted file mode 100644 index df7ee0bae8..0000000000 --- a/assets/scss/admin/modules/_course-outline.scss +++ /dev/null @@ -1,361 +0,0 @@ -/****************************************************************** - -Course Outline - -******************************************************************/ -#llms-course-outline { - box-sizing: border-box; - width: 100%; - - #llms-ouline-header { - box-sizing: border-box; - background: #fafafa; - border: 1px solid #e1e1e1; - width: 100%; - padding: 16px 24px; - position: relative; - border-radius: 4px 4px 0 0; - - .outline-body { - width: 100%; - padding: 20px; - } - - } -} - - -.clear-fix:after -{ - content: "."; - display: block; - clear: both; - visibility: hidden; - line-height: 0; - height: 0; -} - -.clear-fix -{ - zoom: 1; -} - -h1.outline-title { - font-size: 16px; - font-weight: 400; - -} - -.menu-button { - position: relative; - float: right; - width: auto; -} - - -#llms-outline-menu { - visibility:hidden; - transition: opacity 0.3s 0.6s, visibility 0s 0.9s; - opacity: 0; - position: absolute; - left: -84px; - bottom: 40px; - z-index: 6; -} - -#llms-outline-menu.fade-in { - visibility: visible; - opacity: 1; - transition: opacity 0.1s 0s, visibility 0s 0s; - animation: cd-move-in 0.4s; - animation-fill-mode: forwards; -} -@keyframes cd-move-in { - 0% { - transform: translateY(2.5vh); - } - 65% { - transform: translateY(-1.5vh); - } - 100% { - transform: translateY(0vh); - } -} - - -#triangle { - border-width: 2px 0 0 2px; - width: 10px; - height: 10px; - -webkit-transform: rotate(228deg); - -moz-transform: rotate(45deg); - -o-transform: rotate(45deg); - z-index: 1; - background: #313130; - position: absolute; - bottom: -5px; - left: 110px; - z-index: 1; -} -#tooltip_menu { - background: #313130; - -webkit-border-radius: .5em; - -moz-border-radius: .5em; - border-radius: .5em; - width: 200px; - -webkit-box-shadow: 0px 0px 3px rgba(0,0,0,.5); - -moz-box-shadow: 0px 0px 3px rgba(0,0,0,.5); - box-shadow: 0px 0px 3px rgba(0,0,0,.5); - padding: 2px 16px; - -} -#tooltip_menu a { - border-bottom: 1px solid #565656; - z-index: 2; - padding: 16px 10px; - margin: 0; - display: block; - text-decoration: none; - color: $color-white; - font-size: 13px; - transition: all 0.3s ease-in; - text-align: left; - - &:last-child { - border-bottom: 0; - } -} -#tooltip_menu a:hover { - //background: #000; - color: $color-blue; - padding-left: 20px; - //text-shadow: 1px 0px 10px #000; - -} -#tooltip_menu a img { - position: relative; - top: 5px; - border: 0; -} - -.menu-icon { - color: $color-blue; -} -.sortablewrapper { - display: block; -} -#llms_coure_outline_sort { - padding: 0; - background: $color-white; -} -.outline-body { - background: $color-white; -} -.section-icon, .tree-icon { - color: #AAACAD; -} -.ui-state-default.llms-lesson { - position: relative; - padding: 10px 10px 10px 27px; - margin: 0 0 0 6px; - border: 0; - background: $color-white; -} -.llms-lesson:hover, .llms-section:hover { - background: #fafafa; -} -.ui-state-default.llms-section { - margin: 0; - border: 0; - background: $color-white; - color: $color-cinder; -} -.llms-section { - position: relative; - padding: 10px; -} -.llms-lesson-order:before { - content: ""; - position: absolute; - width: 26px; - border-bottom: 1px #BBBBBB solid; - left: -26px; - top: 20px; -} - -.llms-lesson:last-child:before { - height: 44px; -} - -.llms-section, .llms-lesson { - .section-content-wrapper { - z-index: 5; - position: relative; - background: $color-white; - min-height: 50px; - } - .description { - - position: relative; - padding: 10px 0; - color: $color-cinder; - - p { - margin-bottom: 0; - color: $color-grey; - } - } - .list-options { - z-index: 5; - position: relative; - //margin-top: 10px; - } - .list-lesson-details { - margin-top: 10px; - } - - .llms-edit-section-link, - .llms-edit-lesson-link, - a.llms-remove-lesson-link, - a.llms-edit-lesson-content-link, - a.llms-delete-section-link { - color: $color-white !important; - margin-left: 3px; - float: right; - - .dashicons { - // height: 16px; - // font-size: 16px; - vertical-align: middle; - // width: 16px; - } - - // //width: 20px; - // /* height: 30px; */ - // background: $color-lightblue; - // display: block; - // padding: 5px; - - // margin-left: 10px; - // margin-top: 10px; - // transition: ease .3s all; - - // &:hover { - // background: $color-darkblue; - // } - // .icon.button-icon { - // fill: $color-white; - // } - } - a.llms-delete-section-link { - margin-right: 10px; - } - -} - -a.llms-voucher-delete { -// a.llms-delete-section-link, -// a.llms-remove-lesson-link { - display: block; - padding: 5px; - background: #e26049; - float: right; - color: $color-white !important; - transition: ease .3s all; - - &:hover { - background: #af3a26; - } - - .icon.button-icon { - fill: $color-white; - } -} - -// a.llms-delete-section-link, -// a.llms-remove-lesson-link { -// margin-top: 10px; -// margin-left: 10px; -// } - -.llms-lesson-tree { - position: relative; - margin: 0; - min-height: 10px; - width: 100%; - - &:before { - content: ""; - position: absolute; - top: -23px; - bottom: 61px; - border-left: 1px #bbb solid; - left: 6px; - z-index: 10; - } -} - -/** - * Tooltip - */ -.llms-lesson-details { - float: right; -} - -.tooltip{ - display: inline; - position: relative; - margin-right: 10px; - cursor:default; -} -.tooltip:last-child { - margin-right: 0; -} -.tooltip:hover:after{ - background: #313130; - border-radius: 5px; - bottom: 26px; - color: #fff; - content: attr(title); - left: -75px; - padding: 5px 15px; - position: absolute; - text-align: center; - min-width: 150px; - text-shadow: none; // prevent weirdness if adding a tooltip to a WordPress core UI button - z-index: 98; -} -.tooltip:hover:before{ - border: solid; - border-color: #313130 transparent; - border-width: 6px 6px 0 6px; - bottom: 20px; - content: ""; - left: 30%; - position: absolute; - z-index: 99; -} - -.llms-mb-list { - - label { - font-weight: bold; - width: 100%; - display: block; - } - - .input-full { - width: 100%; - } -} - -/** - * sortable - */ -.placeholder { - border: 1px solid $color-blue; - border-left: 1px solid #bbb; - background: $color-blue; - margin-left: 6px; -} - diff --git a/assets/scss/admin/modules/_forms.scss b/assets/scss/admin/modules/_forms.scss deleted file mode 100644 index 8ecdda0117..0000000000 --- a/assets/scss/admin/modules/_forms.scss +++ /dev/null @@ -1,171 +0,0 @@ -/****************************************************************** - -Form Styles - -******************************************************************/ - -// lifterlms form wrapper -#llms-form-wrapper { - - // setup defaults - input[type="text"], - input[type="password"], - input[type="datetime"], - input[type="datetime-local"], - input[type="date"], - input[type="month"], - input[type="time"], - input[type="week"], - input[type="number"], - input[type="email"], - input[type="url"], - input[type="search"], - input[type="tel"], - input[type="color"], - input[type="checkbox"], - select, - textarea, - .llms-field { - - // a focused input (or hovered on) - &:focus, - &:active { - - } // end hover or focus - } - - // sub wrapper for seach filter form (analytics) - .llms-search-form-wrapper { - border-bottom: 1px solid $color-grey; - margin: 20px 0; - - } - - - #llms_analytics_search { - border:none !important; - text-shadow: none !important; - border: none !important; - outline: none !important; - box-shadow: none !important; - margin: 0 !important; - color: $color-white !important; - background: $color-blue !important; - border-radius: 0; - transition: .5s; - - &:hover { - background: $color-darkblue !important; - - }&:active { - background: $color-lightblue !important; - } - } - -} // end input defaults - - -#llms-skip-setup-form { - .llms-admin-link { - background:none!important; - border:none; - padding:0!important; - color:#0074a2; - cursor:pointer; - &:hover { - color:#2ea2cc - }&:focus{ - color:#124964; - } - - } - -} - -/** - * Toggle Switch ( replaces checkbox on admin panels ) - */ -.llms-switch { - position: relative; - width: 100px; - float: right; -} - -.llms-toggle { - position: absolute; - margin-left: -9999px; - visibility: hidden; -} -.llms-toggle + label { - display: block; - position: relative; - cursor: pointer; - outline: none; - user-select: none; -} -input.llms-toggle-round + label { - padding: 2px; - width: 100px; - height: 50px; - background-color: none; - border-radius: 5px; - content: 'On'; -} -input.llms-toggle-round + label:before, -input.llms-toggle-round + label:after { - display: block; - position: absolute; - top: 1px; - left: 1px; - bottom: 1px; - content: ""; -} -input.llms-toggle-round + label:before { - right: 1px; - background-color: #e26049; - border-radius: 5px; - transition: background 0.4s; -} -input.llms-toggle-round + label:after { - width: 38px; - height: 38px; - top: 8px; - left: 8px; - background-color: #fff; - border-radius: 5px; - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3); - transition: margin 0.4s; - z-index: 3; -} -input.llms-toggle-round:checked + label:before { - background-color: #3abba5; -} -input.llms-toggle-round:checked + label:after { - margin-left: 50px; -} - -.llms-toggle-icon-on { - content: ""; - position: absolute; - left: 18px; - top: 15px; - z-index: 2; - color: #2d9584; -} -.llms-toggle-icon-off { - content: ""; - position: absolute; - right: 13px; - top: 15px; - z-index: 2; - color: #af3a26; - -} -.toggle-icon { - width: 30px; - height: 30px; -} -.toggle-description { - float: left; -} - diff --git a/assets/scss/admin/modules/_icons.scss b/assets/scss/admin/modules/_icons.scss deleted file mode 100644 index b937c1072c..0000000000 --- a/assets/scss/admin/modules/_icons.scss +++ /dev/null @@ -1,92 +0,0 @@ -/****************************************************************** - -SVG Styles - -******************************************************************/ - -svg { - &.icon { - height: 24px; - width: 24px; - display: inline-block; - fill: currentColor; // Inherit color - vertical-align: baseline; // Options: baseline, sub, super, text-top, text-bottom, middle, top, bottom - - // Different styling for when an icon appears in a button element - button & { - height: 18px; - width: 18px; - margin: 4px -4px 0 4px; - filter: drop-shadow( 0 1px #eee ); - float: right; - - }&.menu-icon { - height: 20px; - width: 20px; - display: inline-block; - fill: currentColor; - vertical-align: text-bottom; - margin-right: 10px; - - }&.tree-icon { - height: 13px; - width: 13px; - vertical-align: middle; - - }&.section-icon { - height: 16px; - width: 16px; - vertical-align: text-bottom; - - }&.button-icon { - height: 16px; - width: 16px; - vertical-align: text-bottom; - - }&.button-icon-attr { - height: 10px; - width: 10px; - vertical-align: middle; - - }&.list-icon { - height: 12px; - width: 12px; - vertical-align: middle; - - &.on { - color: $color-blue; - - }&.off { - color: $color-cinder; - } - - }&.detail-icon { - height: 16px; - width: 16px; - vertical-align: text-bottom; - cursor:default; - - &.on { - color: $color-blue; - - }&.off { - color: $color-lightgrey; - } - } - - } - - &.icon-ion {} - - &.icon-ion-edit {} - - // rotate for arrow tips - &.icon-ion-arrow-up { - transform: rotate(90deg); - } - - use { - pointer-events: none; - } - -} \ No newline at end of file diff --git a/assets/scss/admin/modules/_llms-order-note.scss b/assets/scss/admin/modules/_llms-order-note.scss deleted file mode 100644 index b055ebb144..0000000000 --- a/assets/scss/admin/modules/_llms-order-note.scss +++ /dev/null @@ -1,35 +0,0 @@ -.llms-order-note { - - .llms-order-note-content { - background: #efefef; - margin-bottom: 10px; - padding: 10px; - position: relative; - &:after { - border-style: solid; - border-color: #efefef transparent; - border-width: 10px 10px 0 0; - bottom: -10px; - content: ''; - display: block; - height: 0; - left: 20px; - position: absolute; - width: 0; - - } - p { - font-size: 13px; - margin: 0; - line-height: 1.5; - } - } - - .llms-order-note-meta { - color: #999; - font-size: 11px; - margin-left: 10px; - } - - -} diff --git a/assets/scss/admin/modules/_mb-tabs.scss b/assets/scss/admin/modules/_mb-tabs.scss deleted file mode 100644 index d409d9b635..0000000000 --- a/assets/scss/admin/modules/_mb-tabs.scss +++ /dev/null @@ -1,58 +0,0 @@ -/****************************************************************** - -Metabox Tabs - -******************************************************************/ - -// free space up if the metabox is on the side -#side-sortables .tab-content { - padding: 0; -} - -.llms-mb-container .tab-content{ - display: none; - background: $color-white; - padding: 15px; - - ul:not(.select2-selection__rendered) { - margin: 0; - - > li { - padding: 20px 0; - margin: 0; - border-bottom: 1px solid $color-lightgrey; - - &.select:not([class*="d-"]) { - width: 100%; - } - - &:last-child { - border: 0; - padding-bottom: 0; - - } - - &.top { - border-bottom: 0; - padding-bottom: 0; - } - - } - } - - .full-width { width: 100%; } - - #wp-content-editor-tools { - background: none; - } - -} - -.llms-mb-container .tab-content.llms-active{ - display: inherit; -} - - -.llms-mb-container .tab-content .no-border { - border-bottom: 0px; -} diff --git a/assets/scss/admin/modules/_merge-codes.scss b/assets/scss/admin/modules/_merge-codes.scss deleted file mode 100644 index dc31a9789e..0000000000 --- a/assets/scss/admin/modules/_merge-codes.scss +++ /dev/null @@ -1,58 +0,0 @@ -.button.llms-merge-code-button { - vertical-align: middle; - img { - margin-right: 3px; - margin-top: -3px; - vertical-align: middle; - } -} - -.llms-mb-container { - .button.llms-merge-code-button img { margin-right: 4px; } - .llms-merge-code-wrapper { - float: right; - top: -5px; - } -} - -.llms-merge-code-wrapper { - display: inline; - position: relative; -} - -.llms-merge-codes { - background: #f7f7f7; - border: 1px solid #ccc; - border-radius: 3px; - box-shadow: 0 1px 0 #ccc; - color: #555; - display: none; - left: 1px; - overflow: hidden; - position: absolute; - top: 30px; - width: 160px; - - ul { - margin: 0; - padding: 0; - } - - li { - cursor: pointer; - margin: 0; - padding: 4px 8px !important; - border-bottom: 1px solid #ccc; - } - - li:hover { - color: #23282d; - background: #fefefe; - } - - &.active { - display: block; - z-index: 777; - } - -} diff --git a/assets/scss/admin/modules/_top-modal.scss b/assets/scss/admin/modules/_top-modal.scss deleted file mode 100644 index 9a118bcebc..0000000000 --- a/assets/scss/admin/modules/_top-modal.scss +++ /dev/null @@ -1,203 +0,0 @@ -/****************************************************************** - -Styles for topModal modal - -******************************************************************/ - -/** - * Base modal styles - */ -.topModal { - display:none; - position:relative; - border:4px solid #808080; - background:#fff; - z-index:1000001; - padding:2px; - max-width:500px; - margin: 34px auto 0; - box-sizing: border-box; - box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); - background-color: #ffffff; - border-radius: 2px; - border: 1px solid #dddddd; - -}.topModalClose { - float:right; - cursor:pointer; - margin-right: 10px; - margin-top: 10px; - -}.topModalContainer { - display: none; - overflow: auto; - overflow-y: hidden; - position: fixed; - top: 0 !important; - right: 0; - bottom: 0; - left: 0; - -webkit-overflow-scrolling: touch; - width: auto !important; - margin-left: 0 !important; - background-color: transparent !important; - z-index: 100002 !important; - -}.topModalBackground { - display:none; - background:#000; - position:fixed; - height:100%; - width:100%; - top:0 !important; - left:0; - margin-left: 0 !important; - z-index: 100002 !important; - box-sizing: border-box; - overflow: auto; - overflow-y: hidden; - -}body.modal-open { - overflow: hidden; - -}.llms-modal-header { - border-top-right-radius: 1px; - border-top-left-radius: 1px; - background: $color-blue; - color: #eeeeee; - padding: 10px 15px; - font-size: 18px; - -}#llms-icon-modal-close { - width:16px; - height: 16px; - fill: $color-white; - -}.llms-modal-content { - padding: 20px; - - h3 { - margin-top: 0; - } - -} - -/** - * Custom Modal Styles for LifterLMS - */ -.llms-modal-form { - - h1 { - margin-top: 0; - } - - input[type=text] { - width: 100%; - } - - textarea, - input[type="text"], - input[type="password"], - input[type="file"], - input[type="datetime"], - input[type="datetime-local"], - input[type="date"], - input[type="month"], - input[type="time"], - input[type="week"], - input[type="number"], - input[type="email"], - input[type="url"], - input[type="search"], - input[type="tel"], - input[type="color"] { - padding: 0 .4em 0 .4em; - margin-bottom: 2em; - vertical-align: middle; - border-radius: 3px; - min-width: 50px; - max-width: 635px; - width: 100%; - min-height: 32px; - background-color: #fff; - border: 1px solid $color-lightgrey; - margin: 0 0 24px 0; - outline: none; - transition: border 0.3s ease-in-out 0s; - - &:focus { - background: $color-white; - border: 1px solid $color-blue; - - } - } - - textarea { - padding: .4em !important; - height: 100px !important; - border-radius: 3px; - vertical-align: middle; - min-height: 32px; - outline: none; - box-sizing: border-box; - - &:focus { - background: $color-white; - border: 1px solid $color-blue; - - } - - } - - .chosen-container-single .chosen-single { - border-radius: 3px; - vertical-align: middle; - min-height: 32px; - border: 1px solid $color-lightgrey; - width: 100%; - background: $color-white !important; - outline: none; - box-sizing: border-box; - box-shadow: 0 0 0 #fff; - line-height: 32px; - margin: 0 0 24px 0; - - &:focus { - background: $color-white; - border: 1px solid $color-blue; - } - } - - .chosen-container-single .chosen-single div b { - margin-top: 4px; - } - - .chosen-search input[type=text] { - border: 1px solid $color-lightgrey; - - &:focus { - background-color: $color-white; - border: 1px solid $color-blue; - } - - } - - .chosen-container-single .chosen-drop { - margin-top: -28px; - } - - .llms-button-primary, .llms-button-secondary { - padding: 10px 10px; - border-radius: 0; - transition: .5s; - box-shadow: 0 1px 1px #ccc; - - &.full { - width: 100%; - } - } -} - -.modal-open .select2-dropdown { - z-index: 1000005; -} diff --git a/assets/scss/admin/modules/_voucher.scss b/assets/scss/admin/modules/_voucher.scss deleted file mode 100644 index a20331ca8d..0000000000 --- a/assets/scss/admin/modules/_voucher.scss +++ /dev/null @@ -1,118 +0,0 @@ -.llms-voucher-codes-wrapper, -.llms-voucher-redemption-wrapper { - - table { - width: 100%; - border-collapse: collapse; - - th, td { - border: none; - } - - thead { - background-color: $color-lightblue; - color:#fff; - th { - padding: 10px 10px; - } - } - - tr { - counter-increment: row-counter; - &:nth-child(even) { - background-color: #F1F1F1; - } - - td { - padding: 5px; - &:first-child:before { - content: counter( row-counter ); - } - } - } - } -} - -.llms-voucher-codes-wrapper { - - table { - width: 100%; - border-collapse: collapse; - - th, td { - border: none; - } - - thead { - background-color: $color-lightblue; - color:#fff; - } - - tr { - &:nth-child(even) { - background-color: #F1F1F1; - } - - td { - - span { - display: inline-block; - min-width: 30px; - } - } - } - } - - button { - cursor: pointer; - } - - .llms-voucher-delete { - float: right; - margin-right: 15px; - } - - .llms-voucher-uses { - width: 50px; - } - - .llms-voucher-add-codes { - float: right; - - input[type="text"] { - width: 30px; - } - } -} - -.llms-voucher-export-wrapper { - - .llms-voucher-export-type { - width: 100%; - - p { - margin: 0 0 0 15px; - } - } - - .llms-voucher-email-wrapper { - width: 100%; - margin: 25px 0; - - input[type="text"] { - width: 100%; - } - - p { - margin: 0; - } - } - - > button { - float: right; - } -} - -.postbox .inside { - overflow: auto; -} diff --git a/assets/scss/admin/modules/_widgets.scss b/assets/scss/admin/modules/_widgets.scss deleted file mode 100644 index d522a4a11c..0000000000 --- a/assets/scss/admin/modules/_widgets.scss +++ /dev/null @@ -1,186 +0,0 @@ -.llms-widget { - background: $color-white; - box-sizing: border-box; - margin-bottom: 20px; - padding: 10px 20px; - position: relative; - width: 100%; - - &.alt { - - border: 1px solid $color-lightgrey; - background-color: #efefef; - margin-bottom: 10px; - - .llms-label { - color: #777; - font-size: 14px; - margin-bottom: 10px; - padding-bottom: 5px; - } - - h2 { - color: #444; - font-weight: 300; - } - - } - - h1 { - font-size: 2.4em; - } - - h2 { - font-size: 1.8em; - } - - .llms-label { - border-bottom: 1px solid $color-lightgrey; - box-sizing: border-box; - color: $color-grey; - font-size: 18px; - font-weight: 300; - letter-spacing: 1px; - margin: 0 0 15px; - padding-bottom: 10px; - text-align: center; - text-transform: uppercase; - } - - .llms-chart { - width: 100%; - padding: 10px; - box-sizing: border-box; - } - - mark.yes { - background-color: #7ad03a; - } - - .llms-subtitle { - margin-bottom: 0; - } - - .spinner { - float: none; - left: 50%; - margin: -10px 0 0 -10px; - position: absolute; - top: 50%; - z-index: 2; - } - - &.is-loading { - - &:before { - background: $color-white; - bottom: 0; - content: ''; - left: 0; - opacity: 0.9; - position: absolute; - right: 0; - top: 0; - z-index: 1; - } - - .spinner { - visibility: visible; - } - - } - - td[colspan="2"] { - padding-left: 0; - } - -} - -.llms-widget-1-3, -.llms-widget-1-4, -.llms-widget-1-5 { - text-align: center; -} - - -.llms-widget { - .llms-widget-info-toggle { - color: $color-lightgrey; - cursor: pointer; - font-size: 16px; - position: absolute; - right: 25px; - top: 13px; - } - - &.info-showing { - .llms-widget-info { - display: block; - } - } -} -.llms-widget-info { - background: $color-cinder; - color: $color-white; - bottom: -50px; - display: none; - padding: 15px; - position: absolute; - text-align: center; - left: 10px; - right: 15px; - z-index: 3; - &:before { - content: ''; - border: 12px solid transparent; - border-bottom-color: $color-cinder; - left: 50%; - margin-left: -12px; - position: absolute; - top: -24px; - } - - p { - margin: 0; - } - -} - - -.llms-user-profile { - padding: 0 20px; -} - -.llms-banner-image { - padding-top: 20px; - img { display: block; } - // padding: 5px; -} - -.llms-widget-row { - @include clearfix(); -} - -.llms-widget-row .no-padding { - padding: 0 !important; -} - -.optin-form-wrapper { - vertical-align: top; - - .optin-form { - height: 335px; - padding-top: 50px; - box-sizing: border-box; - background: #fff; - margin: 5px; - - ._label { - font-weight: bold; - } - - input { - margin-bottom: 10px; - } - } -} diff --git a/assets/scss/admin/partials/_grid.scss b/assets/scss/admin/partials/_grid.scss deleted file mode 100644 index add6846568..0000000000 --- a/assets/scss/admin/partials/_grid.scss +++ /dev/null @@ -1,276 +0,0 @@ -/****************************************************************** - -Grids for Breakpoints - -******************************************************************/ - -// using a mixin since we can't use placeholder selectors -@mixin grid-col { - float: left; - padding-right: 0.75em; - box-sizing: border-box; - -} - -// the last column -.last-col { - float: right; - padding-right: 0 !important; -} -.last-col:after { - clear: both; -} - -/* -Mobile Grid Styles -These are the widths for the mobile grid. -There are four types, but you can add or customize -them however you see fit. -*/ -@media (max-width: 767px) { - - .m-all { - @include grid-col; - width: 100%; - padding-right: 0; - } - - .m-1of2 { - @include grid-col; - width: 50%; - } - - .m-1of3 { - @include grid-col; - width: 33.33%; - } - - .m-2of3 { - @include grid-col; - width: 66.66%; - } - - .m-1of4 { - @include grid-col; - width: 25%; - } - - .m-3of4 { - @include grid-col; - width: 75%; - } - - .m-right { - text-align: center; - } - .m-center { - text-align: center; - } - .m-left { - text-align: center; - } - - .d-right { - text-align: right; - } - .d-center { - text-align: center; - } - .d-left { - text-align: left; - } - -} // end mobile styles - - -/* Portrait tablet to landscape */ -@media (min-width: 768px) and (max-width: 1029px) { - - .t-all { - @include grid-col; - width: 100%; - padding-right: 0; - } - - .t-1of2 { - @include grid-col; - width: 50%; - } - - .t-1of3 { - @include grid-col; - width: 33.33%; - } - - .t-2of3 { - @include grid-col; - width: 66.66%; - } - - .t-1of4 { - @include grid-col; - width: 25%; - } - - .t-3of4 { - @include grid-col; - width: 75%; - } - - .t-1of5 { - @include grid-col; - width: 20%; - } - - .t-2of5 { - @include grid-col; - width: 40%; - } - - .t-3of5 { - @include grid-col; - width: 60%; - } - - .t-4of5 { - @include grid-col; - width: 80%; - } - - .d-right { - text-align: right; - } - .d-center { - text-align: center; - } - .d-left { - text-align: left; - } - -} // end tablet - -/* Landscape to small desktop */ -@media (min-width: 1030px) { - - .d-all { - @include grid-col; - width: 100%; - padding-right: 0; - } - - .d-1of2 { - @include grid-col; - width: 50%; - } - - .d-1of3 { - @include grid-col; - width: 33.33%; - } - - .d-2of3 { - @include grid-col; - width: 66.66%; - } - - .d-1of4 { - @include grid-col; - width: 25%; - } - - .d-3of4 { - @include grid-col; - width: 75%; - } - - .d-1of5 { - @include grid-col; - width: 20%; - } - - .d-2of5 { - @include grid-col; - width: 40%; - } - - .d-3of5 { - @include grid-col; - width: 60%; - } - - .d-4of5 { - @include grid-col; - width: 80%; - } - - .d-1of6 { - @include grid-col; - width: 16.6666666667%; - } - - .d-1of7 { - @include grid-col; - width: 14.2857142857%; - } - - .d-2of7 { - @include grid-col; - width: 28.5714286%; - } - - .d-3of7 { - @include grid-col; - width: 42.8571429%; - } - - .d-4of7 { - @include grid-col; - width: 57.1428572%; - } - - .d-5of7 { - @include grid-col; - width: 71.4285715%; - } - - .d-6of7 { - @include grid-col; - width: 85.7142857%; - } - - .d-1of8 { - @include grid-col; - width: 12.5%; - } - - .d-1of9 { - @include grid-col; - width: 11.1111111111%; - } - - .d-1of10 { - @include grid-col; - width: 10%; - } - - .d-1of11 { - @include grid-col; - width: 9.09090909091%; - } - - .d-1of12 { - @include grid-col; - width: 8.33%; - } - - .d-right { - text-align: right; - } - .d-center { - text-align: center; - } - .d-left { - text-align: left; - } - -} // end desktop styles diff --git a/assets/scss/admin/post-tables/_llms_orders.scss b/assets/scss/admin/post-tables/_llms_orders.scss deleted file mode 100644 index 31cb7a4b6b..0000000000 --- a/assets/scss/admin/post-tables/_llms_orders.scss +++ /dev/null @@ -1,18 +0,0 @@ -.llms-order-status-icon { - &.llms-active, - &.llms-completed { - color: green; - } - - &.llms-failed, - &.llms-expired, - &.llms-cancelled { - color: red; - } - - &.llms-pending, - &.llms-refunded { - color: orange; - } - -} diff --git a/assets/scss/admin/post-tables/_post-tables.scss b/assets/scss/admin/post-tables/_post-tables.scss deleted file mode 100644 index f3843b0916..0000000000 --- a/assets/scss/admin/post-tables/_post-tables.scss +++ /dev/null @@ -1,6 +0,0 @@ -.llms-post-table-post-filter { - display: inline-block; - margin-right: 6px; - max-width: 100%; - width: 220px; -} diff --git a/assets/scss/builder.scss b/assets/scss/builder.scss deleted file mode 100644 index 9c76d9b35a..0000000000 --- a/assets/scss/builder.scss +++ /dev/null @@ -1,5 +0,0 @@ -@import "_includes/vars"; -@import "_includes/extends"; -@import "_includes/mixins"; - -@import "admin/course-builder"; diff --git a/assets/scss/certificates.scss b/assets/scss/certificates.scss deleted file mode 100644 index b5acb877ac..0000000000 --- a/assets/scss/certificates.scss +++ /dev/null @@ -1,110 +0,0 @@ -body { - background-color: #fff; - background-image: none; - margin: 0 auto; -} - -.header { - display: none; -} - -#content { - background: none; -} - -.entry { - top: 120px; - width: 100%; - margin-bottom: 40px !important; - background: none; -} - -.hentry, -.llms_certificate.hentry, -.llms_my_certificate.hentry { - margin-bottom: 40px !important; - padding: 50px 90px !important; - background: none; - border: none; -} - -.site-header, -.site-footer { - display: none; -} - -.nav-primary { - display: none; -} - -.llms-certificate-container { - position: relative; - padding: 20px; - margin: auto; - margin-bottom: 20px; - -webkit-print-color-adjust: exact; - overflow: hidden; -} - -.llms-certificate-container h1:first-child { - text-align: center; -} - -#llms-print-certificate { - text-align: center; -} - -.llms-certificate-container { - - .certificate-background { - position: absolute; - z-index: 1; - top: 0; - left: 0; - right: 0; - margin: 0 auto; - } - - .llms_certificate, - .llms_my_certificate { - position: relative; - z-index: 2; - } -} - - - -@media print { - - @page { size: auto; } - - /* Make everything on the page invisible */ - body * { - visibility: hidden; - background: #fff none; - } - - .site, .site-content{ - overflow: visible; - } - - /* remove all headers, menus and footers */ - header, nav, footer { - display: none; - } - - /* make only the certificate container and its children visible */ - .llms-certificate-container, .llms-certificate-container * { - visibility: visible; - } - - /* position certificate absolutely and center horizontally */ - .llms-certificate-container { - position: absolute; - top: 0; - left: 0; - right: 0; - margin: 0 auto; - background: #fff none; - } -} diff --git a/assets/scss/frontend/_checkout.scss b/assets/scss/frontend/_checkout.scss deleted file mode 100644 index e0baad23da..0000000000 --- a/assets/scss/frontend/_checkout.scss +++ /dev/null @@ -1,181 +0,0 @@ -.llms-checkout-wrapper { - form.llms-login { - border: 3px solid $color-brand-blue; - display: none; - margin-bottom: 10px; - // padding: 15px 5px 5px; - } - .llms-form-heading { - background: $color-brand-blue; - color: #fff; - margin: 0 0 5px; - padding: 10px; - } -} - -.llms-checkout { - background: #fff; - position: relative; -} - -.llms-checkout-cols-2 { - @extend %clearfix; - - @media all and (min-width: 800px) { - - .llms-checkout-col { - float: left; - - &.llms-col-1 { - margin-right: 5px; - width: calc( 58% - 5px ); - } - &.llms-col-2 { - margin-left: 5px; - width: calc( 42% - 5px ); - - button { - width: 100%; - } - } - } - - } - -} - - .llms-checkout-section { - border: 3px solid $color-brand-blue; - margin-bottom: 10px; - position: relative; - } - - .llms-checkout-section-content { - margin: 10px; - &.llms-form-fields { - margin: 0px; - } - - .llms-label { - font-weight: 400; - font-variant: small-caps; - text-transform: lowercase; - } - - .llms-order-summary { - list-style-type: none; - margin: 0; - padding: 0; - - li { list-style-type: none; } - - &.on-sale, - &.has-coupon { - .price-regular { text-decoration: line-through; } - } - - } - - .llms-coupon-wrapper { - border-top: 1px solid #dadada; - margin-top: 10px; - padding-top: 10px; - - .llms-coupon-entry { - display: none; - margin-top: 10px; - } - } - - } - - .llms-payment-gateway-option { - - .llms-description { - margin-left: 5px; - } - - .llms-description { - a { - border: none; - box-shadow: none; - text-decoration: none; - } - img { - display: inline; - max-height: 22px; - vertical-align: middle; - } - } - - } - - .llms-checkout-wrapper ul.llms-payment-gateways { - margin: 5px 0 0; - padding: 0; - } - ul.llms-payment-gateways { - list-style-type: none; - - li:last-child:after { - border-bottom: 1px solid #dadada; - content: ''; - display: block; - margin: 10px; - } - - .llms-payment-gateway { - margin-bottom: 5px; - list-style-type: none; - &:last-child { - margin-bottom: none; - } - - &.is-selected { - .llms-payment-gateway-option label { - font-weight: 700; - } - .llms-gateway-fields { - display: block; - - .llms-notice { - margin-left: 10px; - margin-right: 10px; - } - } - } - - .llms-form-field { - padding-bottom: 0; - } - } - - .llms-gateway-description { - margin-left: 40px; - } - - .llms-gateway-fields { - display: none; - margin: 5px 0 20px; - } - - .llms-payment-gateway-error { - padding: 0 10px; - } - } - - .llms-checkout-confirm { - margin: 0 10px; - } - - .llms-payment-method { - margin: 10px 10px 0; - } - - .llms-gateway-description { - p { - font-size: 85%; - font-style: italic; - margin-bottom: 0; - } - } diff --git a/assets/scss/frontend/_course.scss b/assets/scss/frontend/_course.scss deleted file mode 100644 index 2296f78086..0000000000 --- a/assets/scss/frontend/_course.scss +++ /dev/null @@ -1,21 +0,0 @@ -.course { - .llms-meta-info { - margin: 20px 0; - .llms-meta-title { - margin-bottom: 5px; - } - .llms-meta { - p { - margin-bottom: 0; - } - span { - font-weight: 700; - } - } - } - .llms-course-progress { - margin: 40px auto; - max-width: 480px; - text-align: center; - } -} diff --git a/assets/scss/frontend/_llms-access-plans.scss b/assets/scss/frontend/_llms-access-plans.scss deleted file mode 100644 index b8f3eda2a2..0000000000 --- a/assets/scss/frontend/_llms-access-plans.scss +++ /dev/null @@ -1,192 +0,0 @@ -.llms-access-plans { - @extend %clearfix; - - @media all and (min-width: 600px) { - $cols: 1; - @while $cols <= 5 { - &.cols-#{$cols} .llms-access-plan { - width: 100% / $cols; - } - $cols: $cols + 1; - } - } - -} - -.llms-free-enroll-form { - margin-bottom: 0; -} - -.llms-access-plan { - box-sizing: border-box; - float: left; - text-align: center; - width: 100%; - - .llms-access-plan-footer, - .llms-access-plan-content { - background: #f1f1f1; - } - - &.featured { - - .llms-access-plan-featured { - background: lighten( $color-brand-blue, 8 ); - } - - .llms-access-plan-footer, - .llms-access-plan-content { - border-left: 3px solid $color-brand-blue; - border-right: 3px solid $color-brand-blue; - } - - .llms-access-plan-footer { - border-bottom-color: $color-brand-blue; - } - - } - - &.on-sale { - .price-regular { text-decoration: line-through; } - } - - .stamp { - background: $color-brand-blue; - color: #fff; - font-size: 11px; - font-style: normal; - font-weight: 300; - padding: 2px 3px; - vertical-align: top; - } - - .llms-access-plan-restrictions ul { margin: 0; } - -} - .llms-access-plan-featured { - color: #fff; - font-size: 14px; - font-weight: 400; - margin: 0 2px 0 2px; - } - - .llms-access-plan-content { - margin: 0 2px 0; - - .llms-access-plan-pricing { - padding: 10px 0 0; - } - } - - .llms-access-plan-title { - background: $color-brand-blue; - color: #fff; - margin-bottom: 0; - padding: 10px; - } - - .llms-access-plan-pricing { - - .llms-price-currency-symbol { - font-size: 14px; - vertical-align: top; - } - - } - - .llms-access-plan-price { - font-size: 18px; - font-variant: small-caps; - line-height: 20px; - - .lifterlms-price { - font-weight: 700; - } - - &.sale { - padding: 5px 0; - border-top: 1px solid #d0d0d0; - border-bottom: 1px solid #d0d0d0; - } - } - - .llms-access-plan-trial, - .llms-access-plan-schedule, - .llms-access-plan-sale-end, - .llms-access-plan-expiration { - font-size: 15px; - font-variant: small-caps; - line-height: 1.2; - } - - .llms-access-plan-description { - font-size: 16px; - padding: 10px 10px 0; - - ul { - margin: 0; - li { - border-bottom: 1px solid #d0d0d0; - list-style-type: none; - &:last-child { - border-bottom: none; - } - } - } - - div, img, p, ul, li { - &:last-child { margin-bottom: 0; } - } - } - - .llms-access-plan-restrictions { - .stamp { - vertical-align: baseline; - } - ul { - margin: 0; - li { - font-size: 12px; - line-height: 14px; - list-style-type: none; - } - } - a { - color: $color-brand-orange; - &:hover { - color: $color-brand-orange-dark; - } - } - } - - .llms-access-plan-footer { - border-bottom: 3px solid #f1f1f1; - padding: 10px; - margin: 0 2px 2px 2px; - - .llms-access-plan-pricing { - padding: 0 0 10px; - } - } - - -.webui-popover-content .llms-members-only-restrictions { - text-align: center; - ul,ol,li,p { - margin: 0; - padding: 0; - } - ul,ol,li { - list-style-type: none; - } - li { - padding: 8px 0; - border-top: 1px solid #3b3b3b; - &:first-child { - border-top: none; - } - a { - display: block; - } - } -} diff --git a/assets/scss/frontend/_llms-achievements-certs.scss b/assets/scss/frontend/_llms-achievements-certs.scss deleted file mode 100644 index 3999faae21..0000000000 --- a/assets/scss/frontend/_llms-achievements-certs.scss +++ /dev/null @@ -1,106 +0,0 @@ -ul.llms-achievements-loop, -.lifterlms ul.llms-achievements-loop, -ul.llms-certificates-loop, -.lifterlms ul.llms-certificates-loop { - - @include clearfix(); - list-style-type: none; - margin: 0 -10px; - padding: 0; - - li.llms-achievement-loop-item, - li.llms-certificate-loop-item { - box-sizing: border-box; - display: block; - float: left; - list-style-type: none; - margin: 0; - padding: 10px; - width: 100%; - } - - @media all and (min-width: 600px) { - $cols: 1; - @while $cols <= 5 { - &.loop-cols-#{$cols} li.llms-achievement-loop-item, - &.loop-cols-#{$cols} li.llms-certificate-loop-item { - width: 100% / $cols; - } - $cols: $cols + 1; - } - } - -} - -.llms-achievement, -.llms-certificate { - - background: #f1f1f1; - border: none; - color: inherit; - display: block; - text-decoration: none; - width: 100%; - - &:hover { - background: #eaeaea; - } - - .llms-achievement-img { - display: block; - margin: 0; - width: 100%; - } - - .llms-achievement-title { - font-size: 16px; - margin: 0; - padding: 10px; - text-align: center; - } - - .llms-certificate-title { - font-size: 16px; - margin: 0; - padding: 0 0 10px; - } - - .llms-achievement-info, - .llms-achievement-date { - display: none; - } - - .llms-achievement-content { - padding: 20px; - &:empty { - padding: 0; - } - *:last-child { - margin-bottom: 0; - } - } - -} - -.llms-certificate { - border: 4px double #f1f1f1; - padding: 20px 10px; - background: #fff; - text-align: center; - &:hover { - background: #fff; - border-color: #eaeaea; - } -} - -.llms-achievement-modal { - .llms-achievement { - background: #fff; - } - .llms-achievement-info { - display: block; - } - .llms-achievement-title { - display: none; - } -} diff --git a/assets/scss/frontend/_llms-author.scss b/assets/scss/frontend/_llms-author.scss deleted file mode 100644 index 316e02fdb6..0000000000 --- a/assets/scss/frontend/_llms-author.scss +++ /dev/null @@ -1,165 +0,0 @@ -.llms-author { - .name { - margin-left: 5px; - } - .label { - margin-left: 5px; - } - .avatar { - border-radius: 50%; - } - .bio { - margin-top: 5px; - } -} - - -.llms-instructor-info { - .llms-instructors { - - .llms-col { - &:first-child .llms-author { - margin-left: 0; - } - &:last-child .llms-author { - margin-right: 0; - } - } - - .llms-author { - - background: #f5f5f5; - border-top: 4px solid $color-brand-blue; - text-align: center; - margin: 45px 5px 5px; - padding: 0 10px 10px; - - .avatar { - background: $color-brand-blue; - border: 4px solid $color-brand-blue; - display: block; - margin: -35px auto 10px; - } - - .llms-author-info { - display: block; - // margin: 0 0 5px; - &.name { - font-weight: 700; - } - &.label { - font-size: 85%; - } - &.bio { - font-size: 90%; - margin-bottom: 0; - } - } - } - - } - -} - -// @media only screen and (min-width:800px) { - -// .llms-instructor-info { - -// .llms-instructors { -// @include clearfix; -// .llms-author { -// float: left; -// height: 110px; -// margin-right: 5px; -// text-align: center; -// transition: margin 0.1s ease; -// width: 100px; - -// &:nth-child(n+2) { -// margin-left: -60px; -// } - -// .avatar { -// background: $color-brand-blue; -// border: 4px solid $color-brand-blue; -// display: block; -// margin: 0 auto 10px; -// transition: transform .1s ease; -// } - -// &.has-bio .llms-author-info { -// min-width: 320px; -// } - -// .llms-author-info { -// background: $color-cinder; -// color: #fff; -// display: block; -// font-weight: 300; -// opacity: 0; -// padding: 8px 8px 0 8px; -// position: relative; -// line-height: 1; -// min-width: 180px; -// // max-width: 180px; -// margin: 0; -// text-align: left; -// top: 0; -// transition: opacity 0.1s ease, top 0.3s ease; - -// &:nth-child( 2 ) { -// border-top-left-radius: 4px; -// border-top-right-radius: 4px; -// &:before { -// content: ''; -// border: 8px solid transparent; -// border-bottom-color: $color-cinder; -// margin-left: -8px; -// position: absolute; -// left: 50px; -// top: -16px; -// } -// } - -// &:last-child { -// border-bottom-left-radius: 4px; -// border-bottom-right-radius: 4px; -// padding-bottom: 8px; -// } - -// &.bio { -// line-height: 1.2; -// } - -// } - -// &:hover { -// position: relative; -// z-index: 1; - -// .avatar { -// transform: scale( 1.2 ); -// } - -// .llms-author-info { -// top: 10px; -// opacity: 1; -// } - -// } - -// } -// &:hover { -// .llms-author { -// &:nth-child(n+2) { -// margin-left: -30px; -// } -// } -// } - -// } - -// } - -// } - diff --git a/assets/scss/frontend/_llms-notifications.scss b/assets/scss/frontend/_llms-notifications.scss deleted file mode 100644 index 8a1da8d02e..0000000000 --- a/assets/scss/frontend/_llms-notifications.scss +++ /dev/null @@ -1,177 +0,0 @@ -.llms-notification { - - @include clearfix(); - - background: #fff; - box-shadow: 0 1px 2px -2px #333, 0 1px 1px -1px #333; - border-top: 4px solid $color-blue; - left: 12px; - opacity: 0; - padding: 12px; - position: fixed; - right: 12px; - top: 24px; - transition: - opacity 0.4s ease-in-out, - right 0.4s ease-in-out, - ; - visibility: none; - width: auto; - z-index: 9999999; - - &.visible { - opacity: 1; - transition: - opacity 0.4s ease-in-out, - right 0.4s ease-in-out, - top 0.1s ease-in-out, - background 0.2s ease-in-out, - transform 0.2s ease-in-out - ; - visibility: visible; - - &:hover { - .llms-notification-dismiss { - opacity: 1; - } - } - - } - - .llms-notification-content { - align-items: center; - display: flex; - - } - - .llms-notification-main { - align-self: flex-start; - flex: 4; - order: 2; - } - - .llms-notification-title { - font-size: 18px; - margin: 0; - } - - .llms-notification-body { - font-size: 14px; - line-height: 1.4; - p, li { - font-size: inherit; - } - p { - margin-bottom: 8px; - } - - .llms-mini-cert { - background: #f6f6f6; - border: 4px double #b0b0b0; - padding: 24px 8px; - .llms-mini-cert-title { - font-size: 16px; - font-weight: 700; - margin-bottom: 8px; - text-align: center; - } - p,li { - font-size: 14px; - &:last-child { margin-bottom: 0; } - } - } - } - - .llms-notification-aside { - align-self: flex-start; - flex: 1; - margin-right: 12px; - order: 1; - } - - .llms-notification-icon { - display: block; - max-width: 64px; - } - - .llms-notification-footer { - border-top: 1px solid #e5e5e5; - font-size: 12px; - margin-top: 12px; - padding: 6px 6px 0; - text-align: right; - } - - .llms-notification-dismiss { - color: $color-danger; - cursor: pointer; - font-size: 22px; - position: absolute; - right: 10px; - top: 8px; - transition: opacity 0.4s ease-in-out; - } - -} - -.llms-sd-notification-center { - - .llms-notification-list, - .llms-notification-list-item { - list-style-type: none; - margin: 0; - padding: 0; - } - - .llms-notification-list-item { - &:hover .llms-notification { - background: #fcfcfc; - } - } - - .llms-notification { - opacity: 1; - border-top: 1px solid #e5e5e5; - left: auto; - padding: 24px; - position: relative; - right: auto; - top: auto; - visibility: visible; - width: auto; - .llms-notification-aside { - max-width: 64px; - } - .llms-notification-footer { - border: none; - padding: 0; - text-align: left; - } - .llms-progress { - display: none !important; - } - .llms-notification-date { - color: #515151; - float: left; - margin-right: 6px; - } - .llms-mini-cert { - margin: 0 auto; - max-width: 380px; - } - } -} - -@media all and (min-width: 480px) { - .llms-notification { - left: auto; - right: -800px; - width: 360px; - &.visible { - right: 24px; - } - .llms-notification-dismiss { - opacity: 0; - } - } -} diff --git a/assets/scss/frontend/_llms-outline-collapse.scss b/assets/scss/frontend/_llms-outline-collapse.scss deleted file mode 100644 index ad109277a6..0000000000 --- a/assets/scss/frontend/_llms-outline-collapse.scss +++ /dev/null @@ -1,39 +0,0 @@ -.llms-widget-syllabus--collapsible { - - .llms-section { - - .section-header { - - cursor: pointer; - - } - - &.llms-section--opened { - - .llms-collapse-caret { - .fa-caret-right { display: none; } - } - - } - - &.llms-section--closed { - - .llms-collapse-caret { - .fa-caret-down { display: none; } - } - - .llms-lesson { - display: none; - } - - } - - } - - .llms-syllabus-footer { - - text-align: left; - - } - -} diff --git a/assets/scss/frontend/_llms-pagination.scss b/assets/scss/frontend/_llms-pagination.scss deleted file mode 100644 index d0585c70a2..0000000000 --- a/assets/scss/frontend/_llms-pagination.scss +++ /dev/null @@ -1,29 +0,0 @@ -.llms-pagination { - - ul { - list-style-type: none; - @extend %cf; - - li { - - float: left; - - a { - border-bottom: 0; - text-decoration: none; - } - - .page-numbers { - padding: 0.5em; - text-decoration: underline; - - &.current { - text-decoration: none; - } - } - - } - - } - -} \ No newline at end of file diff --git a/assets/scss/frontend/_llms-progress.scss b/assets/scss/frontend/_llms-progress.scss deleted file mode 100644 index a43869179d..0000000000 --- a/assets/scss/frontend/_llms-progress.scss +++ /dev/null @@ -1,32 +0,0 @@ -/* progress bar */ -.llms-progress { - clear: both; - display: flex; - flex-direction: row-reverse; - position: relative; - height: 1em; - width: 100%; - margin: 15px 0; -} - -.llms-progress .llms-progress-bar { - background-color: #f1f2f1; - position: relative; - height: .4em; - top: .3em; - width: 100%; -} - -.llms-progress .progress-bar-complete { - background-color: $color-brand-pink; - height: 100%; -} - -.progress__indicator { - float: right; - text-align: right; - height: 1em; - line-height: 1em; - margin-left: 5px; - white-space: nowrap; -} diff --git a/assets/scss/frontend/_llms-quizzes.scss b/assets/scss/frontend/_llms-quizzes.scss deleted file mode 100644 index f7f913bb98..0000000000 --- a/assets/scss/frontend/_llms-quizzes.scss +++ /dev/null @@ -1,342 +0,0 @@ -.single-llms_quiz { - - @import "../_includes/quiz-result-question-list"; - - .llms-return { - margin-bottom: 10px; - } - - .llms-quiz-results { - @include clearfix(); - - .llms-donut { - &.passing { - color: $color-success; - svg path { - stroke: $color-success; - } - } - &.pending { - color: #555; - svg path { - stroke: #555; - } - } - &.failing { - color: $color-danger; - svg path { - stroke: $color-danger; - } - } - } - - .llms-quiz-results-aside, - .llms-quiz-results-main, - .llms-quiz-results-history { - margin-bottom: 20px; - } - - - @media all and (min-width: 600px) { - .llms-quiz-results-aside { - float: left; - width: 220px; - } - .llms-quiz-results-main, - .llms-quiz-results-history { - float: left; - width: calc( 100% - 300px ); - } - } - - } - - ul.llms-quiz-meta-info, - ul.llms-quiz-meta-info li { - list-style-type: none; - margin: 0; - padding: 0 - } - - ul.llms-quiz-meta-info { - margin-bottom: 10px; - } - - .llms-quiz-buttons { - margin-top: 10px; - text-align: left; - - form { display: inline-block; } - } - -} - -.llms-quiz-question-wrapper { - min-height: 140px; - position: relative; - .llms-quiz-loading { - bottom: 20px; - left: 0; - position: absolute; - right: 0; - text-align: center; - z-index: 1; - } -} - -.llms-quiz-ui { - background: #fcfcfc; - padding: 20px; - position: relative; - - .llms-quiz-header { - align-items: center; - display: flex; - margin: 0 0 30px; - } - - .llms-progress { - background-color: #f1f2f1; - flex-direction: row; - height: 8px; - margin: 0; - overflow: hidden; - .progress-bar-complete { - transition: width 0.3s ease-in; - width: 0; - } - } - - .llms-error { - @include clearfix(); - background: $color-danger; - border-radius: 4px; - color: #fff; - margin: 10px 0; - padding: 10px; - - a { - color: rgba( #fff, 0.6 ); - float: right; - font-size: 22px; - line-height: 1; - text-decoration: none; - } - - } - - .llms-quiz-counter { - display: none; - - color: #6a6a6a; - float: right; - font-size: 18px; - - .llms-sep { - margin: 0 5px; - } - } - - .llms-quiz-nav { - margin-top: 20px; - button { - margin: 0 10px 0 0; - } - } - -} - -// single question wrapper -.llms-question-wrapper { - - .llms-question-text { - font-size: 30px; - font-weight: 400; - margin-bottom: 15px; - } - - ol.llms-question-choices { - list-style-type: none; - margin: 0; - padding: 0; - - li.llms-choice { - border-bottom: 1px solid #e8e8e8; - margin: 0; - padding: 0; - position: relative; - - &:last-child { - border-bottom: none; - } - - &.type--picture { - border-bottom: none; - label { - padding: 0; - } - .llms-marker { - bottom: 10px; - margin: 0; - position: absolute; - right: 10px; - } - .llms-choice-image { - margin: 2px; - padding: 20px; - transition: background 0.4s ease; - img { - display: block; - width: 100%; - } - } - input:checked ~ .llms-choice-image { - background: #efefef - } - } - - input { - display: none; - left: 0; - pointer-events: none; - position: absolute; - top: 0; - visibility: hidden; - } - - label { - margin: 0; - padding: 10px 20px; - position: relative; - &:hover { - .llms-marker:not(.type--lister) { - .iterator { - display: none; - } - .fa { - display: inline; - } - } - } - } - - .llms-marker { - - background: #f0f0f0; - display: inline-block; - font-size: 20px; - height: 40px; - line-height: 40px; - margin-right: 10px; - text-align: center; - transition: all 0.2s ease; - vertical-align: middle; - width: 40px; - - .fa { - display: none; - } - - &.type--lister, - &.type--checkbox { border-radius: 4px; } - &.type--radio { border-radius: 50%; } - - } - - input:checked + .llms-marker { - background: $color-brand-pink; - color: #fff; - .iterator { - display: none; - } - .fa { - display: inline; - } - } - - .llms-choice-text { - display: inline-block; - font-size: 18px; - font-weight: 400; - line-height: 1.6; - margin-bottom: 0; - vertical-align: middle; - width: calc( 100% - 60px ); - } - - } - } - -} - -.llms-quiz-timer { - background: #fff; - border: 1px solid $color-green; - border-radius: 4px; - color: $color-green; - float: right; - font-size: 18px; - line-height: 1; - margin-left: 20px; - padding: 8px 12px; - position: relative; - white-space: nowrap; - z-index: 1; - - &.color-half { - border-color: $color-orange; - color: $color-orange - } - - &.color-empty { - border-color: $color-danger; - color: $color-danger - } - - .llms-tiles { - display: inline-block; - margin-left: 5px; - } -} - - -// /* My Quizes */ -// .llms-quiz-results { -// @extend %cf; -// font-family: "Open Sans",Verdana,Geneva,sans-serif,sans-serif; -// position: relative; -// } -// .llms-quiz-results > h3 { -// background-color: #f5f5f5; -// padding: 4px; -// } - -// .llms-quiz-result-details { -// float: left; -// ul { -// list-style-type: none; -// float: left; -// li { -// list-style-type: none; -// font-size: 20px; -// } -// } -// } -// .llms-attempts { -// font-weight: bold; -// } - -// .llms-pass-perc { -// font-weight: bold; -// } -// .llms-content-block { -// margin: 6px 0; -// } -// .llms-question-wrapper { -// margin: 40px 0 20px 0; -// } -// .llms-question-count { -// margin-bottom: 20px; -// } - - diff --git a/assets/scss/frontend/_loop.scss b/assets/scss/frontend/_loop.scss deleted file mode 100644 index 784245d64c..0000000000 --- a/assets/scss/frontend/_loop.scss +++ /dev/null @@ -1,263 +0,0 @@ -.llms-loop-list { - @extend %clearfix; - - list-style: none; - margin: 0 -10px; - padding: 0; - - @media all and (min-width: 600px) { - $cols: 1; - @while $cols <= 6 { - &.cols-#{$cols} .llms-loop-item { - width: 100% / $cols; - } - $cols: $cols + 1; - } - } - - -} - -.llms-loop-item { - float: left; - list-style: none; - margin: 0; - padding: 0; - width: 100%; -} - - - .llms-loop-item-content { - background: #f1f1f1; - padding-bottom: 10px; - margin: 10px; - - &:hover { - background: #eaeaea; - } - - .llms-loop-link { - color: #212121; - display: block; - &:visited { - color: #212121; - } - } - - .llms-featured-image { - display: block; - max-width: 100%; - } - - .llms-loop-title { - margin-top: 5px; - &:hover { - color: $color-brand-blue; - } - } - - .llms-meta, - .llms-author, - .llms-loop-title { - padding: 0 10px; - } - - .llms-meta, - .llms-author { - color: #444; - display: block; - font-size: 13px; - margin-bottom: 3px; - &:last-child { - margin-bottom: 0; - } - } - - .llms-featured-img-wrap { - overflow: hidden; - } - - p { - margin-bottom: 0; - } - - .llms-progress { - margin: 0; - height: .4em; - - .progress__indicator { - display: none; - } - - .llms-progress-bar { - background-color: #f6f6f6; - right: 0; - top: 0; - } - } - - } - - - -// .llms-membership-list .memberships { -// border-top: 1px solid #f6f6f6; -// width: 100%; -// display: inline-block; -// text-align: center; -// list-style: none; -// clear: both; -// margin: 0; -// padding: 0; -// } - - - -// .llms-course-list { - -// .llms-membership-link { -// @extend %llms-element; - -// display: block -// } - -// .llms-membership-footer { -// border-top: 3px solid $color-white; -// margin: 15px -15px 0; -// padding: 15px 15px 0; -// text-align: center; -// } - -// } - - - - -// .llms-membership-list .memberships li { -// width: 300px; -// margin: 15px; -// list-style: none; -// vertical-align: top; -// display: inline-block; -// text-align: left; -// } - -// .llms-membership-list .memberships li.first { -// margin-left: 0; -// } - -// .llms-membership-list .memberships li.last { -// margin-right: 15px; -// } - -// .llms-membership-list .memberships li .llms-title { -// display: block; -// font-weight: 700; -// margin-bottom: .5em; -// font-size: 18px; -// text-decoration: none; -// line-height: 30px; -// } - -// .llms-membership-list .memberships li .llms-price { -// display: block; -// font-weight: 700; -// // margin-bottom: .5em; -// // font-size: 24px; -// text-decoration: none; -// line-height: 30px; -// } - -// .llms-course-list { -// //margin: 30px 0; -// padding: 30px; -// //background: #FFF; -// // border-radius: 2px; -// display: inline-block; -// width: 100%; -// box-sizing: border-box; - -// .llms-course-link { -// @extend %llms-element; - -// display: block -// } - -// .llms-course-footer { -// border-top: 3px solid $color-white; -// margin: 15px -15px 0; -// padding: 15px 15px 0; -// text-align: center; -// } - -// .llms-progress { -// margin-top: 0; -// // .progress-bar { -// // background-color: $color-white; -// // } -// } - -// } - -// .llms-course-list .courses { -// //border-top: 1px solid #f6f6f6; -// width: 100%; -// display: inline-block; -// text-align: center; -// list-style: none; -// clear: both; -// margin: 0; -// padding: 0; -// } - -// .llms-course-list .courses li { -// width: 300px; -// padding-top: 0; // twentyfifteen compat -// margin: 15px; -// list-style: none; -// vertical-align: top; -// display: inline-block; -// text-align: left; -// } -// @media screen and (max-width: $break-small) { -// .llms-course-list { -// padding: 30px 10px; - -// .courses li { -// width: auto; -// } -// } -// } - -// // .llms-course-list .courses li.first { -// // margin-left: 0; -// // } - -// .llms-course-list .courses li.last { -// margin-right: 15px; -// } - -// .llms-course-list .courses li .llms-title { -// display: block; -// font-weight: 700; -// margin-bottom: .5em; -// font-size: 18px; -// text-decoration: none; -// line-height: 30px; -// } - -// .llms-course-list .courses li .llms-price { -// display: block; -// font-weight: 700; -// // margin-bottom: .5em; -// // font-size: 24px; -// text-decoration: none; -// line-height: 30px; -// } - - - - -// .courses a.llms-course-link:hover { -// text-decoration: none; -// } diff --git a/assets/scss/frontend/_main.scss b/assets/scss/frontend/_main.scss deleted file mode 100644 index b892c56299..0000000000 --- a/assets/scss/frontend/_main.scss +++ /dev/null @@ -1,452 +0,0 @@ - - - - -.llms-membership-image { - display: block; - margin: 0 auto; -} - - - -.llms-course-image { - display: block; - margin: 0 auto; - max-width: 100%; -} -.llms-featured-image { - display: block; - margin: 0 auto; -} -.llms-image-thumb { - width: 150px; -} - - -.llms-video-wrapper { - text-align: center; - margin-bottom: 10px; -} - - - - - - - - - - - -.clear { - clear: both; - width: 100%; -} -.llms-featured-image { - text-align: center; -} - -/* Genisis Overrides */ -h1, h2, h3, h4, h5, h6 { - font-weight: 300; -} - -#main-content .llms-payment-options p { - margin: 0; - font-size: 16px; -} - -.llms-option { - display: block; - position: relative; - margin: 20px 0; - padding-left:40px; - font-size: 16px; - - label { - cursor: pointer; - position: static; - } -} -.llms-option:first-child { - margin-top:0; -} -.llms-option:last-child { - margin-bottom:0; -} -#main-content .llms-option:last-child { - margin-bottom:0; -} - -.llms-option input[type="radio"] { - display: block; - position: absolute; - top:3px; - left:0; - z-index: 0; -} - -.llms-option input[type="radio"] { - display: inline-block; -} -.llms-option input[type="radio"] + label span.llms-radio { - display: none; -} - -.llms-option input[type="radio"] + label span.llms-radio { - appearance: none; - - z-index: 20; - position: absolute; - top: 0; - left: -2px; - display: inline-block; - width: 24px; - height: 24px; - border-radius: 50%; - cursor: pointer; - vertical-align: middle; - box-shadow: hsla(0,0%,100%,.15) 0 1px 1px, inset hsla(0,0%,0%,.5) 0 0 0 1px; - - background: #efefef; - background-image: radial-gradient(ellipse at center, $color-red 0%,$color-red 40%,#efefef 45%); - background-repeat: no-repeat; - - transition: background-position .15s cubic-bezier(.8, 0, 1, 1); -} -.llms-option input[type="radio"]:checked + label span.llms-radio { - transition: background-position .2s .15s cubic-bezier(0, 0, .2, 1); -} - -.llms-option input[type="radio"] + label span.llms-radio { - background-position: -24px 0; -} -.llms-option input[type="radio"]:checked + label span.llms-radio { - background-position: 0 0; -} - -.llms-option input[type="submit"] { - border:none; - background:$color-red; - color:#fff; - font-size:20px; - padding:10px 0; - border-radius:3px; - cursor:pointer; - width:100%; -} -.llms-styled-text { - padding: 14px 0; -} -.llms-notice-box { - border-radius: 3px; - z-index: 10; - margin: 10px 0; - padding: 15px 20px; - //background: #fffef4; - border: 1px solid #ccc; - list-style-type: none; - width: 100%; - overflow: auto; - input[type="text"] { - height: auto; - } - .col-1-1 { - width: 100%; - input[type=text] { - width: 100%; - } - } - .col-1-2 { - width: 50%; - float: left; - @media screen and (max-width: $break-medium) { - width: 100%; - } - } - .col-1-3 { - width: 33%; - float: left; - margin-right: 10px; - } - .col-1-4 { - width: 25%; - float: left; - margin-right: 10px; - @media screen and (max-width: $break-medium) { - width: 100%; - } - } - .col-1-6 { - width: 16.6%; - float: left; - margin-right: 10px; - } - .col-1-8 { - width: 11%; - float: right; - } - .llms-pad-right { - padding-right: 10px; - @media screen and (max-width: $break-medium) { - padding-right: 0; - } - } -} -input[type="text"].cc_cvv, -#cc_cvv { - margin-right: 0; - width: 23%; - float: right; -} -.llms-clear-box { - border-radius: 3px; - z-index: 10; - margin: 10px 0; - padding: 15px 20px; - list-style-type: none; - width: 100%; - overflow: auto; -} -.llms-price-label { - font-weight: normal; -} -.llms-final-price { - font-weight: bold; - float: right; -} -.llms-center-content { - text-align: center; -} -.llms-input-text { - background-color: #fff; - border: 1px solid #ddd; - color: #333; - font-size: 18px; - font-weight: 300; - padding: 16px; - width: 100%; -} -.llms-price { - margin-bottom: 0; - font-weight: bold; -} -.llms-price-loop { - margin-bottom: 0; - font-weight: bold; -} - -// henty overrides -.courses .entry { - padding: 0 -} -.list-view .site-content .llms-course-list .hentry, .list-view .site-content .llms-membership-list .hentry { - border-top: 0; - padding-top: 0; -} -.llms-content { - width: 100%; -} - -.llms-lesson-button-wrapper { - width: 100%; - display: block; - clear: both; - text-align: center; -} -.llms-template-wrapper { - width: 100%; - display: block; - clear: both; -} -.llms-button-wrapper { - width: 100%; - display: block; - clear: both; - text-align: center; -} - - -//custom select box -.llms-styled-select { - border: 1px solid #ccc; - box-sizing: border-box; - border-radius: 3px; - overflow: hidden; - position: relative; -} -.llms-styled-select, .llms-styled-select select { - width: 100%; -} -select:focus { outline: none; } -.llms-styled-select select { - height: 34px; - padding: 5px 0 5px 5px; - background: transparent; - border: none; - -webkit-appearance: none; - font-size: 16px; - color: #444444; -} - -@-moz-document url-prefix(){ - .--ms-styled-select select { width: 110%; } -} - -.llms-styled-select .fa-sort-desc { - position: absolute; - top: 0; - right: 12px; - font-size: 24px; - color: #ccc; -} - -select::-ms-expand { display: none; } - -_:-o-prefocus, .selector { - .llms-styled-select { background: none; } -} - -.llms-form-item-wrapper { - margin-bottom: 1em; -} - -/* Circle Graph */ -.llms-progress-circle { - position: relative; - width: 200px; - height: 200px; - float: left; -} - -.llms-progress-circle-count { - top: 27%; - position: absolute; - width: 94%; - text-align: center; - color: #666; - font-size:44px; -} -.llms-progress-circle svg { - position: absolute; - width: 200px; - height: 200px; -} -.llms-progress-circle circle { - fill: transparent; -} -svg .llms-background-circle { - fill: transparent; - stroke-width: 10px; - stroke: #f1f2f1; - stroke-dasharray: 430; -} - -svg .llms-animated-circle { - fill: transparent; - stroke-width: 10px; - stroke: #e5554e; - stroke-dasharray: 430; - stroke-dashoffset: 430 - 20 -} - - - - - - - -.llms-widget-syllabus { - - - .llms-lesson-complete, .lesson-complete-placeholder { - font-size: 1.2em; - margin-right: 6px; - color: #ccc; - &.done { - color: #e5554e; - } - }.section-title { - font-weight: bold; - }.lesson-title { - a { - text-decoration: none; - &:hover { - text-decoration: none !important; - } - } - &.done { - a { - color: #999; - text-decoration: line-through; - } - } - } - ul { - list-style-type: none; - li { - list-style-type: none; - ul li { - margin: 0 0 2px 0; - padding: 0; - } - } - } -} - - - -.llms-remove-coupon { - float: right; -} - - - - - -.llms-lesson-link-locked, .llms-lesson-link-locked:hover { - background: #f1f1f1; - box-shadow: 0 1px 2px 0 rgba(1, 1, 1, 0.4); - display: block; - color: #a6a6a6; - min-height: 85px; - padding: 15px; - text-decoration: none; - position: relative; -} - -.llms-lesson-preview.is-complete .llms-lesson-link-locked { - padding-left: 75px; -} - -.llms-lesson-tooltip { display: none; - position:absolute; - color: #000000; - background-color: #c0c0c0; - padding:.25em; - border-radius: 2px; - z-index: 100; - top:0; - left:50%; - text-align: center; - -webkit-transform: translateX(-50%) translateY(-100%); - transform: translateX(-50%) translateY(-100%); - } - -/* arrows - :after */ -.llms-lesson-tooltip:after { - content: ""; - width: 0; - height: 0; - border-top: 8px solid #c0c0c0; - border-left: 8px solid transparent; - border-right: 8px solid transparent; - position:absolute; - bottom:-8px; - left:50%; - transform: translateX(-50%); -} - -.llms-lesson-tooltip.active { - display: inline-block; -} diff --git a/assets/scss/frontend/_notices.scss b/assets/scss/frontend/_notices.scss deleted file mode 100644 index 477078366d..0000000000 --- a/assets/scss/frontend/_notices.scss +++ /dev/null @@ -1,41 +0,0 @@ -.llms-notice { - background: rgba( $color-brand-blue, .3 ); - border-color: $color-brand-blue; - border-style: solid; - border-width: 3px; - padding: 10px; - margin-bottom: 10px; - - p, ul { - &:last-child { margin-bottom: 0; } - } - - li { - list-style-type: none; - } - - &.llms-debug { - background: rgba( #cacaca, .3 ); - border-color: #cacaca; - } - - &.llms-error { - background: rgba( $color-red, .3 ); - border-color: $color-red; - } - - &.llms-success { - background: rgba( $color-green, .3 ); - border-color: $color-green; - } - -} - -// this helps genesis and numerous other themes out a bit -// by being slightly more specific -.entry-content .llms-notice { - margin: 0 0 10px; - li { - list-style-type: none; - } -} diff --git a/assets/scss/frontend/_student-dashboard.scss b/assets/scss/frontend/_student-dashboard.scss deleted file mode 100644 index 529362a505..0000000000 --- a/assets/scss/frontend/_student-dashboard.scss +++ /dev/null @@ -1,221 +0,0 @@ -.llms-student-dashboard { - - .llms-sd-nav {} - - .llms-sd-title { - margin: 25px 0; - } - - .llms-sd-items { // ul - @extend %clearfix; - list-style-type: none; - margin: 0; - padding: 0; - } - .llms-sd-item { // li - float: left; - list-style-type: none; - margin: 0; - padding: 0; - - &:last-child { - .llms-sep { - display: none; - } - } - - .llms-sep { - color: #333; - margin: 0 5px; - } - } - - .llms-sd-section { - margin-bottom: 25px; - .llms-sd-section-footer { - margin-top: 10px; - } - } - - .orders-table { - - border: 1px solid #f5f5f5; - width: 100%; - - thead { - display: none; - th,td { - font-weight: 700; - } - @media all and ( min-width: 600px ) { - display: table-header-group; - } - } - - tbody { - tr:nth-child( even ) { - td, th { - background: #f9f9f9; - } - } - } - - tfoot { - th, td { - padding: 10px; - text-align: right; - &:last-child { border-bottom-width: 0; } - } - } - - th { - font-weight: 700; - } - - th, td { - border-color: #efefef; - border-style: solid; - border-width: 0; - display: block; - padding: 8px 12px; - text-align: center; - - .llms-button-primary { - display: inline-block; - } - - &:last-child { - border-bottom-width: 1px; - } - - &:before { - content: attr( data-label ); - } - - @media all and ( min-width: 600px ) { - border-bottom-width: 1px; - display: table-cell; - text-align: left; - &:first-child { width: 220px; } - &:before { display: none; } - } - - } - - @media all and ( min-width: 600px ) { - &.transactions th:first-child {width: auto; } - } - - } - - .llms-status { - color: #fff; - border-radius: 3px; - display: inline-block; - font-size: 80%; - padding: 3px 6px; - vertical-align: middle; - - &.llms-active, - &.llms-completed, - &.llms-txn-succeeded { - background-color: $color-green; - } - - &.llms-failed, - &.llms-expired, - &.llms-cancelled, - &.llms-txn-failed { - background-color: $color-red; - } - - &.llms-on-hold, - &.llms-pending, - &.llms-refunded, - &.llms-txn-pending, - &.llms-txn-refunded { - background-color: orange; - } - - } - - .llms-person-form-wrapper { - .llms-change-password { display: none; } - } - - .order-primary { - - @media all and ( min-width: 600px ) { - float: left; - width: 68%; - } - - } - .order-secondary { - - @media all and ( min-width: 600px ) { - float: left; - width: 32%; - } - - form { - margin-bottom: 0; - } - - } - - // stack columns when alternate layout declared via filter - @media all and ( min-width: 600px ) { - .llms-view-order.llms-stack-cols { - .order-primary, - .order-secondary { - float: none; - width: 100%; - } - } - } - - .llms-switch-payment-source { - .llms-notice, - .entry-content .llms-notice { - margin-left: 10px; - margin-right: 10px; - } - } - - .llms-switch-payment-source-main { - border: none; - display: none; - margin: 0; - ul.llms-payment-gateways { - padding: 10px 15px 0; - margin: 0; - } - .llms-payment-method, - ul.llms-order-summary { - padding: 0 25px 10px; - margin: 0; - list-style-type: none; - li { list-style-type: none; } - } - } - - /** - * Dashboard Home - */ - .llms-loop-list { - margin: 0 -10px; - } - -} - -.llms-sd-pagination { - margin-top: 24px; - @include clearfix; - .llms-button-secondary { - display: inline-block; - &.prev { float: left; } - &.next { float: right; } - } -} - diff --git a/assets/scss/frontend/_syllabus.scss b/assets/scss/frontend/_syllabus.scss deleted file mode 100644 index 95c553fbdc..0000000000 --- a/assets/scss/frontend/_syllabus.scss +++ /dev/null @@ -1,147 +0,0 @@ -.llms-syllabus-wrapper { - - margin: 15px; - text-align: center; - - .llms-section-title { - margin: 25px 0 0; - } - -} - -.llms-course-navigation { - @extend %clearfix; - - .llms-prev-lesson, - .llms-next-lesson, - .llms-back-to-course { - width: 49%; - } - - .llms-prev-lesson, - .llms-back-to-course { - float: left; - margin-right: 0.5%; - } - - .llms-next-lesson, - .llms-prev-lesson + .llms-back-to-course { - float: right; - margin-left: 0.5%; - } - -} - -.llms-lesson-preview { - display: inline-block; - margin-top: 15px; - max-width: 100%; - position: relative; - width: 480px; - - .llms-lesson-link { - background: #f1f1f1; - color: #212121; - display: block; - // height: 100%; - padding: 15px; - text-decoration: none; - - @include clearfix(); - - &:hover { - background: #eaeaea; - } - - &:visited { - color: #212121; - } - - } - - .llms-lesson-thumbnail { - margin-bottom: 10px; - img { - display: block; - width: 100%; - } - } - - .llms-pre-text { - text-align: left; - } - - .llms-lesson-title { - font-weight: 700; - margin: 0 auto 10px; - text-align: left; - &:last-child { - margin-bottom: 0; - } - } - - .llms-lesson-excerpt { - text-align: left; - } - - .llms-main { - float: left; - width: 100%; - } - .llms-extra { - float: right; - width: 15%; - } - - .llms-extra + .llms-main { - width: 85%; - } - - .llms-lesson-counter, - .llms-free-lesson-svg, - .llms-lesson-complete, - .llms-lesson-complete-placeholder { - display: block; - font-size: 32px; - margin-bottom: 15px; - } - - &.is-free, - &.is-complete { - .llms-lesson-complete { - color: $color-brand-blue; - } - } - - .llms-icon-free { - background: $color-brand-blue; - border-radius: 4px; - color: #f1f1f1; - display: inline-block; - padding: 5px 6px 4px; - line-height: 1; - font-size: 14px; - } - - &.is-incomplete { - .llms-lesson-complete { - color: #cacaca; - } - } - - .llms-lesson-counter { - font-size: 16px; - line-height: 1; - } - - .llms-free-lesson-svg { - fill: currentColor; - height: 23px; - width: 50px; - } - - p { - margin-bottom: 0; - } - -} diff --git a/assets/scss/frontend/_tooltip.scss b/assets/scss/frontend/_tooltip.scss deleted file mode 100644 index afa87788eb..0000000000 --- a/assets/scss/frontend/_tooltip.scss +++ /dev/null @@ -1,63 +0,0 @@ -.llms-tooltip { - - background: #2a2a2a; - border-radius: 4px; - color: #fff; - font-size: 14px; - line-height: 1.2; - opacity: 0; - top: -20px; - padding: 8px 12px; - left: 50%; - position: absolute; - pointer-events: none; - transform: translateX( -50% ); - transition: opacity .2s ease, top .2s ease; - max-width: 320px; - - &.show { - top: -28px; - opacity: 1; - } - - &:after { - - bottom: -8px; - border-top: 8px solid #2a2a2a; - border-left: 8px solid transparent; - border-right: 8px solid transparent; - content: ''; - height: 0; - left: 50%; - position: absolute; - transform: translateX( -50% ); - width: 0; - - } - -} - - - -.webui-popover-title { - font-size: initial; - font-weight: initial; - line-height: initial; -} -.webui-popover-inverse { - .webui-popover-inner .close { - color: #fff; - opacity: 0.6; - text-shadow: none; - &:hover { - opacity: 0.8; - } - } - .webui-popover-content a { - color: #fff; - text-decoration: underline; - &:hover { - text-decoration: none; - } - } -} diff --git a/assets/scss/frontend/_voucher.scss b/assets/scss/frontend/_voucher.scss deleted file mode 100644 index 6c950121af..0000000000 --- a/assets/scss/frontend/_voucher.scss +++ /dev/null @@ -1,3 +0,0 @@ -.voucher-expand { - display: none; -} \ No newline at end of file diff --git a/assets/scss/lifterlms.scss b/assets/scss/lifterlms.scss deleted file mode 100644 index 6f0efceb0c..0000000000 --- a/assets/scss/lifterlms.scss +++ /dev/null @@ -1,39 +0,0 @@ -// -// Main Frontend CSS File -// - -@import "_includes/vars"; -@import "_includes/extends"; -@import "_includes/grid"; -@import "_includes/mixins"; -@import "_includes/buttons"; -@import "_includes/llms-donut"; -@import "_includes/tooltip"; - -@import "frontend/main"; -@import "frontend/loop"; -@import "frontend/course"; -@import "frontend/syllabus"; -@import "frontend/llms-progress"; -@import "frontend/llms-author"; - -@import "frontend/notices"; -@import "frontend/llms-achievements-certs"; -@import "frontend/llms-notifications"; -@import "frontend/llms-pagination"; -@import "frontend/tooltip"; - - -@import "frontend/llms-quizzes"; - -@import "frontend/voucher"; -@import "frontend/llms-access-plans"; -@import "frontend/checkout"; -@import "_includes/llms-form-field"; - -@import "frontend/llms-outline-collapse"; - -@import "frontend/student-dashboard"; - -@import "_includes/vendor/_font-awesome"; -@import "_includes/spinner"; diff --git a/assets/vendor/quill/LICENSE b/assets/vendor/quill/LICENSE deleted file mode 100644 index d5e2503294..0000000000 --- a/assets/vendor/quill/LICENSE +++ /dev/null @@ -1,30 +0,0 @@ -Copyright (c) 2014, Jason Chen -Copyright (c) 2013, salesforce.com -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/composer.json b/composer.json deleted file mode 100644 index db5bb07b3a..0000000000 --- a/composer.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "name": "gocodebox/lifterlms", - "description": "LifterLMS, the #1 WordPress LMS solution, makes it easy to create, sell, and protect engaging online courses.", - "keywords": [ - "WordPress", - "LMS" - ], - "homepage": "https://lifterlms.com", - "license": "GPL-2.0+", - "authors": [ - { - "name": "LifterLMS", - "email": "help@lifterlms.com", - "homepage": "https://lifterlms.com" - } - ], - "type": "wordpress-plugin", - "support": { - "forum": "https://wordpress.org/support/plugin/lifterlms", - "issues": "https://github.com/gocodebox/lifterlms/issues", - "source": "https://github.com/gocodebox/lifterlms" - }, - "autoload": { - "psr-4": { - "LLMS\\": "includes" - } - }, - "repositories": [ - { - "type": "vcs", - "url": "https://github.com/gocodebox/action-scheduler" - }, - { - "type": "vcs", - "url": "https://github.com/ericmann/wp-session-manager" - } - ], - "require": { - "gocodebox/action-scheduler": "dev-master", - "ericmann/wp-session-manager": "dev-master" - }, - "require-dev": { - "codeclimate/php-test-reporter": "dev-master", - "squizlabs/php_codesniffer": "2.*", - "wp-coding-standards/wpcs": "dev-master", - "phpunit/phpunit": "^5.6" - }, - "scripts": { - "post-install-cmd": [ - "\"vendor/bin/phpcs\" --config-set installed_paths ../../../vendor/wp-coding-standards/wpcs", - "\"vendor/bin/phpcs\" --config-set default_standard ./phpcs.xml" - ], - "phpcs": "./vendor/bin/phpcs --colors --extensions=php -n lifterlms.php includes/ templates/", - "phpunit": "./vendor/bin/phpunit", - "tests-install": [ - "mysql.server start", - "@tests-teardown", - "tests/bin/install.sh lifterlms_tests root password localhost latest" - ], - "tests-teardown": "tests/bin/teardown.sh lifterlms_tests root password localhost latest" - } -} diff --git a/composer.lock b/composer.lock deleted file mode 100644 index f7eddf6243..0000000000 --- a/composer.lock +++ /dev/null @@ -1,2277 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", - "This file is @generated automatically" - ], - "content-hash": "12614d184677a0c294d45efe310f9efd", - "packages": [ - { - "name": "ericmann/wp-session-manager", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/ericmann/wp-session-manager.git", - "reference": "8a4aacd25e4a89429e93a85df70a068052853cae" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ericmann/wp-session-manager/zipball/8a4aacd25e4a89429e93a85df70a068052853cae", - "reference": "8a4aacd25e4a89429e93a85df70a068052853cae", - "shasum": "" - }, - "type": "wordpress-plugin", - "license": [ - "GPLv2.0+" - ], - "authors": [ - { - "name": "Eric Mann", - "email": "eric@eamann.com", - "homepage": "https://eamann.com", - "role": "Developer" - } - ], - "description": "Prototype session management for WordPress.", - "homepage": "https://github.com/ericmann/wp-session-manager", - "keywords": [ - "session" - ], - "support": { - "source": "https://github.com/ericmann/wp-session-manager/tree/1.2.2", - "issues": "https://github.com/ericmann/wp-session-manager/issues" - }, - "time": "2017-04-26 13:27:37" - }, - { - "name": "gocodebox/action-scheduler", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/gocodebox/action-scheduler.git", - "reference": "d7b66cbf2d423bec4d4129a45f9969261ec1d2af" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/gocodebox/action-scheduler/zipball/d7b66cbf2d423bec4d4129a45f9969261ec1d2af", - "reference": "d7b66cbf2d423bec4d4129a45f9969261ec1d2af", - "shasum": "" - }, - "type": "library", - "authors": [ - { - "name": "Thomas Patrick Levy", - "email": "thomasplevy@gmail.com" - } - ], - "description": "Fork of https://github.com/Prospress/action-scheduler", - "support": { - "source": "https://github.com/gocodebox/action-scheduler/tree/master" - }, - "time": "2017-03-10 23:45:17" - } - ], - "packages-dev": [ - { - "name": "codeclimate/php-test-reporter", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/codeclimate/php-test-reporter.git", - "reference": "4eac73dc737c09961b1a6b8b73825666ebea28b5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/codeclimate/php-test-reporter/zipball/4eac73dc737c09961b1a6b8b73825666ebea28b5", - "reference": "4eac73dc737c09961b1a6b8b73825666ebea28b5", - "shasum": "" - }, - "require": { - "ext-curl": "*", - "padraic/phar-updater": "^1.0", - "php": "^5.3 || ^7.0", - "psr/log": "^1.0", - "satooshi/php-coveralls": "^1.0", - "symfony/console": "^2.0 || ^3.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.0.0", - "phpunit/phpunit": "^4.8.31" - }, - "bin": [ - "composer/bin/test-reporter" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.3.x-dev" - } - }, - "autoload": { - "psr-4": { - "CodeClimate\\PhpTestReporter\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Code Climate", - "email": "hello@codeclimate.com", - "homepage": "https://codeclimate.com" - } - ], - "description": "PHP client for reporting test coverage to Code Climate", - "homepage": "https://github.com/codeclimate/php-test-reporter", - "keywords": [ - "codeclimate", - "coverage" - ], - "time": "2017-04-24 15:47:41" - }, - { - "name": "doctrine/instantiator", - "version": "1.0.5", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", - "shasum": "" - }, - "require": { - "php": ">=5.3,<8.0-DEV" - }, - "require-dev": { - "athletic/athletic": "~0.1.8", - "ext-pdo": "*", - "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", - "keywords": [ - "constructor", - "instantiate" - ], - "time": "2015-06-14T21:17:01+00:00" - }, - { - "name": "guzzle/guzzle", - "version": "v3.9.3", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle3.git", - "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/0645b70d953bc1c067bbc8d5bc53194706b628d9", - "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9", - "shasum": "" - }, - "require": { - "ext-curl": "*", - "php": ">=5.3.3", - "symfony/event-dispatcher": "~2.1" - }, - "replace": { - "guzzle/batch": "self.version", - "guzzle/cache": "self.version", - "guzzle/common": "self.version", - "guzzle/http": "self.version", - "guzzle/inflection": "self.version", - "guzzle/iterator": "self.version", - "guzzle/log": "self.version", - "guzzle/parser": "self.version", - "guzzle/plugin": "self.version", - "guzzle/plugin-async": "self.version", - "guzzle/plugin-backoff": "self.version", - "guzzle/plugin-cache": "self.version", - "guzzle/plugin-cookie": "self.version", - "guzzle/plugin-curlauth": "self.version", - "guzzle/plugin-error-response": "self.version", - "guzzle/plugin-history": "self.version", - "guzzle/plugin-log": "self.version", - "guzzle/plugin-md5": "self.version", - "guzzle/plugin-mock": "self.version", - "guzzle/plugin-oauth": "self.version", - "guzzle/service": "self.version", - "guzzle/stream": "self.version" - }, - "require-dev": { - "doctrine/cache": "~1.3", - "monolog/monolog": "~1.0", - "phpunit/phpunit": "3.7.*", - "psr/log": "~1.0", - "symfony/class-loader": "~2.1", - "zendframework/zend-cache": "2.*,<2.3", - "zendframework/zend-log": "2.*,<2.3" - }, - "suggest": { - "guzzlehttp/guzzle": "Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated." - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.9-dev" - } - }, - "autoload": { - "psr-0": { - "Guzzle": "src/", - "Guzzle\\Tests": "tests/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Guzzle Community", - "homepage": "https://github.com/guzzle/guzzle/contributors" - } - ], - "description": "PHP HTTP client. This library is deprecated in favor of https://packagist.org/packages/guzzlehttp/guzzle", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ], - "abandoned": "guzzlehttp/guzzle", - "time": "2015-03-18T18:23:50+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.6.1", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/8e6e04167378abf1ddb4d3522d8755c5fd90d102", - "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102", - "shasum": "" - }, - "require": { - "php": ">=5.4.0" - }, - "require-dev": { - "doctrine/collections": "1.*", - "phpunit/phpunit": "~4.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "homepage": "https://github.com/myclabs/DeepCopy", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "time": "2017-04-12T18:52:22+00:00" - }, - { - "name": "padraic/humbug_get_contents", - "version": "1.0.4", - "source": { - "type": "git", - "url": "https://github.com/padraic/file_get_contents.git", - "reference": "66797199019d0cb4529cb8d29c6f0b4c5085b53a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/padraic/file_get_contents/zipball/66797199019d0cb4529cb8d29c6f0b4c5085b53a", - "reference": "66797199019d0cb4529cb8d29c6f0b4c5085b53a", - "shasum": "" - }, - "require": { - "php": ">=5.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "psr-4": { - "Humbug\\": "src/Humbug/" - }, - "files": [ - "src/function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Pádraic Brady", - "email": "padraic.brady@gmail.com", - "homepage": "http://blog.astrumfutura.com" - } - ], - "description": "Secure wrapper for accessing HTTPS resources with file_get_contents for PHP 5.3+", - "homepage": "https://github.com/padraic/file_get_contents", - "keywords": [ - "download", - "file_get_contents", - "http", - "https", - "ssl", - "tls" - ], - "time": "2015-04-22T18:45:00+00:00" - }, - { - "name": "padraic/phar-updater", - "version": "1.0.3", - "source": { - "type": "git", - "url": "https://github.com/padraic/phar-updater.git", - "reference": "c17eeb3887dc4269d1b4837dc875d39e9f8149a8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/padraic/phar-updater/zipball/c17eeb3887dc4269d1b4837dc875d39e9f8149a8", - "reference": "c17eeb3887dc4269d1b4837dc875d39e9f8149a8", - "shasum": "" - }, - "require": { - "padraic/humbug_get_contents": "^1.0", - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "psr-4": { - "Humbug\\SelfUpdate\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Pádraic Brady", - "email": "padraic.brady@gmail.com", - "homepage": "http://blog.astrumfutura.com" - } - ], - "description": "A thing to make PHAR self-updating easy and secure.", - "keywords": [ - "humbug", - "phar", - "self-update", - "update" - ], - "time": "2016-01-05T23:08:01+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "1.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", - "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", - "shasum": "" - }, - "require": { - "php": ">=5.5" - }, - "require-dev": { - "phpunit/phpunit": "^4.6" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "time": "2015-12-27T11:43:31+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "3.1.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", - "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", - "shasum": "" - }, - "require": { - "php": ">=5.5", - "phpdocumentor/reflection-common": "^1.0@dev", - "phpdocumentor/type-resolver": "^0.2.0", - "webmozart/assert": "^1.0" - }, - "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^4.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2016-09-30T07:12:33+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "0.2.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", - "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", - "shasum": "" - }, - "require": { - "php": ">=5.5", - "phpdocumentor/reflection-common": "^1.0" - }, - "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "time": "2016-11-25T06:54:22+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "v1.7.0", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "93d39f1f7f9326d746203c7c056f300f7f126073" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073", - "reference": "93d39f1f7f9326d746203c7c056f300f7f126073", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", - "sebastian/comparator": "^1.1|^2.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0" - }, - "require-dev": { - "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8 || ^5.6.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6.x-dev" - } - }, - "autoload": { - "psr-0": { - "Prophecy\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "time": "2017-03-02T20:05:34+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "4.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d", - "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-xmlwriter": "*", - "php": "^5.6 || ^7.0", - "phpunit/php-file-iterator": "^1.3", - "phpunit/php-text-template": "^1.2", - "phpunit/php-token-stream": "^1.4.2 || ^2.0", - "sebastian/code-unit-reverse-lookup": "^1.0", - "sebastian/environment": "^1.3.2 || ^2.0", - "sebastian/version": "^1.0 || ^2.0" - }, - "require-dev": { - "ext-xdebug": "^2.1.4", - "phpunit/phpunit": "^5.7" - }, - "suggest": { - "ext-xdebug": "^2.5.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "time": "2017-04-02T07:44:40+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "1.4.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "time": "2016-10-03T07:40:28+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "time": "2015-06-21T13:50:34+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "1.0.9", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "time": "2017-02-26T11:10:40+00:00" - }, - { - "name": "phpunit/php-token-stream", - "version": "1.4.11", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7", - "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "time": "2017-02-27T10:12:30+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "5.7.19", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "69c4f49ff376af2692bad9cebd883d17ebaa98a1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/69c4f49ff376af2692bad9cebd883d17ebaa98a1", - "reference": "69c4f49ff376af2692bad9cebd883d17ebaa98a1", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "myclabs/deep-copy": "~1.3", - "php": "^5.6 || ^7.0", - "phpspec/prophecy": "^1.6.2", - "phpunit/php-code-coverage": "^4.0.4", - "phpunit/php-file-iterator": "~1.4", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "^3.2", - "sebastian/comparator": "^1.2.4", - "sebastian/diff": "~1.2", - "sebastian/environment": "^1.3.4 || ^2.0", - "sebastian/exporter": "~2.0", - "sebastian/global-state": "^1.1", - "sebastian/object-enumerator": "~2.0", - "sebastian/resource-operations": "~1.0", - "sebastian/version": "~1.0.3|~2.0", - "symfony/yaml": "~2.1|~3.0" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "3.0.2" - }, - "require-dev": { - "ext-pdo": "*" - }, - "suggest": { - "ext-xdebug": "*", - "phpunit/php-invoker": "~1.1" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.7.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "time": "2017-04-03T02:22:27+00:00" - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "3.4.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", - "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.6 || ^7.0", - "phpunit/php-text-template": "^1.2", - "sebastian/exporter": "^1.2 || ^2.0" - }, - "conflict": { - "phpunit/phpunit": "<5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^5.4" - }, - "suggest": { - "ext-soap": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" - ], - "time": "2016-12-08T20:27:08+00:00" - }, - { - "name": "psr/log", - "version": "1.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "time": "2016-10-10T12:19:37+00:00" - }, - { - "name": "satooshi/php-coveralls", - "version": "v1.0.1", - "source": { - "type": "git", - "url": "https://github.com/satooshi/php-coveralls.git", - "reference": "da51d304fe8622bf9a6da39a8446e7afd432115c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/da51d304fe8622bf9a6da39a8446e7afd432115c", - "reference": "da51d304fe8622bf9a6da39a8446e7afd432115c", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-simplexml": "*", - "guzzle/guzzle": "^2.8|^3.0", - "php": ">=5.3.3", - "psr/log": "^1.0", - "symfony/config": "^2.1|^3.0", - "symfony/console": "^2.1|^3.0", - "symfony/stopwatch": "^2.0|^3.0", - "symfony/yaml": "^2.0|^3.0" - }, - "suggest": { - "symfony/http-kernel": "Allows Symfony integration" - }, - "bin": [ - "bin/coveralls" - ], - "type": "library", - "autoload": { - "psr-4": { - "Satooshi\\": "src/Satooshi/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Kitamura Satoshi", - "email": "with.no.parachute@gmail.com", - "homepage": "https://www.facebook.com/satooshi.jp" - } - ], - "description": "PHP client library for Coveralls API", - "homepage": "https://github.com/satooshi/php-coveralls", - "keywords": [ - "ci", - "coverage", - "github", - "test" - ], - "time": "2016-01-20T17:35:46+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2017-03-04T06:30:41+00:00" - }, - { - "name": "sebastian/comparator", - "version": "1.2.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2 || ~2.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "time": "2017-01-29T09:50:25+00:00" - }, - { - "name": "sebastian/diff", - "version": "1.4.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff" - ], - "time": "2015-12-08T07:14:41+00:00" - }, - { - "name": "sebastian/environment", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", - "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^5.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "time": "2016-11-26T07:53:53+00:00" - }, - { - "name": "sebastian/exporter", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", - "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "sebastian/recursion-context": "~2.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "time": "2016-11-19T08:54:04+00:00" - }, - { - "name": "sebastian/global-state", - "version": "1.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "time": "2015-10-12T03:26:01+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7", - "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7", - "shasum": "" - }, - "require": { - "php": ">=5.6", - "sebastian/recursion-context": "~2.0" - }, - "require-dev": { - "phpunit/phpunit": "~5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-02-18T15:18:39+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", - "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2016-11-19T07:33:16+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", - "shasum": "" - }, - "require": { - "php": ">=5.6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2015-07-28T20:34:47+00:00" - }, - { - "name": "sebastian/version", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", - "shasum": "" - }, - "require": { - "php": ">=5.6" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-10-03T07:35:21+00:00" - }, - { - "name": "squizlabs/php_codesniffer", - "version": "2.8.1", - "source": { - "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "d7cf0d894e8aa4c73712ee4a331cc1eaa37cdc7d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/d7cf0d894e8aa4c73712ee4a331cc1eaa37cdc7d", - "reference": "d7cf0d894e8aa4c73712ee4a331cc1eaa37cdc7d", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.1.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "bin": [ - "scripts/phpcs", - "scripts/phpcbf" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "classmap": [ - "CodeSniffer.php", - "CodeSniffer/CLI.php", - "CodeSniffer/Exception.php", - "CodeSniffer/File.php", - "CodeSniffer/Fixer.php", - "CodeSniffer/Report.php", - "CodeSniffer/Reporting.php", - "CodeSniffer/Sniff.php", - "CodeSniffer/Tokens.php", - "CodeSniffer/Reports/", - "CodeSniffer/Tokenizers/", - "CodeSniffer/DocGenerators/", - "CodeSniffer/Standards/AbstractPatternSniff.php", - "CodeSniffer/Standards/AbstractScopeSniff.php", - "CodeSniffer/Standards/AbstractVariableSniff.php", - "CodeSniffer/Standards/IncorrectPatternException.php", - "CodeSniffer/Standards/Generic/Sniffs/", - "CodeSniffer/Standards/MySource/Sniffs/", - "CodeSniffer/Standards/PEAR/Sniffs/", - "CodeSniffer/Standards/PSR1/Sniffs/", - "CodeSniffer/Standards/PSR2/Sniffs/", - "CodeSniffer/Standards/Squiz/Sniffs/", - "CodeSniffer/Standards/Zend/Sniffs/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "lead" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "http://www.squizlabs.com/php-codesniffer", - "keywords": [ - "phpcs", - "standards" - ], - "time": "2017-03-01T22:17:45+00:00" - }, - { - "name": "symfony/config", - "version": "v3.2.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/config.git", - "reference": "e5533fcc0b3dd377626153b2852707878f363728" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/e5533fcc0b3dd377626153b2852707878f363728", - "reference": "e5533fcc0b3dd377626153b2852707878f363728", - "shasum": "" - }, - "require": { - "php": ">=5.5.9", - "symfony/filesystem": "~2.8|~3.0" - }, - "require-dev": { - "symfony/yaml": "~3.0" - }, - "suggest": { - "symfony/yaml": "To use the yaml reference dumper" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Config\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Config Component", - "homepage": "https://symfony.com", - "time": "2017-04-12T14:13:17+00:00" - }, - { - "name": "symfony/console", - "version": "v3.2.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "a7a17e0c6c3c4d70a211f80782e4b90ddadeaa38" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/a7a17e0c6c3c4d70a211f80782e4b90ddadeaa38", - "reference": "a7a17e0c6c3c4d70a211f80782e4b90ddadeaa38", - "shasum": "" - }, - "require": { - "php": ">=5.5.9", - "symfony/debug": "~2.8|~3.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/event-dispatcher": "~2.8|~3.0", - "symfony/filesystem": "~2.8|~3.0", - "symfony/process": "~2.8|~3.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/filesystem": "", - "symfony/process": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Console Component", - "homepage": "https://symfony.com", - "time": "2017-04-26T01:39:17+00:00" - }, - { - "name": "symfony/debug", - "version": "v3.2.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/debug.git", - "reference": "fd6eeee656a5a7b384d56f1072243fe1c0e81686" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/fd6eeee656a5a7b384d56f1072243fe1c0e81686", - "reference": "fd6eeee656a5a7b384d56f1072243fe1c0e81686", - "shasum": "" - }, - "require": { - "php": ">=5.5.9", - "psr/log": "~1.0" - }, - "conflict": { - "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" - }, - "require-dev": { - "symfony/class-loader": "~2.8|~3.0", - "symfony/http-kernel": "~2.8|~3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Debug\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Debug Component", - "homepage": "https://symfony.com", - "time": "2017-04-19T20:17:50+00:00" - }, - { - "name": "symfony/event-dispatcher", - "version": "v2.8.20", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "7fc8e2b4118ff316550596357325dfd92a51f531" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7fc8e2b4118ff316550596357325dfd92a51f531", - "reference": "7fc8e2b4118ff316550596357325dfd92a51f531", - "shasum": "" - }, - "require": { - "php": ">=5.3.9" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "^2.0.5|~3.0.0", - "symfony/dependency-injection": "~2.6|~3.0.0", - "symfony/expression-language": "~2.6|~3.0.0", - "symfony/stopwatch": "~2.3|~3.0.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony EventDispatcher Component", - "homepage": "https://symfony.com", - "time": "2017-04-26T16:56:54+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v3.2.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "040651db13cf061827a460cc10f6e36a445c45b4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/040651db13cf061827a460cc10f6e36a445c45b4", - "reference": "040651db13cf061827a460cc10f6e36a445c45b4", - "shasum": "" - }, - "require": { - "php": ">=5.5.9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Filesystem Component", - "homepage": "https://symfony.com", - "time": "2017-04-12T14:13:17+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.3.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4", - "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "time": "2016-11-14T01:06:16+00:00" - }, - { - "name": "symfony/stopwatch", - "version": "v3.2.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "5a0105afb670dbd38f521105c444de1b8e10cfe3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5a0105afb670dbd38f521105c444de1b8e10cfe3", - "reference": "5a0105afb670dbd38f521105c444de1b8e10cfe3", - "shasum": "" - }, - "require": { - "php": ">=5.5.9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Stopwatch Component", - "homepage": "https://symfony.com", - "time": "2017-04-12T14:13:17+00:00" - }, - { - "name": "symfony/yaml", - "version": "v3.2.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "acec26fcf7f3031e094e910b94b002fa53d4e4d6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/acec26fcf7f3031e094e910b94b002fa53d4e4d6", - "reference": "acec26fcf7f3031e094e910b94b002fa53d4e4d6", - "shasum": "" - }, - "require": { - "php": ">=5.5.9" - }, - "require-dev": { - "symfony/console": "~2.8|~3.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", - "time": "2017-05-01T14:55:58+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.2.0", - "source": { - "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", - "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "time": "2016-11-23T20:04:58+00:00" - }, - { - "name": "wp-coding-standards/wpcs", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards.git", - "reference": "407e4b85f547a5251185f89ceae6599917343388" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/WordPress-Coding-Standards/WordPress-Coding-Standards/zipball/407e4b85f547a5251185f89ceae6599917343388", - "reference": "407e4b85f547a5251185f89ceae6599917343388", - "shasum": "" - }, - "require": { - "squizlabs/php_codesniffer": "^2.8.1" - }, - "type": "library", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Contributors", - "homepage": "https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/graphs/contributors" - } - ], - "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress coding conventions", - "keywords": [ - "phpcs", - "standards", - "wordpress" - ], - "time": "2017-03-20 23:17:58" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": { - "gocodebox/action-scheduler": 20, - "ericmann/wp-session-manager": 20, - "codeclimate/php-test-reporter": 20, - "wp-coding-standards/wpcs": 20 - }, - "prefer-stable": false, - "prefer-lowest": false, - "platform": [], - "platform-dev": [] -} diff --git a/gulpfile.js/index.js b/gulpfile.js/index.js deleted file mode 100644 index ad8775913e..0000000000 --- a/gulpfile.js/index.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Main Gulp File - * - * Requires all task files - */ -var gulp = require('gulp'); - -// all tasks from lib-tasks -require( 'lifterlms-lib-tasks' )( gulp ); - -// all custom tasks -require( './tasks/js:additional' ); -require( './tasks/js:builder' ); -require( './tasks/readme' ); -require( './tasks/versioner:readme' ); diff --git a/gulpfile.js/tasks/js:additional.js b/gulpfile.js/tasks/js:additional.js deleted file mode 100644 index e9941c109c..0000000000 --- a/gulpfile.js/tasks/js:additional.js +++ /dev/null @@ -1,41 +0,0 @@ -var gulp = require( 'gulp' ) - , header = require( 'gulp-header' ) - , include = require( 'gulp-include' ) - , maps = require( 'gulp-sourcemaps' ) - , pump = require( 'pump' ) - , rename = require( 'gulp-rename' ) - , uglify = require( 'gulp-uglify' ) -; - -gulp.task( 'js:additional', function( cb ) { - - var notice = [ - '/****************************************************************', - ' *', - ' * Contributor\'s Notice', - ' * ', - ' * This is a compiled file and should not be edited directly!', - ' * The uncompiled script is located in the "assets/private" directory', - ' * ', - ' ****************************************************************/', - '', - '', - ]; - - pump( [ - gulp.src( 'assets/js/private/**/*.js' ), - maps.init(), - include(), - header( notice.join( '\n' ) ), - gulp.dest( 'assets/js' ), - uglify(), - rename( { - suffix: '.min', - } ), - maps.write(), - gulp.dest( 'assets/js' ) - ], - cb - ); - -} ); diff --git a/gulpfile.js/tasks/js:builder.js b/gulpfile.js/tasks/js:builder.js deleted file mode 100644 index e9a190cf74..0000000000 --- a/gulpfile.js/tasks/js:builder.js +++ /dev/null @@ -1,63 +0,0 @@ -/** - * ----------------------------------------------------------- - * js:builder - * ----------------------------------------------------------- - * Compile Admin builder Javascript - */ - -var gulp = require( 'gulp' ) - , notify = require( 'gulp-notify' ) - , requirejsOptimize = require( 'gulp-requirejs-optimize' ) - , rename = require( 'gulp-rename' ) - , sourcemaps = require( 'gulp-sourcemaps' ) -; - -gulp.task( 'js:builder', function() { - - gulp.src( 'assets/js/builder/main.js' ) - // unminified - .pipe( sourcemaps.init() ) - .pipe( requirejsOptimize( function( file ) { - return { - name: 'vendor/almond', - optimize: 'none', - wrap: { - start: "(function($){", - end: "}(jQuery));" - }, - baseUrl: 'assets/js/builder/', - include: [ 'main' ], - preserveLicenseComments: false - }; - } ).on( 'error', notify.onError( { - message: '<%= error.message %>', - sound: 'Frog', - title: 'js:builder error' - } ) ) ) - .pipe( rename( 'llms-builder.js' ) ) - .pipe( sourcemaps.write('/') ) - .pipe( gulp.dest( 'assets/js/' ) ) - - // minified - .pipe( sourcemaps.init() ) - .pipe( requirejsOptimize( function( file ) { - return { - name: 'vendor/almond', - optimize: 'uglify2', - wrap: { - start: "(function($){", - end: "}(jQuery));" - }, - baseUrl: 'assets/js/builder/', - include: [ 'main' ], - preserveLicenseComments: false - }; - } ).on( 'error', notify.onError( { - message: '<%= error.message %>', - sound: 'Frog', - title: 'js:builder error' - } ) ) ) - .pipe( rename( 'llms-builder.min.js' ) ) - .pipe( sourcemaps.write('/') ) - .pipe( gulp.dest( 'assets/js/' ) ); -}); diff --git a/gulpfile.js/tasks/readme.js b/gulpfile.js/tasks/readme.js deleted file mode 100644 index 1cc2e4fc85..0000000000 --- a/gulpfile.js/tasks/readme.js +++ /dev/null @@ -1,74 +0,0 @@ -/** - * ----------------------------------------------------------- - * readme - * ----------------------------------------------------------- - * - * Generate a readme.txt from _readme files - * - */ - -var gulp = require( 'gulp' ), - fs = require( 'fs' ), - include = require( 'gulp-include' ) -; - -/** - * Convert the CHANGELOG.md file to the format WP.org needs for the special mdown - */ -function changelog( cb ) { - - fs.readFile( './CHANGELOG.md', 'utf8', function( err, data ) { - - if ( err ) { - return console.log( err ); - } - - var counter = 0, - stop; - - data = data.replace( 'LifterLMS Changelog', '== Changelog ==' ); - data = data.replace( '===================', '' ); - - data = data.replace( /v\d+\.\d+\.\d+ - \d{4}\-\d{2}\-\d{2}/g, function( match ) { - - if ( 10 === counter ) { - stop = match; - } - - counter++; - - return '= ' + match + ' ='; - - } ); - - data = data.substring( 0, data.indexOf( stop ) - 5 ); - - // b/c ocd... - data = data.replace( /-------------------/g, '-----------------------' ); - - // write to the file in _readme dir - fs.writeFile( './_readme/changelog.md', data, 'utf8', function( err ) { - - if ( err ) { - return console.log( err ); - } - - cb(); - - }); - - - } ); - -} - -gulp.task( 'readme', function() { - changelog( function() { - - return gulp.src( '_readme/readme.txt' ) - .pipe( include() ) - .pipe( gulp.dest( './' ) ); - - } ); - -} ); diff --git a/gulpfile.js/tasks/versioner:readme.js b/gulpfile.js/tasks/versioner:readme.js deleted file mode 100644 index 12c70b0979..0000000000 --- a/gulpfile.js/tasks/versioner:readme.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * ----------------------------------------------------------- - * Versioner - * ----------------------------------------------------------- - * - * Update placeholder @since & @version docblocks - * witn an actual version numbers - * - * Usage: gulp versioner -V 9.9.9 - */ - -var gulp = require( 'gulp' ) - , replace = require( 'gulp-replace' ) - , argv = require( 'yargs' ).argv - , gutil = require( 'gulp-util' ) -; - -gulp.task( 'versioner:readme', function() { - - var the_version = argv.V; - - if ( ! the_version ) { - gutil.log( gutil.colors.red( 'Missing version number. Try `gulp versioner -V 9.9.9`' ) ); - return; - } - - return gulp.src( [ './_readme/header.md' ], { base: './' } ) - .pipe( replace( /Stable tag: (\d+\.\d+\.\d+)/g, function( match, p1, offset, string ) { - return match.replace( p1, the_version ); - } ) ) - .pipe( gulp.dest( './' ) ); - -} ); diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 56c1ba8b3b..0000000000 --- a/package-lock.json +++ /dev/null @@ -1,7883 +0,0 @@ -{ - "name": "lifterlms", - "version": "3.17.8", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@gulp-sourcemaps/identity-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz", - "integrity": "sha1-z6I7xYQPkQTOMqZedNt+epdLvuE=", - "dev": true, - "requires": { - "acorn": "5.4.0", - "css": "2.2.1", - "normalize-path": "2.1.1", - "source-map": "0.5.7", - "through2": "2.0.3" - } - }, - "@gulp-sourcemaps/map-sources": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", - "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", - "dev": true, - "requires": { - "normalize-path": "2.1.1", - "through2": "2.0.3" - } - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "acorn": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.4.0.tgz", - "integrity": "sha512-bkLTrtPfRASTxDXFaih7SbeYSsQ8MjrqCQKMrgZ4Hc7kYI//WVU6rDTAIqVrAudjgMFQEGthYfodtaw8dTRJrg==", - "dev": true - }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-cyan": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", - "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-red": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", - "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true - }, - "ansicolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.2.1.tgz", - "integrity": "sha1-vgiVmQl7dKXJxKhKDNvNtivYeu8=", - "dev": true - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", - "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", - "dev": true, - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true - }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true - }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", - "dev": true - }, - "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", - "dev": true - }, - "async-foreach": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", - "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "atob": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", - "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=", - "dev": true - }, - "autoprefixer": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-8.4.1.tgz", - "integrity": "sha512-YqUclCBDXUT9Y7aQ8Xv+ja8yhTZYJoMsOD7WS++gZIJLCpCu+gPcKGDlhk6S3WxhLkTcNVdaMZAWys2nzZCH7g==", - "dev": true, - "requires": { - "browserslist": "3.2.6", - "caniuse-lite": "1.0.30000833", - "normalize-range": "0.1.2", - "num2fraction": "1.2.2", - "postcss": "6.0.22", - "postcss-value-parser": "3.3.0" - } - }, - "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", - "dev": true - }, - "aws4": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", - "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "1.0.1", - "class-utils": "0.3.6", - "component-emitter": "1.2.1", - "define-property": "1.0.0", - "isobject": "3.0.1", - "mixin-deep": "1.3.0", - "pascalcase": "0.1.1" - } - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "dev": true, - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "beeper": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", - "dev": true - }, - "binaryextensions": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-1.0.1.tgz", - "integrity": "sha1-HmN0iLNbWL2l9HdL+WpSEqjJB1U=", - "dev": true - }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, - "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "dev": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "1.1.0", - "array-unique": "0.3.2", - "extend-shallow": "2.0.1", - "fill-range": "4.0.0", - "isobject": "3.0.1", - "repeat-element": "1.1.2", - "snapdragon": "0.8.1", - "snapdragon-node": "2.1.1", - "split-string": "3.1.0", - "to-regex": "3.0.1" - } - }, - "browserslist": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.6.tgz", - "integrity": "sha512-XCsMSg9V4S1VRdcp265dJ+8kBRjfuFXcavbisY7G6T9QI0H1Z24PP53vvs0WDYWqm38Mco1ILDtafcS8ZR4xiw==", - "dev": true, - "requires": { - "caniuse-lite": "1.0.30000833", - "electron-to-chromium": "1.3.45" - } - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "1.0.0", - "component-emitter": "1.2.1", - "get-value": "2.0.6", - "has-value": "1.0.0", - "isobject": "3.0.1", - "set-value": "2.0.0", - "to-object-path": "0.3.0", - "union-value": "1.0.0", - "unset-value": "1.0.0" - } - }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "requires": { - "camelcase": "2.1.1", - "map-obj": "1.0.1" - } - }, - "caniuse-lite": { - "version": "1.0.30000833", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000833.tgz", - "integrity": "sha512-tKNuKu4WLImh4NxoTgntxFpDrRiA0Q6Q1NycNhuMST0Kx+Pt8YnRDW6V8xsyH6AtO2CpAoibatEk5eaEhP3O1g==", - "dev": true - }, - "cardinal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-1.0.0.tgz", - "integrity": "sha1-UOIcGwqjdyn5N33vGWtanOyTLuk=", - "dev": true, - "requires": { - "ansicolors": "0.2.1", - "redeyed": "1.0.1" - } - }, - "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", - "dev": true - }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" - }, - "dependencies": { - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true - } - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "3.1.0", - "define-property": "0.2.5", - "isobject": "3.0.1", - "static-extend": "0.1.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "cli-table": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", - "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", - "dev": true, - "requires": { - "colors": "1.0.3" - } - }, - "cli-usage": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/cli-usage/-/cli-usage-0.1.7.tgz", - "integrity": "sha512-x/Q52iLSZsRrRb2ePmTsVYXrGcrPQ8G4yRAY7QpMlumxAfPVrnDOH2X6Z5s8qsAX7AA7YuIi8AXFrvH0wWEesA==", - "dev": true, - "requires": { - "marked": "0.3.12", - "marked-terminal": "2.0.0" - } - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", - "wordwrap": "0.0.2" - } - }, - "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", - "dev": true - }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "cloneable-readable": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", - "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", - "dev": true, - "requires": { - "inherits": "2.0.3", - "process-nextick-args": "2.0.0", - "readable-stream": "2.3.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "1.0.0", - "object-visit": "1.0.1" - } - }, - "color-convert": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, - "colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", - "dev": true - }, - "combined-stream": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", - "dev": true, - "requires": { - "delayed-stream": "1.0.0" - } - }, - "commander": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.1.0.tgz", - "integrity": "sha1-0SG7roYNmZKj1Re6lvVliOR8Z4E=", - "dev": true - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-with-sourcemaps": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.7.tgz", - "integrity": "sha512-5i4Spc9NNvVXzkR77x2kjcYCDZMNPLzP7ZBzJMNKZjXzk+E6tRVL/lPlYw60VM3hb7gf+iBQn2x1T8TpMN0SEw==", - "dev": true, - "requires": { - "source-map": "0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, - "convert-source-map": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", - "dev": true - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cross-spawn": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", - "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", - "dev": true, - "requires": { - "lru-cache": "4.1.2", - "which": "1.3.0" - }, - "dependencies": { - "lru-cache": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", - "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", - "dev": true, - "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" - } - } - } - }, - "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "dev": true, - "requires": { - "boom": "2.10.1" - } - }, - "css": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", - "integrity": "sha1-c6TIHehdtmTU7mdPfUcIXjstVdw=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "source-map": "0.1.43", - "source-map-resolve": "0.3.1", - "urix": "0.1.0" - }, - "dependencies": { - "atob": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", - "integrity": "sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M=", - "dev": true - }, - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "dev": true, - "requires": { - "amdefine": "1.0.1" - } - }, - "source-map-resolve": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", - "integrity": "sha1-YQ9hIqRFuN1RU1oqcbeD38Ekh2E=", - "dev": true, - "requires": { - "atob": "1.1.3", - "resolve-url": "0.2.1", - "source-map-url": "0.3.0", - "urix": "0.1.0" - } - }, - "source-map-url": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", - "integrity": "sha1-fsrxO1e80J2opAxdJp2zN5nUqvk=", - "dev": true - } - } - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "1.0.2" - } - }, - "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "dev": true, - "requires": { - "es5-ext": "0.10.38" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "dateformat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", - "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", - "dev": true - }, - "deap": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deap/-/deap-1.0.1.tgz", - "integrity": "sha512-k75KYNZMvwAwes2xIPry/QTffXIchjD8QfABvvfTr80P85jv5ZcKqcoDo+vMe71nNnVnXYe8MA28weyqcf/DKw==", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "debug-fabulous": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.0.0.tgz", - "integrity": "sha512-dsd50qQ1atDeurcxL7XOjPp4nZCGZzWIONDujDXzl1atSyC3hMbZD+v6440etw+Vt0Pr8ce4TQzHfX3KZM05Mw==", - "dev": true, - "requires": { - "debug": "3.1.0", - "memoizee": "0.4.11", - "object-assign": "4.1.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - } - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "1.0.3" - } - }, - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "1.0.2" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, - "deprecated": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", - "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", - "dev": true - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, - "detect-newline": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", - "dev": true - }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", - "dev": true - }, - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "1.1.14" - } - }, - "duplexify": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.4.tgz", - "integrity": "sha512-JzYSLYMhoVVBe8+mbHQ4KgpvHpm0DZpJuL8PY93Vyv1fW7jYJ90LoXa1di/CVbJM+TgMs91rbDapE/RNIfnJsA==", - "dev": true, - "requires": { - "end-of-stream": "1.4.1", - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "stream-shift": "1.0.0" - }, - "dependencies": { - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, - "requires": { - "once": "1.4.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "dev": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "electron-to-chromium": { - "version": "1.3.45", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.45.tgz", - "integrity": "sha1-RYrBscXHYM6IEaFtK/vZfsMLr7g=", - "dev": true - }, - "end-of-stream": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", - "dev": true, - "requires": { - "once": "1.3.3" - } - }, - "error-ex": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", - "dev": true, - "requires": { - "is-arrayish": "0.2.1" - } - }, - "es5-ext": { - "version": "0.10.38", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.38.tgz", - "integrity": "sha512-jCMyePo7AXbUESwbl8Qi01VSH2piY9s/a3rSU/5w/MlTIx8HPL1xn2InGN8ejt/xulcJgnTO7vqNtOAxzYd2Kg==", - "dev": true, - "requires": { - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.38", - "es6-symbol": "3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.38" - } - }, - "es6-weak-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.38", - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.38" - } - }, - "event-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.1.7.tgz", - "integrity": "sha1-tMVAAS0P4UmEIPPYlGAI22OTw3o=", - "dev": true, - "requires": { - "duplexer": "0.1.1", - "from": "0.1.7", - "map-stream": "0.1.0", - "pause-stream": "0.0.11", - "split": "0.2.10", - "stream-combiner": "0.0.4", - "through": "2.3.8" - } - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "4.1.2", - "shebang-command": "1.2.0", - "which": "1.3.0" - } - }, - "lru-cache": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", - "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", - "dev": true, - "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" - } - } - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "posix-character-classes": "0.1.1", - "regex-not": "1.0.0", - "snapdragon": "0.8.1", - "to-regex": "3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, - "requires": { - "fill-range": "2.2.3" - }, - "dependencies": { - "fill-range": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", - "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", - "dev": true, - "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "1.1.7", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" - } - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "1.0.1" - } - }, - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", - "dev": true - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "0.3.2", - "define-property": "1.0.0", - "expand-brackets": "2.1.4", - "extend-shallow": "2.0.1", - "fragment-cache": "0.2.1", - "regex-not": "1.0.0", - "snapdragon": "0.8.1", - "to-regex": "3.0.1" - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fancy-log": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", - "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", - "dev": true, - "requires": { - "ansi-gray": "0.1.1", - "color-support": "1.1.3", - "time-stamp": "1.1.0" - } - }, - "fd-slicer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", - "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", - "dev": true, - "requires": { - "pend": "1.2.0" - } - }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "2.0.1", - "is-number": "3.0.0", - "repeat-string": "1.6.1", - "to-regex-range": "2.1.1" - } - }, - "find-index": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", - "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", - "dev": true - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" - } - }, - "findup": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/findup/-/findup-0.1.5.tgz", - "integrity": "sha1-itkpozk7rGJ5V6fl3kYjsGsOLOs=", - "dev": true, - "requires": { - "colors": "0.6.2", - "commander": "2.1.0" - }, - "dependencies": { - "colors": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", - "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=", - "dev": true - } - } - }, - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "1.0.0", - "is-glob": "3.1.0", - "micromatch": "3.1.10", - "resolve-dir": "1.0.1" - } - }, - "fined": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", - "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", - "dev": true, - "requires": { - "expand-tilde": "2.0.2", - "is-plain-object": "2.0.4", - "object.defaults": "1.1.0", - "object.pick": "1.3.0", - "parse-filepath": "1.0.2" - } - }, - "first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", - "dev": true - }, - "flagged-respawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", - "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", - "dev": true - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "1.0.2" - } - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", - "dev": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.6", - "mime-types": "2.1.18" - } - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "0.2.2" - } - }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", - "dev": true - }, - "fs-extra": { - "version": "0.26.7", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz", - "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "jsonfile": "2.4.0", - "klaw": "1.3.1", - "path-is-absolute": "1.0.1", - "rimraf": "2.6.2" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - } - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fstream": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.2" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - } - } - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - }, - "dependencies": { - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - } - } - }, - "gaze": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", - "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", - "dev": true, - "requires": { - "globule": "0.1.0" - } - }, - "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", - "dev": true - }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "requires": { - "is-property": "1.0.2" - } - }, - "get-caller-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", - "dev": true - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "glob": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "2.0.10", - "once": "1.3.3" - } - }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" - }, - "dependencies": { - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "2.0.1" - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - } - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "3.1.0", - "path-dirname": "1.0.2" - } - }, - "glob-stream": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", - "dev": true, - "requires": { - "glob": "4.5.3", - "glob2base": "0.0.12", - "minimatch": "2.0.10", - "ordered-read-streams": "0.1.0", - "through2": "0.6.5", - "unique-stream": "1.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - } - } - }, - "glob-watcher": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "dev": true, - "requires": { - "gaze": "0.5.2" - } - }, - "glob2base": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", - "dev": true, - "requires": { - "find-index": "0.1.1" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "1.0.2", - "is-windows": "1.0.2", - "resolve-dir": "1.0.1" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "2.0.2", - "homedir-polyfill": "1.0.1", - "ini": "1.3.5", - "is-windows": "1.0.2", - "which": "1.3.0" - } - }, - "globule": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", - "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", - "dev": true, - "requires": { - "glob": "3.1.21", - "lodash": "1.0.2", - "minimatch": "0.2.14" - }, - "dependencies": { - "glob": { - "version": "3.1.21", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "dev": true, - "requires": { - "graceful-fs": "1.2.3", - "inherits": "1.0.2", - "minimatch": "0.2.14" - } - }, - "graceful-fs": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", - "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", - "dev": true - }, - "inherits": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", - "dev": true - }, - "minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true, - "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" - } - } - } - }, - "glogg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", - "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", - "dev": true, - "requires": { - "sparkles": "1.0.0" - } - }, - "graceful-fs": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true, - "requires": { - "natives": "1.1.3" - } - }, - "growly": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", - "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", - "dev": true - }, - "gulp": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", - "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", - "dev": true, - "requires": { - "archy": "1.0.0", - "chalk": "1.1.3", - "deprecated": "0.0.1", - "gulp-util": "3.0.8", - "interpret": "1.1.0", - "liftoff": "2.5.0", - "minimist": "1.2.0", - "orchestrator": "0.3.8", - "pretty-hrtime": "1.0.3", - "semver": "4.3.6", - "tildify": "1.2.0", - "v8flags": "2.1.1", - "vinyl-fs": "0.3.14" - } - }, - "gulp-autoprefixer": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/gulp-autoprefixer/-/gulp-autoprefixer-5.0.0.tgz", - "integrity": "sha1-gjfCeKaXdScKHK/n1vEBz81YVUQ=", - "dev": true, - "requires": { - "autoprefixer": "8.4.1", - "fancy-log": "1.3.2", - "plugin-error": "1.0.1", - "postcss": "6.0.22", - "through2": "2.0.3", - "vinyl-sourcemaps-apply": "0.2.1" - } - }, - "gulp-checktextdomain": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/gulp-checktextdomain/-/gulp-checktextdomain-2.1.1.tgz", - "integrity": "sha1-lFpwn38QqEksg+VoynbElf7LIDk=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "fs-extra": "0.26.7", - "gulp-util": "3.0.8", - "php-parser": "2.2.0", - "ramda": "0.20.1", - "text-table": "0.2.0", - "through2": "2.0.3" - } - }, - "gulp-composer": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/gulp-composer/-/gulp-composer-0.4.5.tgz", - "integrity": "sha512-k4Wep10UwqX1mKFWGaKTIJp1isuAyE+Y3OZccUCAMPvwbppNc6pYKfer25gZI82N/GYHlLKas67dRDv1SrdDVQ==", - "dev": true, - "requires": { - "ansi-colors": "1.1.0", - "fancy-log": "1.3.2", - "plugin-error": "1.0.1", - "shelljs": "0.2.6", - "through2": "2.0.3" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "2.3.6", - "xtend": "4.0.1" - } - } - } - }, - "gulp-header": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-2.0.5.tgz", - "integrity": "sha512-7bOIiHvM1GUHIG3LRH+UIanOxyjSys0FbzzgUBlV2cZIIZihEW+KKKKm0ejUBNGvRdhISEFFr6HlptXoa28gtQ==", - "dev": true, - "requires": { - "concat-with-sourcemaps": "1.0.7", - "lodash.template": "4.4.0", - "through2": "2.0.3" - }, - "dependencies": { - "lodash.template": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", - "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", - "dev": true, - "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.templatesettings": "4.1.0" - } - }, - "lodash.templatesettings": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", - "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", - "dev": true, - "requires": { - "lodash._reinterpolate": "3.0.0" - } - } - } - }, - "gulp-include": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/gulp-include/-/gulp-include-1.1.1.tgz", - "integrity": "sha1-/mLn9othXniAyTmY+mIImRj7kyc=", - "dev": true, - "requires": { - "event-stream": "3.1.7", - "glob": "4.5.3", - "gulp-util": "2.2.20" - }, - "dependencies": { - "ansi-regex": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", - "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", - "dev": true - }, - "ansi-styles": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", - "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", - "dev": true - }, - "chalk": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", - "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", - "dev": true, - "requires": { - "ansi-styles": "1.1.0", - "escape-string-regexp": "1.0.5", - "has-ansi": "0.1.0", - "strip-ansi": "0.3.0", - "supports-color": "0.2.0" - } - }, - "dateformat": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true, - "requires": { - "get-stdin": "4.0.1", - "meow": "3.7.0" - } - }, - "gulp-util": { - "version": "2.2.20", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", - "integrity": "sha1-1xRuVyiRC9jwR6awseVJvCLb1kw=", - "dev": true, - "requires": { - "chalk": "0.5.1", - "dateformat": "1.0.12", - "lodash._reinterpolate": "2.4.1", - "lodash.template": "2.4.1", - "minimist": "0.2.0", - "multipipe": "0.1.2", - "through2": "0.5.1", - "vinyl": "0.2.3" - } - }, - "has-ansi": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", - "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", - "dev": true, - "requires": { - "ansi-regex": "0.2.1" - } - }, - "lodash._reinterpolate": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", - "integrity": "sha1-TxInqlqHEfxjL1sHofRgequLMiI=", - "dev": true - }, - "lodash.escape": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", - "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", - "dev": true, - "requires": { - "lodash._escapehtmlchar": "2.4.1", - "lodash._reunescapedhtml": "2.4.1", - "lodash.keys": "2.4.1" - } - }, - "lodash.keys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "2.4.1", - "lodash._shimkeys": "2.4.1", - "lodash.isobject": "2.4.1" - } - }, - "lodash.template": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", - "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", - "dev": true, - "requires": { - "lodash._escapestringchar": "2.4.1", - "lodash._reinterpolate": "2.4.1", - "lodash.defaults": "2.4.1", - "lodash.escape": "2.4.1", - "lodash.keys": "2.4.1", - "lodash.templatesettings": "2.4.1", - "lodash.values": "2.4.1" - } - }, - "lodash.templatesettings": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", - "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", - "dev": true, - "requires": { - "lodash._reinterpolate": "2.4.1", - "lodash.escape": "2.4.1" - } - }, - "minimist": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", - "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "strip-ansi": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", - "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", - "dev": true, - "requires": { - "ansi-regex": "0.2.1" - } - }, - "supports-color": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", - "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", - "dev": true - }, - "through2": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", - "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "3.0.0" - } - }, - "vinyl": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", - "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", - "dev": true, - "requires": { - "clone-stats": "0.0.1" - } - }, - "xtend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", - "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", - "dev": true - } - } - }, - "gulp-notify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/gulp-notify/-/gulp-notify-2.2.0.tgz", - "integrity": "sha1-BGyChcKS6X7tThWgCcJsu+XO8TU=", - "dev": true, - "requires": { - "gulp-util": "3.0.8", - "lodash.template": "3.6.2", - "node-notifier": "4.6.1", - "node.extend": "1.1.6", - "through2": "0.6.5" - }, - "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - } - } - }, - "gulp-rename": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.2.tgz", - "integrity": "sha1-OtRCh2PwXidk3sHGfYaNsnVoeBc=", - "dev": true - }, - "gulp-replace": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-0.5.4.tgz", - "integrity": "sha1-aaZ5FLvRPFYr/xT1BKQDeWqg2qk=", - "dev": true, - "requires": { - "istextorbinary": "1.0.2", - "readable-stream": "2.3.3", - "replacestream": "4.0.3" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "gulp-requirejs-optimize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gulp-requirejs-optimize/-/gulp-requirejs-optimize-1.2.0.tgz", - "integrity": "sha1-cMPxWsF6y/Is4MUH6D1DQ2XKUws=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "gulp-util": "3.0.8", - "lodash.defaults": "4.2.0", - "requirejs": "2.3.5", - "through2": "2.0.3", - "vinyl-sourcemaps-apply": "0.2.1" - }, - "dependencies": { - "lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", - "dev": true - }, - "vinyl-sourcemaps-apply": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", - "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", - "dev": true, - "requires": { - "source-map": "0.5.7" - } - } - } - }, - "gulp-rtlcss": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gulp-rtlcss/-/gulp-rtlcss-1.2.0.tgz", - "integrity": "sha512-2JCyoR1EDRQadc/68DPlSLYDTsXdtwJEVyqMbmEa9DebHqFv8v8C2IbeU7Pr1+oUrUUGYkeoKcPu/cpkSFcb4g==", - "dev": true, - "requires": { - "plugin-error": "0.1.2", - "rtlcss": "2.2.1", - "through2": "2.0.3", - "vinyl-sourcemaps-apply": "0.2.1" - }, - "dependencies": { - "arr-diff": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", - "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", - "dev": true, - "requires": { - "arr-flatten": "1.1.0", - "array-slice": "0.2.3" - } - }, - "arr-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", - "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", - "dev": true - }, - "array-slice": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", - "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", - "dev": true - }, - "extend-shallow": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", - "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", - "dev": true, - "requires": { - "kind-of": "1.1.0" - } - }, - "kind-of": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", - "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", - "dev": true - }, - "plugin-error": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", - "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", - "dev": true, - "requires": { - "ansi-cyan": "0.1.1", - "ansi-red": "0.1.1", - "arr-diff": "1.1.0", - "arr-union": "2.1.0", - "extend-shallow": "1.1.4" - } - } - } - }, - "gulp-sass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/gulp-sass/-/gulp-sass-4.0.1.tgz", - "integrity": "sha512-OMQEgWNggpog8Tc5v1MuI6eo+5iiPkVeLL76iBhDoEEScLUPfZlpvzmgTnLkpcqdrNodZxpz5qcv6mS2rulk3g==", - "dev": true, - "requires": { - "chalk": "2.4.1", - "lodash.clonedeep": "4.5.0", - "node-sass": "4.9.0", - "plugin-error": "1.0.1", - "replace-ext": "1.0.0", - "strip-ansi": "4.0.0", - "through2": "2.0.3", - "vinyl-sourcemaps-apply": "0.2.1" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" - } - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "3.0.0" - } - } - } - }, - "gulp-sort": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/gulp-sort/-/gulp-sort-2.0.0.tgz", - "integrity": "sha1-xnYqLx8N4KP8WVohWZ0/rI26Gso=", - "dev": true, - "requires": { - "through2": "2.0.3" - } - }, - "gulp-sourcemaps": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", - "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=", - "dev": true, - "requires": { - "@gulp-sourcemaps/identity-map": "1.0.1", - "@gulp-sourcemaps/map-sources": "1.0.0", - "acorn": "5.4.0", - "convert-source-map": "1.5.1", - "css": "2.2.1", - "debug-fabulous": "1.0.0", - "detect-newline": "2.1.0", - "graceful-fs": "4.1.11", - "source-map": "0.6.1", - "strip-bom-string": "1.0.0", - "through2": "2.0.3" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "gulp-uglify": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-1.5.4.tgz", - "integrity": "sha1-UkeI2HZm0J+dDCH7IXf5ADmmWMk=", - "dev": true, - "requires": { - "deap": "1.0.1", - "fancy-log": "1.3.2", - "gulp-util": "3.0.8", - "isobject": "2.1.0", - "through2": "2.0.3", - "uglify-js": "2.6.4", - "uglify-save-license": "0.4.1", - "vinyl-sourcemaps-apply": "0.2.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - }, - "vinyl-sourcemaps-apply": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", - "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", - "dev": true, - "requires": { - "source-map": "0.5.7" - } - } - } - }, - "gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "dev": true, - "requires": { - "array-differ": "1.0.0", - "array-uniq": "1.0.3", - "beeper": "1.1.1", - "chalk": "1.1.3", - "dateformat": "2.2.0", - "fancy-log": "1.3.2", - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash._reescape": "3.0.0", - "lodash._reevaluate": "3.0.0", - "lodash._reinterpolate": "3.0.0", - "lodash.template": "3.6.2", - "minimist": "1.2.0", - "multipipe": "0.1.2", - "object-assign": "3.0.0", - "replace-ext": "0.0.1", - "through2": "2.0.3", - "vinyl": "0.5.3" - } - }, - "gulp-vinyl-zip": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/gulp-vinyl-zip/-/gulp-vinyl-zip-2.1.0.tgz", - "integrity": "sha1-JOQGhdwFtxSZlSRQmeBZAmO+ja0=", - "dev": true, - "requires": { - "event-stream": "3.3.4", - "queue": "4.4.2", - "through2": "2.0.3", - "vinyl": "2.1.0", - "vinyl-fs": "2.4.4", - "yauzl": "2.9.1", - "yazl": "2.4.3" - }, - "dependencies": { - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "1.1.0" - } - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" - } - }, - "clone": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", - "dev": true - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "event-stream": { - "version": "3.3.4", - "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", - "dev": true, - "requires": { - "duplexer": "0.1.1", - "from": "0.1.7", - "map-stream": "0.1.0", - "pause-stream": "0.0.11", - "split": "0.3.3", - "stream-combiner": "0.0.4", - "through": "2.3.8" - } - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "0.1.1" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "2.0.10", - "once": "1.3.3", - "path-is-absolute": "1.0.1" - } - }, - "glob-stream": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", - "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", - "dev": true, - "requires": { - "extend": "3.0.1", - "glob": "5.0.15", - "glob-parent": "3.1.0", - "micromatch": "2.3.11", - "ordered-read-streams": "0.3.0", - "through2": "0.6.5", - "to-absolute-glob": "0.1.1", - "unique-stream": "2.2.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - } - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "gulp-sourcemaps": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", - "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", - "dev": true, - "requires": { - "convert-source-map": "1.5.1", - "graceful-fs": "4.1.11", - "strip-bom": "2.0.0", - "through2": "2.0.3", - "vinyl": "1.2.0" - }, - "dependencies": { - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "1.0.4", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - } - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.4" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "ordered-read-streams": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", - "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", - "dev": true, - "requires": { - "is-stream": "1.1.0", - "readable-stream": "2.3.6" - } - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" - } - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", - "dev": true, - "requires": { - "through": "2.3.8" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } - }, - "unique-stream": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", - "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", - "dev": true, - "requires": { - "json-stable-stringify": "1.0.1", - "through2-filter": "2.0.0" - } - }, - "vinyl": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", - "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", - "dev": true, - "requires": { - "clone": "2.1.1", - "clone-buffer": "1.0.0", - "clone-stats": "1.0.0", - "cloneable-readable": "1.1.2", - "remove-trailing-separator": "1.1.0", - "replace-ext": "1.0.0" - } - }, - "vinyl-fs": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", - "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", - "dev": true, - "requires": { - "duplexify": "3.5.4", - "glob-stream": "5.3.5", - "graceful-fs": "4.1.11", - "gulp-sourcemaps": "1.6.0", - "is-valid-glob": "0.3.0", - "lazystream": "1.0.0", - "lodash.isequal": "4.5.0", - "merge-stream": "1.0.1", - "mkdirp": "0.5.1", - "object-assign": "4.1.1", - "readable-stream": "2.3.6", - "strip-bom": "2.0.0", - "strip-bom-stream": "1.0.0", - "through2": "2.0.3", - "through2-filter": "2.0.0", - "vali-date": "1.0.0", - "vinyl": "1.2.0" - }, - "dependencies": { - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "1.0.4", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - } - } - } - } - }, - "gulp-wp-pot": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-wp-pot/-/gulp-wp-pot-2.3.0.tgz", - "integrity": "sha512-GscMtG1MOcKezqdmolPO5Did0a1F1v87P6PVvULocghlM5w12fpfd5VKVVoMd4/P7uQBQ5y30xfSGeormmOzFQ==", - "dev": true, - "requires": { - "plugin-error": "1.0.1", - "through2": "2.0.3", - "vinyl": "2.1.0", - "wp-pot": "1.6.0" - }, - "dependencies": { - "clone": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", - "dev": true - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "vinyl": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", - "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", - "dev": true, - "requires": { - "clone": "2.1.1", - "clone-buffer": "1.0.0", - "clone-stats": "1.0.0", - "cloneable-readable": "1.1.2", - "remove-trailing-separator": "1.1.0", - "replace-ext": "1.0.0" - } - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "1.0.1" - } - }, - "har-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "commander": "2.15.1", - "is-my-json-valid": "2.17.2", - "pinkie-promise": "2.0.1" - }, - "dependencies": { - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - } - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-glob/-/has-glob-1.0.0.tgz", - "integrity": "sha1-mqqe7b/7G6OZCnsAEPtnjuAIEgc=", - "dev": true, - "requires": { - "is-glob": "3.1.0" - } - }, - "has-gulplog": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true, - "requires": { - "sparkles": "1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "2.0.6", - "has-values": "1.0.0", - "isobject": "3.0.1" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "dev": true, - "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" - } - }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true - }, - "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true, - "requires": { - "parse-passwd": "1.0.0" - } - }, - "hosted-git-info": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", - "dev": true - }, - "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "dev": true, - "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.1", - "sshpk": "1.14.1" - } - }, - "in-publish": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", - "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=", - "dev": true - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "2.0.1" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "1.3.3", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true - }, - "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", - "dev": true - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz", - "integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU=", - "dev": true - }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "requires": { - "is-relative": "1.0.0", - "is-windows": "1.0.2" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, - "requires": { - "builtin-modules": "1.1.1" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" - } - }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, - "requires": { - "is-primitive": "2.0.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "2.1.1" - } - }, - "is-my-ip-valid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", - "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", - "dev": true - }, - "is-my-json-valid": { - "version": "2.17.2", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", - "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", - "dev": true, - "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "is-my-ip-valid": "1.0.0", - "jsonpointer": "4.0.1", - "xtend": "4.0.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-odd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", - "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", - "dev": true, - "requires": { - "is-number": "4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "3.0.1" - } - }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true - }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "requires": { - "is-unc-path": "1.0.0" - } - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "requires": { - "unc-path-regex": "0.1.2" - } - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-valid-glob": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", - "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "istextorbinary": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-1.0.2.tgz", - "integrity": "sha1-rOGTVNGpoBc+/rEITOD4ewrX3s8=", - "dev": true, - "requires": { - "binaryextensions": "1.0.1", - "textextensions": "1.0.2" - } - }, - "js-base64": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.3.tgz", - "integrity": "sha512-H7ErYLM34CvDMto3GbD6xD0JLUGYXR3QTcH6B/tr4Hi/QpSThnCsIp+Sy5FRTw3B0d6py4HcNkW7nO/wdtGWEw==", - "dev": true - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "0.0.0" - } - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true, - "optional": true - } - } - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true, - "optional": true - } - } - }, - "lazy-cache": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", - "integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=", - "dev": true, - "requires": { - "set-getter": "0.1.0" - } - }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "2.3.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "1.0.0" - } - }, - "lifterlms-lib-tasks": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/lifterlms-lib-tasks/-/lifterlms-lib-tasks-1.10.0.tgz", - "integrity": "sha512-vUSAaVDRWtE+U0JETNZGfSRz6GT+IXM3qbAh9ZlQI8yAK/pVZ0Ds8Kh7qo3zlXe1puzBGJwVXHOnYywh6vo8eQ==", - "dev": true, - "requires": { - "gulp-autoprefixer": "5.0.0", - "gulp-checktextdomain": "2.1.1", - "gulp-composer": "0.4.5", - "gulp-include": "2.3.1", - "gulp-rename": "1.2.2", - "gulp-replace": "0.6.1", - "gulp-rtlcss": "1.2.0", - "gulp-sass": "4.0.1", - "gulp-sort": "2.0.0", - "gulp-sourcemaps": "2.6.4", - "gulp-uglify": "3.0.0", - "gulp-vinyl-zip": "2.1.0", - "gulp-wp-pot": "2.3.0", - "markdown-html": "github:gocodebox/markdown-html#6e523690a9d1dbfba75cab01c96b7c12871cbb83", - "merge": "1.2.0", - "node-version-compare": "1.0.1", - "pump": "1.0.3", - "yargs": "8.0.2" - }, - "dependencies": { - "ansi-regex": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", - "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", - "dev": true - }, - "ansi-styles": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", - "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", - "dev": true - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "chalk": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", - "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", - "dev": true, - "requires": { - "ansi-styles": "1.1.0", - "escape-string-regexp": "1.0.5", - "has-ansi": "0.1.0", - "strip-ansi": "0.3.0", - "supports-color": "0.2.0" - } - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - } - } - }, - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "dateformat": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true, - "requires": { - "get-stdin": "4.0.1", - "meow": "3.7.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "2.0.0" - } - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "2.0.10", - "once": "1.3.3", - "path-is-absolute": "1.0.1" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "gulp-include": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/gulp-include/-/gulp-include-2.3.1.tgz", - "integrity": "sha1-8eDtPw/QdMNHx+WfnPA409vbPjA=", - "dev": true, - "requires": { - "event-stream": "3.1.7", - "glob": "5.0.15", - "gulp-util": "2.2.20", - "source-map": "0.5.7", - "strip-bom": "2.0.0", - "vinyl-sourcemaps-apply": "0.2.1" - } - }, - "gulp-replace": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-0.6.1.tgz", - "integrity": "sha1-Eb+Mj85TPjPi9qjy9DC5VboL4GY=", - "dev": true, - "requires": { - "istextorbinary": "1.0.2", - "readable-stream": "2.3.6", - "replacestream": "4.0.3" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "gulp-uglify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.0.tgz", - "integrity": "sha1-DfAzHXKg0wLj434QlIXd3zPG0co=", - "dev": true, - "requires": { - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash": "4.17.10", - "make-error-cause": "1.2.2", - "through2": "2.0.3", - "uglify-js": "3.3.23", - "vinyl-sourcemaps-apply": "0.2.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "2.3.6", - "xtend": "4.0.1" - } - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - } - } - }, - "gulp-util": { - "version": "2.2.20", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", - "integrity": "sha1-1xRuVyiRC9jwR6awseVJvCLb1kw=", - "dev": true, - "requires": { - "chalk": "0.5.1", - "dateformat": "1.0.12", - "lodash._reinterpolate": "2.4.1", - "lodash.template": "2.4.1", - "minimist": "0.2.0", - "multipipe": "0.1.2", - "through2": "0.5.1", - "vinyl": "0.2.3" - } - }, - "has-ansi": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", - "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", - "dev": true, - "requires": { - "ansi-regex": "0.2.1" - } - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "strip-bom": "3.0.0" - }, - "dependencies": { - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } - } - }, - "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", - "dev": true - }, - "lodash._reinterpolate": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", - "integrity": "sha1-TxInqlqHEfxjL1sHofRgequLMiI=", - "dev": true - }, - "lodash.escape": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", - "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", - "dev": true, - "requires": { - "lodash._escapehtmlchar": "2.4.1", - "lodash._reunescapedhtml": "2.4.1", - "lodash.keys": "2.4.1" - } - }, - "lodash.keys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "2.4.1", - "lodash._shimkeys": "2.4.1", - "lodash.isobject": "2.4.1" - } - }, - "lodash.template": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", - "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", - "dev": true, - "requires": { - "lodash._escapestringchar": "2.4.1", - "lodash._reinterpolate": "2.4.1", - "lodash.defaults": "2.4.1", - "lodash.escape": "2.4.1", - "lodash.keys": "2.4.1", - "lodash.templatesettings": "2.4.1", - "lodash.values": "2.4.1" - } - }, - "lodash.templatesettings": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", - "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", - "dev": true, - "requires": { - "lodash._reinterpolate": "2.4.1", - "lodash.escape": "2.4.1" - } - }, - "minimist": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", - "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=", - "dev": true - }, - "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "0.7.0", - "lcid": "1.0.0", - "mem": "1.1.0" - } - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "2.3.0" - } - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "2.0.0", - "normalize-package-data": "2.4.0", - "path-type": "2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "2.1.0", - "read-pkg": "2.0.0" - } - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - } - } - }, - "strip-ansi": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", - "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", - "dev": true, - "requires": { - "ansi-regex": "0.2.1" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } - }, - "supports-color": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", - "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", - "dev": true - }, - "through2": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", - "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "3.0.0" - } - }, - "uglify-js": { - "version": "3.3.23", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.23.tgz", - "integrity": "sha512-Ks+KqLGDsYn4z+pU7JsKCzC0T3mPYl+rU+VcPZiQOazjE4Uqi4UCRY3qPMDbJi7ze37n1lDXj3biz1ik93vqvw==", - "dev": true, - "requires": { - "commander": "2.15.1", - "source-map": "0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "vinyl": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", - "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", - "dev": true, - "requires": { - "clone-stats": "0.0.1" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "xtend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", - "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", - "dev": true - }, - "yargs": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", - "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", - "dev": true, - "requires": { - "camelcase": "4.1.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "os-locale": "2.1.0", - "read-pkg-up": "2.0.0", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "3.2.1", - "yargs-parser": "7.0.0" - } - }, - "yargs-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", - "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", - "dev": true, - "requires": { - "camelcase": "4.1.0" - } - } - } - }, - "liftoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", - "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", - "dev": true, - "requires": { - "extend": "3.0.1", - "findup-sync": "2.0.0", - "fined": "1.1.0", - "flagged-respawn": "1.0.0", - "is-plain-object": "2.0.4", - "object.map": "1.0.1", - "rechoir": "0.6.2", - "resolve": "1.7.1" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } - } - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "2.0.0", - "path-exists": "3.0.0" - }, - "dependencies": { - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - } - } - }, - "lodash": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", - "dev": true - }, - "lodash._arraycopy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz", - "integrity": "sha1-due3wfH7klRzdIeKVi7Qaj5Q9uE=", - "dev": true - }, - "lodash._arrayeach": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz", - "integrity": "sha1-urFWsqkNPxu9XGU0AzSeXlkz754=", - "dev": true - }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true, - "requires": { - "lodash._basecopy": "3.0.1", - "lodash.keys": "3.1.2" - } - }, - "lodash._baseclone": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz", - "integrity": "sha1-MDUZv2OT/n5C802LYw73eU41Qrc=", - "dev": true, - "requires": { - "lodash._arraycopy": "3.0.0", - "lodash._arrayeach": "3.0.0", - "lodash._baseassign": "3.2.0", - "lodash._basefor": "3.0.3", - "lodash.isarray": "3.0.4", - "lodash.keys": "3.1.2" - } - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basefor": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz", - "integrity": "sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI=", - "dev": true - }, - "lodash._basetostring": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", - "dev": true - }, - "lodash._basevalues": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", - "dev": true - }, - "lodash._bindcallback": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", - "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", - "dev": true - }, - "lodash._escapehtmlchar": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", - "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=", - "dev": true, - "requires": { - "lodash._htmlescapes": "2.4.1" - } - }, - "lodash._escapestringchar": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz", - "integrity": "sha1-7P4iYYoq3lC/7qQ5N+Ud9m8O23I=", - "dev": true - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "lodash._htmlescapes": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", - "integrity": "sha1-MtFL8IRLbeb4tioFG09nwii2JMs=", - "dev": true - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "lodash._isnative": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", - "integrity": "sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=", - "dev": true - }, - "lodash._objecttypes": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", - "integrity": "sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=", - "dev": true - }, - "lodash._reescape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", - "dev": true - }, - "lodash._reevaluate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", - "dev": true - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "lodash._reunescapedhtml": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", - "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", - "dev": true, - "requires": { - "lodash._htmlescapes": "2.4.1", - "lodash.keys": "2.4.1" - }, - "dependencies": { - "lodash.keys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "2.4.1", - "lodash._shimkeys": "2.4.1", - "lodash.isobject": "2.4.1" - } - } - } - }, - "lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", - "dev": true - }, - "lodash._shimkeys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", - "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", - "dev": true, - "requires": { - "lodash._objecttypes": "2.4.1" - } - }, - "lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", - "dev": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "lodash.defaults": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", - "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", - "dev": true, - "requires": { - "lodash._objecttypes": "2.4.1", - "lodash.keys": "2.4.1" - }, - "dependencies": { - "lodash.keys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "2.4.1", - "lodash._shimkeys": "2.4.1", - "lodash.isobject": "2.4.1" - } - } - } - }, - "lodash.escape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true, - "requires": { - "lodash._root": "3.0.1" - } - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", - "dev": true - }, - "lodash.isobject": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", - "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", - "dev": true, - "requires": { - "lodash._objecttypes": "2.4.1" - } - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" - } - }, - "lodash.mergewith": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", - "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==", - "dev": true - }, - "lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", - "dev": true - }, - "lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true, - "requires": { - "lodash._basecopy": "3.0.1", - "lodash._basetostring": "3.0.1", - "lodash._basevalues": "3.0.0", - "lodash._isiterateecall": "3.0.9", - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0", - "lodash.keys": "3.1.2", - "lodash.restparam": "3.6.1", - "lodash.templatesettings": "3.1.1" - } - }, - "lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true, - "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0" - } - }, - "lodash.toarray": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", - "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=", - "dev": true - }, - "lodash.values": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz", - "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", - "dev": true, - "requires": { - "lodash.keys": "2.4.1" - }, - "dependencies": { - "lodash.keys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "2.4.1", - "lodash._shimkeys": "2.4.1", - "lodash.isobject": "2.4.1" - } - } - } - }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "0.4.1", - "signal-exit": "3.0.2" - } - }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, - "lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", - "dev": true, - "requires": { - "es5-ext": "0.10.38" - } - }, - "make-error": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", - "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==", - "dev": true - }, - "make-error-cause": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", - "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", - "dev": true, - "requires": { - "make-error": "1.3.4" - } - }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, - "map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "1.0.1" - } - }, - "markdown-html": { - "version": "github:gocodebox/markdown-html#6e523690a9d1dbfba75cab01c96b7c12871cbb83", - "dev": true, - "requires": { - "marked": "0.3.12", - "mu2": "0.5.21", - "optimist": "0.3.7" - } - }, - "marked": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.12.tgz", - "integrity": "sha512-k4NaW+vS7ytQn6MgJn3fYpQt20/mOgYM5Ft9BYMfQJDz2QT6yEeS9XJ8k2Nw8JTeWK/znPPW2n3UJGzyYEiMoA==", - "dev": true - }, - "marked-terminal": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-2.0.0.tgz", - "integrity": "sha1-Xq9Wi+ZvaGVBr6UqVYKAMQox3i0=", - "dev": true, - "requires": { - "cardinal": "1.0.0", - "chalk": "1.1.3", - "cli-table": "0.3.1", - "lodash.assign": "4.2.0", - "node-emoji": "1.8.1" - }, - "dependencies": { - "lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", - "dev": true - } - } - }, - "matched": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/matched/-/matched-2.0.1.tgz", - "integrity": "sha512-2aidSwg5/8qzUSFx2HuU3tIwY0yyRKA126l67CWIBHhXZlCvA8jjD7C7DqvuTJNzNbbmK/ETRFx3aNEgOFjuzA==", - "dev": true, - "requires": { - "arr-union": "3.1.0", - "glob": "7.1.2", - "has-glob": "1.0.0", - "is-valid-glob": "1.0.0", - "resolve-dir": "1.0.1" - }, - "dependencies": { - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.3.3", - "path-is-absolute": "1.0.1" - } - }, - "is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "1.1.8" - } - } - } - }, - "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true, - "requires": { - "mimic-fn": "1.2.0" - } - }, - "memoizee": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.11.tgz", - "integrity": "sha1-vemBdmPJ5A/bKk6hw2cpYIeujI8=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.38", - "es6-weak-map": "2.0.2", - "event-emitter": "0.3.5", - "is-promise": "2.1.0", - "lru-queue": "0.1.0", - "next-tick": "1.0.0", - "timers-ext": "0.1.2" - } - }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "requires": { - "camelcase-keys": "2.1.0", - "decamelize": "1.2.0", - "loud-rejection": "1.6.0", - "map-obj": "1.0.1", - "minimist": "1.2.0", - "normalize-package-data": "2.4.0", - "object-assign": "4.1.1", - "read-pkg-up": "1.0.1", - "redent": "1.0.0", - "trim-newlines": "1.0.0" - }, - "dependencies": { - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - } - } - }, - "merge": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz", - "integrity": "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo=", - "dev": true - }, - "merge-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "requires": { - "readable-stream": "2.3.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "braces": "2.3.2", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "extglob": "2.0.4", - "fragment-cache": "0.2.1", - "kind-of": "6.0.2", - "nanomatch": "1.2.9", - "object.pick": "1.3.0", - "regex-not": "1.0.0", - "snapdragon": "0.8.1", - "to-regex": "3.0.2" - }, - "dependencies": { - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "1.0.2", - "isobject": "3.0.1" - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "1.0.0", - "is-extendable": "1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "2.0.4" - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "regex-not": "1.0.2", - "safe-regex": "1.1.0" - }, - "dependencies": { - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "3.0.2", - "safe-regex": "1.1.0" - } - } - } - } - } - }, - "mime-db": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", - "dev": true - }, - "mime-types": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", - "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", - "dev": true, - "requires": { - "mime-db": "1.33.0" - } - }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - }, - "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "dev": true, - "requires": { - "brace-expansion": "1.1.8" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "mixin-deep": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.0.tgz", - "integrity": "sha512-dgaCvoh6i1nosAUBKb0l0pfJ78K8+S9fluyIR2YvAeUD/QuMahnFnF3xYty5eYXMjhGSsB0DsW6A0uAZyetoAg==", - "dev": true, - "requires": { - "for-in": "1.0.2", - "is-extendable": "1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - } - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "mu2": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/mu2/-/mu2-0.5.21.tgz", - "integrity": "sha1-iIqPD9kOsc/anbgUdvbhmcyeWNM=", - "dev": true - }, - "multipipe": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "dev": true, - "requires": { - "duplexer2": "0.0.2" - } - }, - "nan": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", - "dev": true - }, - "nanomatch": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", - "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", - "dev": true, - "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "fragment-cache": "0.2.1", - "is-odd": "2.0.0", - "is-windows": "1.0.2", - "kind-of": "6.0.2", - "object.pick": "1.3.0", - "regex-not": "1.0.0", - "snapdragon": "0.8.1", - "to-regex": "3.0.1" - }, - "dependencies": { - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "1.0.2", - "isobject": "3.0.1" - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "1.0.0", - "is-extendable": "1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "2.0.4" - } - } - } - }, - "natives": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.3.tgz", - "integrity": "sha512-BZGSYV4YOLxzoTK73l0/s/0sH9l8SHs2ocReMH1f8JYSh5FUWu4ZrKCpJdRkWXV6HFR/pZDz7bwWOVAY07q77g==", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node-emoji": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.8.1.tgz", - "integrity": "sha512-+ktMAh1Jwas+TnGodfCfjUbJKoANqPaJFN0z0iqh41eqD8dvguNzcitVSBSVK1pidz0AqGbLKcoVuVLRVZ/aVg==", - "dev": true, - "requires": { - "lodash.toarray": "4.4.0" - } - }, - "node-gyp": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz", - "integrity": "sha1-m/vlRWIoYoSDjnUOrAUpWFP6HGA=", - "dev": true, - "requires": { - "fstream": "1.0.11", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "nopt": "3.0.6", - "npmlog": "4.1.2", - "osenv": "0.1.5", - "request": "2.79.0", - "rimraf": "2.6.2", - "semver": "5.3.0", - "tar": "2.2.1", - "which": "1.3.0" - }, - "dependencies": { - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.3.3", - "path-is-absolute": "1.0.1" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "1.1.8" - } - }, - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true - } - } - }, - "node-notifier": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-4.6.1.tgz", - "integrity": "sha1-BW0UJE89zBzq3+aK+c/wxUc6M/M=", - "dev": true, - "requires": { - "cli-usage": "0.1.7", - "growly": "1.3.0", - "lodash.clonedeep": "3.0.2", - "minimist": "1.2.0", - "semver": "5.5.0", - "shellwords": "0.1.1", - "which": "1.3.0" - }, - "dependencies": { - "lodash.clonedeep": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-3.0.2.tgz", - "integrity": "sha1-oKHkDYKl6on/WxR7hETtY9koJ9s=", - "dev": true, - "requires": { - "lodash._baseclone": "3.3.0", - "lodash._bindcallback": "3.0.1" - } - }, - "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", - "dev": true - } - } - }, - "node-sass": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.0.tgz", - "integrity": "sha512-QFHfrZl6lqRU3csypwviz2XLgGNOoWQbo2GOvtsfQqOfL4cy1BtWnhx/XUeAO9LT3ahBzSRXcEO6DdvAH9DzSg==", - "dev": true, - "requires": { - "async-foreach": "0.1.3", - "chalk": "1.1.3", - "cross-spawn": "3.0.1", - "gaze": "1.1.2", - "get-stdin": "4.0.1", - "glob": "7.1.2", - "in-publish": "2.0.0", - "lodash.assign": "4.2.0", - "lodash.clonedeep": "4.5.0", - "lodash.mergewith": "4.6.1", - "meow": "3.7.0", - "mkdirp": "0.5.1", - "nan": "2.10.0", - "node-gyp": "3.6.2", - "npmlog": "4.1.2", - "request": "2.79.0", - "sass-graph": "2.2.4", - "stdout-stream": "1.4.0", - "true-case-path": "1.0.2" - }, - "dependencies": { - "gaze": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz", - "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU=", - "dev": true, - "requires": { - "globule": "1.2.0" - } - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.3.3", - "path-is-absolute": "1.0.1" - } - }, - "globule": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.0.tgz", - "integrity": "sha1-HcScaCLdnoovoAuiopUAboZkvQk=", - "dev": true, - "requires": { - "glob": "7.1.2", - "lodash": "4.17.10", - "minimatch": "3.0.4" - } - }, - "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "1.1.8" - } - } - } - }, - "node-version-compare": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/node-version-compare/-/node-version-compare-1.0.1.tgz", - "integrity": "sha1-2Fv9IPCsreM1d/VmgscQnDTFUM0=", - "dev": true - }, - "node.extend": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.6.tgz", - "integrity": "sha1-p7iCyC1sk6SGOlUEvV3o7IYli5Y=", - "dev": true, - "requires": { - "is": "3.2.1" - } - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1.1.1" - } - }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "dev": true, - "requires": { - "hosted-git-info": "2.5.0", - "is-builtin-module": "1.0.0", - "semver": "4.3.6", - "validate-npm-package-license": "3.0.1" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "1.1.0" - } - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "2.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } - }, - "num2fraction": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", - "dev": true - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true - }, - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "0.1.1", - "define-property": "0.2.5", - "kind-of": "3.2.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "3.0.1" - } - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "1.0.1", - "array-slice": "1.1.0", - "for-own": "1.0.0", - "isobject": "3.0.1" - } - }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "requires": { - "for-own": "1.0.0", - "make-iterator": "1.0.1" - } - }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, - "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" - }, - "dependencies": { - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "1.0.2" - } - } - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "3.0.1" - } - }, - "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "optimist": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", - "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", - "dev": true, - "requires": { - "wordwrap": "0.0.2" - } - }, - "orchestrator": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", - "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", - "dev": true, - "requires": { - "end-of-stream": "0.1.5", - "sequencify": "0.0.7", - "stream-consume": "0.1.1" - } - }, - "ordered-read-streams": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "1.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-limit": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", - "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", - "dev": true, - "requires": { - "p-try": "1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "1.2.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "requires": { - "is-absolute": "1.0.0", - "map-cache": "0.2.2", - "path-root": "0.1.1" - } - }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, - "requires": { - "glob-base": "0.3.0", - "is-dotfile": "1.0.3", - "is-extglob": "1.0.0", - "is-glob": "2.0.1" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - } - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "1.3.1" - } - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "2.0.1" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "dev": true - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "0.1.2" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, - "path-sort": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/path-sort/-/path-sort-0.1.0.tgz", - "integrity": "sha1-ywF11Oy/paGP5nTMbXIL/hXguAU=", - "dev": true - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - } - } - }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true, - "requires": { - "through": "2.3.8" - } - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "php-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/php-parser/-/php-parser-2.2.0.tgz", - "integrity": "sha1-ZzhPClkz2770C+qwqzHQuMWC/4g=", - "dev": true - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "2.0.4" - } - }, - "plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", - "dev": true, - "requires": { - "ansi-colors": "1.1.0", - "arr-diff": "4.0.0", - "arr-union": "3.1.0", - "extend-shallow": "3.0.2" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "1.0.0", - "is-extendable": "1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "2.0.4" - } - } - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "postcss": { - "version": "6.0.22", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.22.tgz", - "integrity": "sha512-Toc9lLoUASwGqxBSJGTVcOQiDqjK+Z2XlWBg+IgYwQMY9vA2f7iMpXVc1GpPcfTSyM5lkxNo0oDwDRO+wm7XHA==", - "dev": true, - "requires": { - "chalk": "2.4.1", - "source-map": "0.6.1", - "supports-color": "5.4.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "3.0.0" - } - } - } - }, - "postcss-value-parser": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", - "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=", - "dev": true - }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "pump": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", - "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", - "dev": true, - "requires": { - "end-of-stream": "1.4.1", - "once": "1.3.3" - }, - "dependencies": { - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, - "requires": { - "once": "1.4.0" - }, - "dependencies": { - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - } - } - } - } - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "qs": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", - "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", - "dev": true - }, - "queue": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/queue/-/queue-4.4.2.tgz", - "integrity": "sha512-fSMRXbwhMwipcDZ08enW2vl+YDmAmhcNcr43sCJL8DIg+CFOsoRLG23ctxA+fwNk1w55SePSiS7oqQQSgQoVJQ==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "ramda": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.20.1.tgz", - "integrity": "sha1-yB6PteeLXv8iaTSe4ENBN7THRlE=", - "dev": true - }, - "randomatic": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", - "dev": true, - "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "1.1.0", - "normalize-package-data": "2.4.0", - "path-type": "1.1.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "1.1.2", - "read-pkg": "1.1.0" - } - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "1.7.1" - } - }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "2.1.0", - "strip-indent": "1.0.1" - } - }, - "redeyed": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-1.0.1.tgz", - "integrity": "sha1-6WwZO0DAgWsArshCaY5hGF5VSYo=", - "dev": true, - "requires": { - "esprima": "3.0.0" - }, - "dependencies": { - "esprima": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.0.0.tgz", - "integrity": "sha1-U88kes2ncxPlUcOqLnM0LT+099k=", - "dev": true - } - } - }, - "regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "dev": true, - "requires": { - "is-equal-shallow": "0.1.3" - } - }, - "regex-not": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.0.tgz", - "integrity": "sha1-Qvg+OXcWIt+CawKvF2Ul1qXxV/k=", - "dev": true, - "requires": { - "extend-shallow": "2.0.1" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "1.0.2" - } - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "replacestream": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-4.0.3.tgz", - "integrity": "sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA==", - "dev": true, - "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1", - "readable-stream": "2.3.3" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "request": { - "version": "2.79.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", - "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", - "dev": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.7.0", - "caseless": "0.11.0", - "combined-stream": "1.0.6", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "2.0.6", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.18", - "oauth-sign": "0.8.2", - "qs": "6.3.2", - "stringstream": "0.0.5", - "tough-cookie": "2.3.4", - "tunnel-agent": "0.4.3", - "uuid": "3.2.1" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "requirejs": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.5.tgz", - "integrity": "sha512-svnO+aNcR/an9Dpi44C7KSAy5fFGLtmPbaaCeQaklUz8BQhS64tWWIIlvEA5jrWICzlO/X9KSzSeXFnZdBu8nw==", - "dev": true - }, - "resolve": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", - "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", - "dev": true, - "requires": { - "path-parse": "1.0.5" - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "2.0.2", - "global-modules": "1.0.0" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "requires": { - "align-text": "0.1.4" - } - }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, - "requires": { - "glob": "7.1.2" - }, - "dependencies": { - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.3.3", - "path-is-absolute": "1.0.1" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "1.1.8" - } - } - } - }, - "rtlcss": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-2.2.1.tgz", - "integrity": "sha512-JjQ5DlrmwiItAjlmhoxrJq5ihgZcE0wMFxt7S17bIrt4Lw0WwKKFk+viRhvodB/0falyG/5fiO043ZDh6/aqTw==", - "dev": true, - "requires": { - "chalk": "2.4.1", - "findup": "0.1.5", - "mkdirp": "0.5.1", - "postcss": "6.0.22", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" - } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "3.0.0" - } - } - } - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "0.1.15" - } - }, - "sass-graph": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", - "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", - "dev": true, - "requires": { - "glob": "7.1.2", - "lodash": "4.17.10", - "scss-tokenizer": "0.2.3", - "yargs": "7.1.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" - } - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.3.3", - "path-is-absolute": "1.0.1" - } - }, - "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "1.1.8" - } - }, - "yargs": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", - "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", - "dev": true, - "requires": { - "camelcase": "3.0.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "os-locale": "1.4.0", - "read-pkg-up": "1.0.1", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "1.0.2", - "which-module": "1.0.0", - "y18n": "3.2.1", - "yargs-parser": "5.0.0" - } - }, - "yargs-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", - "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", - "dev": true, - "requires": { - "camelcase": "3.0.0" - } - } - } - }, - "scss-tokenizer": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", - "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", - "dev": true, - "requires": { - "js-base64": "2.4.3", - "source-map": "0.4.4" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": "1.0.1" - } - } - } - }, - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "dev": true - }, - "sequencify": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", - "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", - "dev": true - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-getter": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz", - "integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=", - "dev": true, - "requires": { - "to-object-path": "0.3.0" - } - }, - "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", - "dev": true, - "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "split-string": "3.1.0" - } - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "shelljs": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.2.6.tgz", - "integrity": "sha1-kEktcv/MgVmXa6umL7D2iE8MM3g=", - "dev": true - }, - "shellwords": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", - "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", - "dev": true - }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "snapdragon": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", - "integrity": "sha1-4StUh/re0+PeoKyR6UAL91tAE3A=", - "dev": true, - "requires": { - "base": "0.11.2", - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "map-cache": "0.2.2", - "source-map": "0.5.7", - "source-map-resolve": "0.5.1", - "use": "2.0.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "1.0.0", - "isobject": "3.0.1", - "snapdragon-util": "3.0.1" - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", - "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", - "dev": true, - "requires": { - "atob": "2.0.3", - "decode-uri-component": "0.2.0", - "resolve-url": "0.2.1", - "source-map-url": "0.4.0", - "urix": "0.1.0" - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "sparkles": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", - "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", - "dev": true - }, - "spdx-correct": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", - "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", - "dev": true, - "requires": { - "spdx-license-ids": "1.2.2" - } - }, - "spdx-expression-parse": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", - "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", - "dev": true - }, - "spdx-license-ids": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", - "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", - "dev": true - }, - "split": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz", - "integrity": "sha1-Zwl8YB1pfOE2j0GPBs0gHPBSGlc=", - "dev": true, - "requires": { - "through": "2.3.8" - } - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "3.0.2" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "1.0.0", - "is-extendable": "1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "2.0.4" - } - } - } - }, - "sshpk": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", - "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", - "dev": true, - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "0.2.5", - "object-copy": "0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "stdout-stream": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.0.tgz", - "integrity": "sha1-osfIWH5U2UJ+qe2zrD8s1SLfN4s=", - "dev": true, - "requires": { - "readable-stream": "2.3.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", - "dev": true, - "requires": { - "duplexer": "0.1.1" - } - }, - "stream-consume": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", - "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", - "dev": true - }, - "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "stringstream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-bom": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", - "dev": true, - "requires": { - "first-chunk-stream": "1.0.0", - "is-utf8": "0.2.1" - } - }, - "strip-bom-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", - "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", - "dev": true, - "requires": { - "first-chunk-stream": "1.0.0", - "strip-bom": "2.0.0" - }, - "dependencies": { - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } - } - } - }, - "strip-bom-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", - "dev": true - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "4.0.1" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "tar": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", - "dev": true, - "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "textextensions": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-1.0.2.tgz", - "integrity": "sha1-ZUhjk+4fK7A5pgy7oFsLaL2VAdI=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "2.3.3", - "xtend": "4.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "through2-filter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", - "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", - "dev": true, - "requires": { - "through2": "2.0.3", - "xtend": "4.0.1" - } - }, - "tildify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "dev": true, - "requires": { - "os-homedir": "1.0.2" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, - "timers-ext": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.2.tgz", - "integrity": "sha1-YcxHp2wavTGV8UUn+XjViulMUgQ=", - "dev": true, - "requires": { - "es5-ext": "0.10.38", - "next-tick": "1.0.0" - } - }, - "to-absolute-glob": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", - "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", - "dev": true, - "requires": { - "extend-shallow": "2.0.1" - } - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "to-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.1.tgz", - "integrity": "sha1-FTWL7kosg712N3uh3ASdDxiDeq4=", - "dev": true, - "requires": { - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "regex-not": "1.0.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "3.0.0", - "repeat-string": "1.6.1" - } - }, - "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", - "dev": true, - "requires": { - "punycode": "1.4.1" - } - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, - "true-case-path": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.2.tgz", - "integrity": "sha1-fskRMJJHZsf1c74wIMNPj9/QDWI=", - "dev": true, - "requires": { - "glob": "6.0.4" - }, - "dependencies": { - "glob": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "2.0.10", - "once": "1.3.3", - "path-is-absolute": "1.0.1" - } - } - } - }, - "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", - "dev": true - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, - "optional": true - }, - "uglify-js": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.6.4.tgz", - "integrity": "sha1-ZeovswWck5RpLxX+2HwrNsFrmt8=", - "dev": true, - "requires": { - "async": "0.2.10", - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" - }, - "dependencies": { - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", - "window-size": "0.1.0" - } - } - } - }, - "uglify-save-license": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/uglify-save-license/-/uglify-save-license-0.4.1.tgz", - "integrity": "sha1-lXJsF8xv0XHDYX479NjYKqjEzOE=", - "dev": true - }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true - }, - "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", - "dev": true, - "requires": { - "arr-union": "3.1.0", - "get-value": "2.0.6", - "is-extendable": "0.1.1", - "set-value": "0.4.3" - }, - "dependencies": { - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "to-object-path": "0.3.0" - } - } - } - }, - "unique-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", - "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", - "dev": true - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "0.3.1", - "isobject": "3.0.1" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "2.0.6", - "has-values": "0.1.4", - "isobject": "2.1.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "use": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/use/-/use-2.0.2.tgz", - "integrity": "sha1-riig1y+TvyJCKhii43mZMRLeyOg=", - "dev": true, - "requires": { - "define-property": "0.2.5", - "isobject": "3.0.1", - "lazy-cache": "2.0.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", - "dev": true - }, - "v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "dev": true, - "requires": { - "user-home": "1.1.1" - } - }, - "vali-date": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", - "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", - "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", - "dev": true, - "requires": { - "spdx-correct": "1.0.2", - "spdx-expression-parse": "1.0.4" - } - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "1.3.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - }, - "vinyl-fs": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", - "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", - "dev": true, - "requires": { - "defaults": "1.0.3", - "glob-stream": "3.1.18", - "glob-watcher": "0.0.6", - "graceful-fs": "3.0.11", - "mkdirp": "0.5.1", - "strip-bom": "1.0.0", - "through2": "0.6.5", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - } - } - }, - "vinyl-sourcemaps-apply": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", - "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", - "dev": true, - "requires": { - "source-map": "0.5.7" - } - }, - "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", - "dev": true, - "requires": { - "isexe": "2.0.0" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "wide-align": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", - "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", - "dev": true, - "requires": { - "string-width": "1.0.2" - } - }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true - }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - }, - "wp-pot": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/wp-pot/-/wp-pot-1.6.0.tgz", - "integrity": "sha512-bdB6gq6ORKtqhQ/eNnv6oRxS5KZMycFbmKmHXuOrViCUN4P9KFhwvBisr0zwltY6SrPMWipf4Wi89nWpXcba/A==", - "dev": true, - "requires": { - "matched": "2.0.1", - "path-sort": "0.1.0", - "php-parser": "3.0.0-alpha2" - }, - "dependencies": { - "php-parser": { - "version": "3.0.0-alpha2", - "resolved": "https://registry.npmjs.org/php-parser/-/php-parser-3.0.0-alpha2.tgz", - "integrity": "sha1-bcORysgJ5UFzjxxz9uy52ECjiEA=", - "dev": true - } - } - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "yargs": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", - "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", - "dev": true, - "requires": { - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "lodash.assign": "4.2.0", - "os-locale": "1.4.0", - "read-pkg-up": "1.0.1", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "1.0.2", - "which-module": "1.0.0", - "window-size": "0.2.0", - "y18n": "3.2.1", - "yargs-parser": "2.4.1" - }, - "dependencies": { - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" - } - }, - "lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", - "dev": true - }, - "window-size": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", - "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", - "dev": true - } - } - }, - "yargs-parser": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", - "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", - "dev": true, - "requires": { - "camelcase": "3.0.0", - "lodash.assign": "4.2.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", - "dev": true - } - } - }, - "yauzl": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz", - "integrity": "sha1-qBmB6nCleUYTOIPwKcWCGok1mn8=", - "dev": true, - "requires": { - "buffer-crc32": "0.2.13", - "fd-slicer": "1.0.1" - } - }, - "yazl": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.4.3.tgz", - "integrity": "sha1-7CblzIfVYBud+EMtvdPNLlFzoHE=", - "dev": true, - "requires": { - "buffer-crc32": "0.2.13" - } - } - } -} diff --git a/package.json b/package.json deleted file mode 100644 index 21494f86e2..0000000000 --- a/package.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "lifterlms", - "version": "3.17.8", - "description": "LifterLMS by codeBOX", - "repository": { - "type": "git", - "url": "https://github.com/gocodebox/lifterlms.git" - }, - "author": "LifterLMS", - "license": "GPL-3.0", - "bugs": { - "url": "https://github.com/gocodebox/lifterlms/issues" - }, - "homepage": "https://lifterlms.com", - "devDependencies": { - "gulp": "^3.9.1", - "gulp-header": "^2.0.5", - "gulp-include": "^1.1.1", - "gulp-notify": "^2.2.0", - "gulp-rename": "^1.2.0", - "gulp-replace": "^0.5.4", - "gulp-requirejs-optimize": "^1.2.0", - "gulp-sourcemaps": "^2.6.1", - "gulp-uglify": "^1.5.4", - "lifterlms-lib-tasks": "^1.10.0", - "markdown-html": "gocodebox/markdown-html", - "yargs": "^4.1.0" - } -} diff --git a/phpcs.xml b/phpcs.xml deleted file mode 100644 index 9a21839d23..0000000000 --- a/phpcs.xml +++ /dev/null @@ -1,41 +0,0 @@ -<?xml version="1.0"?> -<ruleset name="LifterLMS"> - <description>LifterLMS Rules for PHP_CodeSniffer</description> - - <rule ref="Squiz.PHP.CommentedOutCode"/> - <rule ref="Squiz.WhiteSpace.SuperfluousWhitespace"/> - <rule ref="Generic.CodeAnalysis.UnusedFunctionParameter"/> - <rule ref="Generic.Commenting.Todo"/> - <rule ref="Generic.ControlStructures.InlineControlStructure"/> - - <!-- - Use all the Rules in the WordPress Core Standard - --> - <rule ref="WordPress-Core"> - - <!-- - @todo possibly remove this rule - removing this for now - this does not allow filenames with underscores - can't handle that today... - --> - <exclude name="WordPress.Files.FileName" /> - - <!-- - @todo definetly fix this, there's just soo many non yodas... - --> - <exclude name="WordPress.PHP.YodaConditions"/> - - <!-- - @todo fix this before too long... - --> - <exclude name="WordPress.Functions.DontExtract"/> - <exclude name="WordPress.WP.PreparedSQL"/> - - <!-- - @todo waiting on resolution for this bug report: https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/issues/719 - --> - <exclude name="WordPress.WP.I18n"/> - - </rule> -</ruleset> diff --git a/phpmd.xml b/phpmd.xml deleted file mode 100644 index b0a15a383e..0000000000 --- a/phpmd.xml +++ /dev/null @@ -1,52 +0,0 @@ -<?xml version="1.0"?> -<ruleset name="WordPress LifterLMS" - xmlns="http://pmd.sf.net/ruleset/1.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd" - xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd"> - <description>LifterLMS Standards</description> - - - <rule ref="rulesets/cleancode.xml"> - - <!-- used all over --> - <exclude name="BooleanArgumentFlag" /> - - <!-- in lack of real namespacing --> - <exclude name="StaticAccess" /> - - <!-- I disagree with this --> - <exclude name="ElseExpression" /> - - </rule> - - - <rule ref="rulesets/codesize.xml" /> - - <rule ref="rulesets/design.xml"> - - <!-- normal in WP for redirects, etc --> - <exclude name="ExitExpression" /> - - </rule> - - - <rule ref="rulesets/naming.xml/ShortVariable"> - <properties> - - <!-- common in WP --> - <property name="exceptions" value="id,wp" /> - - </properties> - </rule> - - - <rule ref="rulesets/naming.xml/LongVariable" /> - <rule ref="rulesets/naming.xml/ShortMethodName" /> - <rule ref="rulesets/naming.xml/ConstructorWithNameAsEnclosingClass" /> - <rule ref="rulesets/naming.xml/ConstantNamingConventions" /> - <rule ref="rulesets/naming.xml/BooleanGetMethodName" /> - - <rule ref="rulesets/unusedcode.xml" /> - -</ruleset> diff --git a/phpunit.xml b/phpunit.xml deleted file mode 100644 index fd7e130056..0000000000 --- a/phpunit.xml +++ /dev/null @@ -1,39 +0,0 @@ -<phpunit - bootstrap="tests/bootstrap.php" - backupGlobals="false" - colors="true" - convertErrorsToExceptions="true" - convertNoticesToExceptions="true" - convertWarningsToExceptions="true" - verbose="true" - syntaxCheck="true" - > - <testsuites> - <testsuite name="LifterLMS Test Suite"> - <directory suffix=".php">tests/unit-tests</directory> - </testsuite> - </testsuites> - <filter> - <whitelist addUncoveredFilesFromWhitelist="true"> - <directory suffix=".php">.</directory> - <exclude> - <directory suffix=".php">./templates/</directory> - <directory>./tests/</directory> - <directory suffix=".php">./tmp/</directory> - <directory suffix=".php">./deploy/</directory> - <directory suffix=".php">./dist/</directory> - <directory suffix=".php">./node_modules/</directory> - <directory suffix=".php">./vendor/</directory> - </exclude> - </whitelist> - </filter> - <listeners> - <listener - class="LLMS_Test_Time_Threshold_Listener" - file="tests/framework/class.llms.test.time.threshold.listner.php" - /> - </listeners> -<!-- <logging> - <log type="coverage-clover" target="build/logs/clover.xml"/> - </logging> --> -</phpunit> diff --git a/readme.txt b/readme.txt index 17f701755d..622ce90dcb 100644 --- a/readme.txt +++ b/readme.txt @@ -5,7 +5,7 @@ Tags: learning management system, LMS, membership, elearning, online courses, qu Requires at least: 4.0 Requires PHP: 5.6 Tested up to: 4.9.5 -Stable tag: 3.17.8 +Stable tag: 3.17.7 License: GPLv3 License URI: https://www.gnu.org/licenses/gpl-3.0.html diff --git a/tests/bin/install.sh b/tests/bin/install.sh deleted file mode 100755 index 42e677ce26..0000000000 --- a/tests/bin/install.sh +++ /dev/null @@ -1,128 +0,0 @@ -#!/usr/bin/env bash -# see https://github.com/wp-cli/wp-cli/blob/master/templates/install-wp-tests.sh - -if [ $# -lt 3 ]; then - echo "usage: $0 <db-name> <db-user> <db-pass> [db-host] [wp-version] [skip-database-creation]" - exit 1 -fi - -DB_NAME=$1 -DB_USER=$2 -DB_PASS=$3 -DB_HOST=${4-localhost} -WP_VERSION=${5-latest} -SKIP_DB_CREATE=${6-false} - -WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib} -WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/} - -download() { - if [ `which curl` ]; then - curl -s "$1" > "$2"; - elif [ `which wget` ]; then - wget -nv -O "$2" "$1" - fi -} - -if [[ $WP_VERSION =~ [0-9]+\.[0-9]+(\.[0-9]+)? ]]; then - WP_TESTS_TAG="tags/$WP_VERSION" -elif [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then - WP_TESTS_TAG="trunk" -else - # http serves a single offer, whereas https serves multiple. we only want one - download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json - grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json - LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//') - if [[ -z "$LATEST_VERSION" ]]; then - echo "Latest WordPress version could not be found" - exit 1 - fi - WP_TESTS_TAG="tags/$LATEST_VERSION" -fi - -set -ex - -install_wp() { - - if [ -d $WP_CORE_DIR ]; then - return; - fi - - mkdir -p $WP_CORE_DIR - - if [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then - mkdir -p /tmp/wordpress-nightly - download https://wordpress.org/nightly-builds/wordpress-latest.zip /tmp/wordpress-nightly/wordpress-nightly.zip - unzip -q /tmp/wordpress-nightly/wordpress-nightly.zip -d /tmp/wordpress-nightly/ - mv /tmp/wordpress-nightly/wordpress/* $WP_CORE_DIR - else - if [ $WP_VERSION == 'latest' ]; then - local ARCHIVE_NAME='latest' - else - local ARCHIVE_NAME="wordpress-$WP_VERSION" - fi - download https://wordpress.org/${ARCHIVE_NAME}.tar.gz /tmp/wordpress.tar.gz - tar --strip-components=1 -zxmf /tmp/wordpress.tar.gz -C $WP_CORE_DIR - fi - - download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php -} - -install_test_suite() { - # portable in-place argument for both GNU sed and Mac OSX sed - if [[ $(uname -s) == 'Darwin' ]]; then - local ioption='-i .bak' - else - local ioption='-i' - fi - - # set up testing suite if it doesn't yet exist - if [ ! -d $WP_TESTS_DIR ]; then - # set up testing suite - mkdir -p $WP_TESTS_DIR - svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes - svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/data/ $WP_TESTS_DIR/data - fi - - if [ ! -f wp-tests-config.php ]; then - download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php - # remove all forward slashes in the end - WP_CORE_DIR=$(echo $WP_CORE_DIR | sed "s:/\+$::") - sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR/':" "$WP_TESTS_DIR"/wp-tests-config.php - sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php - sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php - sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php - sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php - fi - -} - -install_db() { - - if [ ${SKIP_DB_CREATE} = "true" ]; then - return 0 - fi - - # parse DB_HOST for port or socket references - local PARTS=(${DB_HOST//\:/ }) - local DB_HOSTNAME=${PARTS[0]}; - local DB_SOCK_OR_PORT=${PARTS[1]}; - local EXTRA="" - - if ! [ -z $DB_HOSTNAME ] ; then - if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then - EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp" - elif ! [ -z $DB_SOCK_OR_PORT ] ; then - EXTRA=" --socket=$DB_SOCK_OR_PORT" - elif ! [ -z $DB_HOSTNAME ] ; then - EXTRA=" --host=$DB_HOSTNAME --protocol=tcp" - fi - fi - - # create database - mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA -} - -install_wp -install_test_suite -install_db diff --git a/tests/bin/teardown.sh b/tests/bin/teardown.sh deleted file mode 100755 index 71084bcddb..0000000000 --- a/tests/bin/teardown.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env bash - -if [ $# -lt 3 ]; then - echo "usage: $0 <db-name> <db-user> <db-pass> [db-host]" - exit 1 -fi - -DB_NAME=$1 -DB_USER=$2 -DB_PASS=$3 -DB_HOST=${4-localhost} - -WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib} -WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/} - -delete_db() { - - # parse DB_HOST for port or socket references - local PARTS=(${DB_HOST//\:/ }) - local DB_HOSTNAME=${PARTS[0]}; - local DB_SOCK_OR_PORT=${PARTS[1]}; - local EXTRA="" - - if ! [ -z $DB_HOSTNAME ] ; then - if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then - EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp" - elif ! [ -z $DB_SOCK_OR_PORT ] ; then - EXTRA=" --socket=$DB_SOCK_OR_PORT" - elif ! [ -z $DB_HOSTNAME ] ; then - EXTRA=" --host=$DB_HOSTNAME --protocol=tcp" - fi - fi - - # create database - mysqladmin drop -f $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA - -} - -delete_db - -rm -rf $WP_TESTS_DIR -rm -rf $WP_CORE_DIR diff --git a/tests/bin/travis.sh b/tests/bin/travis.sh deleted file mode 100755 index 5b2ae09911..0000000000 --- a/tests/bin/travis.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash -# usage: travis.sh before|after - -if [ $1 == 'before' ]; then - - composer self-update - composer install --no-interaction - -elif [ $1 == 'during' ]; then - - # ensure that we exit as soon as we encounter an error - set -e - - # lint - find -L . -path ./vendor -prune -o -name '*.php' -print0 | xargs -0 -n 1 -P 4 php -l; - - # phpcs - composer run-script phpcs - - # phpunit - ./vendor/bin/phpunit --coverage-clover build/logs/clover.xml - -fi diff --git a/tests/bootstrap.php b/tests/bootstrap.php deleted file mode 100644 index aca0bbf696..0000000000 --- a/tests/bootstrap.php +++ /dev/null @@ -1,146 +0,0 @@ -<?php -/** - * LifterLMS Unit Testing Bootstrap - * @since 3.3.1 - * @version 3.8.0 - * @thanks WooCommerce <3 - */ -class LLMS_Unit_Tests_Bootstrap { - - /** - * Singleton Instance of LLMS_Unit_Tests_Bootstrap - * @var obj - */ - protected static $instance = null; - - /** - * WP Tests Directory Path - * @var string - */ - public $wp_tests_dir; - - /** - * Tests Directory Path - * @var string - */ - public $tests_dir; - - /** - * Plugin Directory Path - * @var string - */ - public $plugin_dir; - - /** - * Get Singleton Class Instance - * @return LLMS_Unit_Tests_Bootstrap - * @since 3.3.1 - * @version 3.3.1 - */ - public static function instance() { - if ( is_null( self::$instance ) ) { - self::$instance = new self(); - } - return self::$instance; - } - - /** - * Constructor - * @since 3.3.1 - * @version 3.3.1 - */ - public function __construct() { - - echo 'Welcome to the LifterLMS Test Suite' . PHP_EOL . PHP_EOL . PHP_EOL; - - ini_set( 'display_errors','on' ); - error_reporting( E_ALL ); - - // Ensure server variable is set for WP email functions. - if ( ! isset( $_SERVER['SERVER_NAME'] ) ) { - $_SERVER['SERVER_NAME'] = 'localhost'; - } - - $this->tests_dir = dirname( __FILE__ ); - $this->plugin_dir = dirname( $this->tests_dir ); - $this->wp_tests_dir = getenv( 'WP_TESTS_DIR' ) ? getenv( 'WP_TESTS_DIR' ) : '/tmp/wordpress-tests-lib'; - - // load test function so tests_add_filter() is available - require_once $this->wp_tests_dir . '/includes/functions.php'; - - require_once 'tests/framework/llms.test.functions.php'; - - // load LLMS - tests_add_filter( 'muplugins_loaded', array( $this, 'load_llms' ) ); - - // install LLMS - tests_add_filter( 'setup_theme', array( $this, 'install_llms' ) ); - - // load the WP testing environment - require_once( $this->wp_tests_dir . '/includes/bootstrap.php' ); - - // load LLMS testing framework - $this->includes(); - } - - /** - * Load LifterLMS - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function load_llms() { - - // override this constant otherwise a bunch of includes will fail when running tests - define( 'LLMS_PLUGIN_DIR', trailingslashit( $this->plugin_dir ) ); - - require_once( $this->plugin_dir . '/lifterlms.php' ); - - } - - /** - * Install LifterLMS - * @return [type] [description] - * @since 3.3.1 - * @version 3.3.1 - */ - public function install_llms() { - - echo 'Installing LifterLMS...' . PHP_EOL; - - // Clean existing install first. - define( 'WP_UNINSTALL_PLUGIN', true ); - define( 'LLMS_REMOVE_ALL_DATA', true ); - include( $this->plugin_dir . '/uninstall.php' ); - - // install LLMS - LLMS_Install::install(); - - // Reload capabilities after install, see https://core.trac.wordpress.org/ticket/28374 - if ( version_compare( $GLOBALS['wp_version'], '4.7', '<' ) ) { - $GLOBALS['wp_roles']->reinit(); - } else { - $GLOBALS['wp_roles'] = null; - wp_roles(); - } - - - } - - /** - * Load LifterLMS Tests & Related - * @return void - * @since 3.3.1 - * @version 3.8.0 - */ - public function includes() { - - require 'tests/framework/class.llms.unit.test.case.php'; - require 'tests/framework/class.llms.notification.test.case.php'; - require 'tests/framework/class.llms.post.model.unit.test.case.php'; - - } - - -} -LLMS_Unit_Tests_Bootstrap::instance(); diff --git a/tests/framework/class.llms.notification.test.case.php b/tests/framework/class.llms.notification.test.case.php deleted file mode 100644 index e660618ba9..0000000000 --- a/tests/framework/class.llms.notification.test.case.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php -/** - * Unit Test Case with tests and utilities specific to testing LifterLMS Notification Classes - * @since 3.8.0 - * @version 3.8.0 - */ -class LLMS_NotificationTestCase extends LLMS_UnitTestCase { - - public function test_is_registered() { - - $main = LLMS()->notifications(); - - $controller = $main->get_controller( $this->notification_id ); - $this->assertTrue( is_a( $controller, 'LLMS_Abstract_Notification_Controller' ) ); - $this->assertEquals( $this->notification_id, $controller->id ); - - // $view = $main->get_view( $this->notification_id ); - // $this->assertTrue( is_a( $view, 'LLMS_Abstract_Notification_View' ) ); - // $this->assertEquals( $this->notification_id, $view->trigger_id ); - - } - -} diff --git a/tests/framework/class.llms.post.model.unit.test.case.php b/tests/framework/class.llms.post.model.unit.test.case.php deleted file mode 100644 index f9e1f2b69a..0000000000 --- a/tests/framework/class.llms.post.model.unit.test.case.php +++ /dev/null @@ -1,196 +0,0 @@ -<?php -/** - * Unit Test Case with tests and utilities specific to testing classes - * which extend the LLMS_Post_Model - * @since 3.4.0 - * @version 3.4.0 - */ -class LLMS_PostModelUnitTestCase extends LLMS_UnitTestCase { - - /** - * class name for the model being tested by the class - * @var string - */ - protected $class_name = ''; - - /** - * db post type of the model being tested - * @var string - */ - protected $post_type = ''; - - /** - * Get properties, used by test_getters_setters - * This should match, exactly, the object's $properties array - * @return array - * @since 3.4.0 - * @version 3.4.0 - */ - protected function get_properties() { - return array(); - } - - /** - * Get data to fill a create post with - * This is used by test_getters_setters - * @return array - * @since 3.4.0 - * @version 3.4.0 - */ - protected function get_data() { - return array(); - } - - /* - /$$ /$$ /$$ - | $$ |__/| $$ - /$$ /$$ /$$$$$$ /$$| $$ /$$$$$$$ - | $$ | $$|_ $$_/ | $$| $$ /$$_____/ - | $$ | $$ | $$ | $$| $$| $$$$$$ - | $$ | $$ | $$ /$$| $$| $$ \____ $$ - | $$$$$$/ | $$$$/| $$| $$ /$$$$$$$/ - \______/ \___/ |__/|__/|_______/ - */ - - /** - * Will hold an intance of the model being tested by the class - * @var obj - */ - protected $obj = null; - - - /** - * Create a post that can be tested - * @param string|array $args string for post title or array of arguments to use when creating the post - * @return void - * @since 3.4.0 - * @version 3.4.0 - */ - protected function create( $args = 'test title' ) { - - $this->obj = new $this->class_name( 'new', $args ); - - } - - /* - /$$ /$$ - | $$ | $$ - /$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$$ - |_ $$_/ /$$__ $$ /$$_____/|_ $$_/ /$$_____/ - | $$ | $$$$$$$$| $$$$$$ | $$ | $$$$$$ - | $$ /$$| $$_____/ \____ $$ | $$ /$$\____ $$ - | $$$$/| $$$$$$$ /$$$$$$$/ | $$$$//$$$$$$$/ - \___/ \_______/|_______/ \___/ |_______/ - */ - - /** - * Test creation of the model - * @return void - * @since 3.4.0 - * @version 3.4.0 - */ - public function test_create_model() { - - $this->create( 'test title' ); - - $id = $this->obj->get( 'id' ); - - $test = llms_get_post( $id ); - - $this->assertEquals( $id, $test->get( 'id' ) ); - $this->assertEquals( $this->post_type, $test->get( 'type' ) ); - $this->assertEquals( 'test title', $test->get( 'title' ) ); - - } - - /** - * Test getters and setters - * @return void - * @since 3.4.0 - * @version 3.4.0 - */ - public function test_getters_setters() { - - $this->create( 'test title' ); - $props = $this->get_properties(); - $data = $this->get_data(); - - foreach ( $props as $prop => $type ) { - - // set should return true - $this->assertTrue( $this->obj->set( $prop, $data[ $prop ] ) ); - - // make sure gotten value equals set val - $this->assertEquals( $data[ $prop ], $this->obj->get( $prop ) ); - - // check type - switch ( $type ) { - - case 'absint': - // should be numeric - $this->assertTrue( is_numeric( $this->obj->get( $prop ) ) ); - // strings should return 0 - $this->obj->set( $prop, 'string' ); - $this->assertEquals( 0, $this->obj->get( $prop ) ); - // floats should drop the decimal - $this->obj->set( $prop, 12.3 ); - $this->assertEquals( 12, $this->obj->get( $prop ) ); - // negative should return positive - $this->obj->set( $prop, -45 ); - $this->assertEquals( 45, $this->obj->get( $prop ) ); - // numeric strind should return int - $this->obj->set( $prop, '6' ); - $this->assertEquals( '6', $this->obj->get( $prop ) ); - break; - - case 'array': - // should be an array - $this->assertTrue( is_array( $this->obj->get( $prop ) ) ); - // strings should return an array with the string as the first item in the array - $this->obj->set( $prop, 'string' ); - $this->assertEquals( array( 'string'), $this->obj->get( $prop ) ); - break; - - case 'float': - // should be a float - $this->assertTrue( is_float( $this->obj->get( $prop ) ) ); - // string should return 0 - $this->obj->set( $prop, 'string' ); - $this->assertEquals( 0, $this->obj->get( $prop ) ); - // decimals shouldn't be lost - $this->obj->set( $prop, 123.456 ); - $this->assertEquals( 123.456, $this->obj->get( $prop ) ); - // whole numbers should still be whole numbers - $this->obj->set( $prop, 789 ); - $this->assertEquals( 789, $this->obj->get( $prop ) ); - // check super big numbers - $this->obj->set( $prop, 1234567.89 ); - $this->assertEquals( 1234567.89, $this->obj->get( $prop ) ); - break; - - case 'text': - $this->assertTrue( is_string( $this->obj->get( $prop ) ) ); - break; - - case 'yesno': - // yes returns yes - $this->obj->set( $prop, 'yes' ); - $this->assertEquals( 'yes', $this->obj->get( $prop ) ); - // no returns no - $this->obj->set( $prop, 'no' ); - $this->assertEquals( 'no', $this->obj->get( $prop ) ); - // anything else returns no - $this->obj->set( $prop, 'string' ); - $this->assertEquals( 'no', $this->obj->get( $prop ) ); - $this->obj->set( $prop, '' ); - $this->assertEquals( 'no', $this->obj->get( $prop ) ); - $this->obj->set( $prop, 123456 ); - $this->assertEquals( 'no', $this->obj->get( $prop ) ); - break; - - } - - } - } - -} diff --git a/tests/framework/class.llms.test.time.threshold.listner.php b/tests/framework/class.llms.test.time.threshold.listner.php deleted file mode 100644 index e6b0ed0027..0000000000 --- a/tests/framework/class.llms.test.time.threshold.listner.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php -/** - * Output warnings when tests take too long to run - * @source http://aaronsaray.com/2017/phpunit-listener-for-long-running-tests-update - * @since 3.17.4 - * @version 3.17.4 - */ -class LLMS_Test_Time_Threshold_Listener extends PHPUnit_Framework_BaseTestListener { - - public function startTestSuite( PHPUnit_Framework_TestSuite $suite ) { - llms_set_test_time_limit(); - } - - /** - * A test ended - print out if it was too long - * @param Test $test - * @param float $time seconds - */ - public function endTest( PHPUnit_Framework_Test $test, $time ) { - - global $llms_test_time_limit; - - if ( $time * 1000 > $llms_test_time_limit ) { - $error = sprintf( - '%s::%s ran for %s seconds', - get_class( $test ), - $test->getName(), - $time - ); - print "\n\033[41m" . $error . "\033[0m\n"; - } - - // reset the time limit in case a test has expanded the limit - llms_set_test_time_limit(); - - } - -} diff --git a/tests/framework/class.llms.unit.test.case.php b/tests/framework/class.llms.unit.test.case.php deleted file mode 100644 index 4878d910a7..0000000000 --- a/tests/framework/class.llms.unit.test.case.php +++ /dev/null @@ -1,213 +0,0 @@ -<?php -/** - * LifterLMS Unit Test Case Base clase - * @since 3.3.1 - * @version 3.17.2 - */ -class LLMS_UnitTestCase extends WP_UnitTestCase { - - /** - * Setup tests - * Automatically called before each test - * @return void - * @since 3.17.0 - * @version 3.17.0 - */ - public function setUp() { - parent::setUp(); - llms_reset_current_time(); - } - - /** - * Automatically complete a percentage of courses for a student - * @param integer $student_id WP User ID of a student - * @param array $course_ids array of WP Post IDs for the courses - * @param integer $perc percentage of each course complete - * percentage is based off the total number of lessons in the course - * fractions will be rounded up - * @return void - * @since 3.7.3 - * @version 3.17.2 - */ - protected function complete_courses_for_student( $student_id = 0, $course_ids = array(), $perc = 100 ) { - - $student = new LLMS_Student( $student_id ); - - if ( ! is_array( $course_ids ) ) { - $course_ids = array( $course_ids ); - } - - foreach ( $course_ids as $course_id ) { - - $course = llms_get_post( $course_id ); - - // enroll the student if not already enrolled - if ( ! $student->is_enrolled( $course_id ) ) { - $student->enroll( $course_id ); - } - - $lessons = $course->get_lessons( 'ids' ); - $num_lessons = count( $lessons ); - $stop = 100 === $perc ? $num_lessons : round( ( $perc / 100 ) * $num_lessons ); - - foreach ( $lessons as $i => $lid ) { - - // stop once we reach the stopping point - if ( $i + 1 > $stop ) { - break; - } - - $lesson = llms_get_post( $lid ); - if ( $lesson->has_quiz() ) { - - $attempt = LLMS_Quiz_Attempt::init( $lesson->get( 'quiz' ), $lid, $student->get_id() )->start(); - while ( $attempt->get_next_question() ) { - - $question_id = $attempt->get_next_question(); - $question = llms_get_post( $question_id ); - $options = $question->get_choices(); - $attempt->answer_question( $question_id, array( rand( 0, ( count( $options ) - 1 ) ) ) ); - - } - - $attempt->end(); - - } else { - - $student->mark_complete( $lid, 'lesson' ); - - } - - } - - } - } - - /** - * Generates a set of mock courses - * @param integer $num_courses number of courses to generate - * @param integer $num_sections number of sections to generate for each course - * @param integer $num_lessons number of lessons to generate for each section - * @param integer $num_quizzes number of quizzes to generate for each section - * quizzes will be attached to the last lessons ie each section - * if you generate 3 lessons / section and 1 quiz / section the quiz - * will always be the 3rd lesson - * @return array indexed array of course ids - * @since 3.7.3 - * @version 3.7.3 - */ - protected function generate_mock_courses( $num_courses = 1, $num_sections = 5, $num_lessons = 5, $num_quizzes = 1, $num_questions = 5 ) { - - $courses = array(); - $i = 1; - while ( $i <= $num_courses ) { - $courses[] = $this->get_mock_course_array( $i, $num_sections, $num_lessons, $num_quizzes, $num_questions ); - $i++; - } - - $gen = new LLMS_Generator( array( 'courses' => $courses ) ); - $gen->set_generator( 'LifterLMS/BulkCourseGenerator' ); - $gen->set_default_post_status( 'publish' ); - $gen->generate(); - if ( ! $gen->is_error() ) { - return $gen->get_generated_courses(); - } - - } - - /** - * Generates an array of course data which can be passed to a Generator - * @param int $iterator number for use as course number - * @param int $num_sections number of sections to generate for the course - * @param int $num_lessons number of lessons for each section in the course - * @param int $num_quizzes number of quizzes for each section in the course - * @return array - * @since 3.7.3 - * @version 3.16.12 - */ - protected function get_mock_course_array( $iterator = 1, $num_sections = 3, $num_lessons = 5, $num_quizzes = 1, $num_questions = 5 ) { - - $mock = array( - 'title' => sprintf( 'mock course %d', $iterator ), - ); - - $sections = array(); - $sections_i = 1; - while ( $sections_i <= $num_sections ) { - - $section = array( - 'title' => sprintf( 'mock section %d', $sections_i ), - 'lessons' => array(), - ); - - $lessons_i = 1; - - $quizzes_start_i = $num_lessons - $num_quizzes + 1; - - while ( $lessons_i <= $num_lessons ) { - - $lesson = array( - 'title' => sprintf( 'mock lesson %d', $lessons_i ), - ); - - if ( $lessons_i >= $quizzes_start_i ) { - - $lesson['quiz_enabled'] = 'yes'; - - $lesson['quiz'] = array( - 'title' => sprintf( 'mock quiz %d', $lessons_i ), - ); - - $questions = array(); - $questions_i = 1; - while ( $questions_i <= $num_questions ) { - - $options_i = 1; - $total_options = rand( 2, 5 ); - $correct_option = rand( $options_i, $total_options ); - $choices = array(); - while( $options_i <= $total_options ) { - $choices[] = array( - 'choice' => sprintf( 'choice %d', $options_i ), - 'choice_type' => 'text', - 'correct' => ( $options_i === $correct_option ), - ); - $options_i++; - } - $questions[] = array( - 'title' => sprintf( 'question %d', $questions_i ), - 'question_type' => 'choice', - 'choices' => $choices, - 'points' => 1, - ); - - $questions_i++; - - } - - $lesson['quiz']['questions'] = $questions; - - } - - array_push( $section['lessons'], $lesson ); - $lessons_i++; - } - - array_push( $sections, $section ); - - $sections_i++; - - } - - $mock['sections'] = $sections; - - return $mock; - - } - - protected function get_mock_student() { - $student_id = $this->factory->user->create( array( 'role' => 'student' ) ); - return llms_get_student( $student_id ); - } - -} diff --git a/tests/framework/llms.test.functions.php b/tests/framework/llms.test.functions.php deleted file mode 100644 index 6f9e0bccc2..0000000000 --- a/tests/framework/llms.test.functions.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php - -/** - * Plug llms_crrent_time() to allow mocking of the current time via the $llms_mock_time global - * @param string $type Type of time to retrieve. Accepts 'mysql', 'timestamp', or PHP date format string (e.g. 'Y-m-d'). - * @param int|bool $gmt Optional. Whether to use GMT timezone. Default false. - * @return int|string Integer if $type is 'timestamp', string otherwise. - * @since 3.4.0 - * @version 3.17.0 - */ -function llms_current_time( $type, $gmt = 0 ) { - global $llms_mock_time; - if ( ! empty( $llms_mock_time ) ) { - - switch ( $type ) { - case 'mysql': - return date( 'Y-m-d H:i:s', $llms_mock_time ); - case 'timestamp': - return $llms_mock_time; - default: - return date( $type, $llms_mock_time ); - } - - } - return current_time( $type, $gmt ); -} - -/** - * Set the mocked current time - * @param mixed $time date time string parsable by date() - * @return void - * @since 3.4.0 - * @version 3.4.0 - */ -function llms_mock_current_time( $time ) { - global $llms_mock_time; - $llms_mock_time = strtotime( $time ); -} - -/** - * Reset current time after mocking it - * @return void - * @since 3.16.0 - * @version 3.16.0 - */ -function llms_reset_current_time() { - global $llms_mock_time; - $llms_mock_time = null; -} - -/** - * Set the time limit threshold - * @param int $limit time limit in milliseconds - * @return void - * @since 3.17.4 - * @version 3.17.4 - */ -function llms_set_test_time_limit( $limit = 4000 ) { - global $llms_test_time_limit; - $llms_test_time_limit = $limit; -} diff --git a/tests/unit-tests/abstracts/class.llms.test.abstract.integration.php b/tests/unit-tests/abstracts/class.llms.test.abstract.integration.php deleted file mode 100644 index 314698783d..0000000000 --- a/tests/unit-tests/abstracts/class.llms.test.abstract.integration.php +++ /dev/null @@ -1,110 +0,0 @@ -<?php -/** - * Tests for the LLMS_Abstract_Integration class - * @group abstracts - * @group integrations - * @since [version] - * @version [version] - */ -class LLMS_Test_Abstract_Integration extends LLMS_UnitTestCase { - - /** - * Retrieve the abstract class mock stub - * @return obj - * @since [version] - * @version [version] - */ - private function get_stub() { - - $stub = $this->getMockForAbstractClass( 'LLMS_Abstract_Integration' ); - - // setup variables that would be configured by abstract configure method - $stub->title = 'Mock Integration'; - $stub->id = 'mocker'; - $stub->description = 'this is a mock description of the integration'; - - return $stub; - - } - - /** - * test add_settings() method - * @return void - * @since [version] - * @version [version] - */ - public function test_add_settings() { - - $stub = $this->get_stub(); - - // must be an array - $this->assertTrue( is_array( $stub->add_settings( array() ) ) ); - - // only the default integration settings - $this->assertEquals( 4, count( $stub->add_settings( array() ) ) ); - - // mimic other settings from other integrations - $this->assertEquals( 10, count( $stub->add_settings( array( 1, 2, 3, 4, 5, 6 ) ) ) ); - - } - - /** - * Test is_available() method - * @return void - * @since [version] - * @version [version] - */ - public function test_is_available() { - - $stub = $this->get_stub(); - - // by default it is not available - $this->assertFalse( $stub->is_available() ); - - // enable it - $stub->set_option( 'enabled', 'yes' ); - $this->assertTrue( $stub->is_available() ); - - // explicitly disable it - $stub->set_option( 'enabled', 'no' ); - $this->assertFalse( $stub->is_available() ); - - } - - /** - * Test is_enabled() method - * @return void - * @since [version] - * @version [version] - */ - public function test_is_enabled() { - - $stub = $this->get_stub(); - - // disabled by default (no option found) - $this->assertFalse( $stub->is_enabled() ); - - // enable it - $stub->set_option( 'enabled', 'yes' ); - $this->assertTrue( $stub->is_enabled() ); - - // explicitly disable it - $stub->set_option( 'enabled', 'no' ); - $this->assertFalse( $stub->is_enabled() ); - - } - - /** - * test is_installed() method - * by default this just returns true, extending classes override it - * @return void - * @since [version] - * @version [version] - */ - public function test_is_installed() { - - $this->assertTrue( $this->get_stub()->is_installed() ); - - } - -} diff --git a/tests/unit-tests/abstracts/class.llms.test.abstract.options.data.php b/tests/unit-tests/abstracts/class.llms.test.abstract.options.data.php deleted file mode 100644 index 4d0effd94e..0000000000 --- a/tests/unit-tests/abstracts/class.llms.test.abstract.options.data.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php -/** - * Tests for the LLMS_Abstract_Integration class - * @group abstracts - * @group options - * @group settings - * @since [version] - * @version [version] - */ -class LLMS_Test_Abstract_Options_Data extends LLMS_UnitTestCase { - - /** - * Retrieve the abstract class mock stub - * @return obj - * @since [version] - * @version [version] - */ - private function get_stub() { - - return $this->getMockForAbstractClass( 'LLMS_Abstract_Options_Data' ); - - } - - /** - * test get_option() method - * @return void - * @since [version] - * @version [version] - */ - public function test_get_option() { - - $stub = $this->get_stub(); - - // default value - $this->assertEquals( '', $stub->get_option( 'mock_option' ) ); - $this->assertEquals( 'mockvalue', $stub->get_option( 'mock_option', 'mockvalue' ) ); - - update_option( 'llms_mock_option', 'mockvalue' ); - - $this->assertEquals( 'mockvalue', $stub->get_option( 'mock_option' ) ); - $this->assertEquals( 'mockvalue', $stub->get_option( 'mock_option', 'anothermockvalue' ) ); - - } - - /** - * test get_option_name() method - * @return void - * @since [version] - * @version [version] - */ - public function test_get_option_name() { - - $stub = $this->get_stub(); - - $this->assertEquals( 'llms_mock_option', $stub->get_option_name( 'mock_option' ) ); - - // change the option prefix as an extending class might via overriding the `get_option_prefix()` method - $reflection = new ReflectionClass( $this->get_stub() ); - $prop = $reflection->getProperty( 'option_prefix' ); - $prop->setAccessible( true ); - $prop->setValue( $stub, 'llms_extended_' ); - - $this->assertEquals( 'llms_extended_mock_option', $stub->get_option_name( 'mock_option' ) ); - - } - - /** - * test set_option() method - * @return void - * @since [version] - * @version [version] - */ - public function test_set_option() { - - delete_option( 'llms_mock_option' ); - $this->assertEquals( true, $this->get_stub()->set_option( 'mock_option', 'mockvalue' ) ); - $this->assertEquals( 'mockvalue', get_option( 'llms_mock_option', 'mockvalue' ) ); - - } - -} diff --git a/tests/unit-tests/class.llms.test.controller.lesson.progression.php b/tests/unit-tests/class.llms.test.controller.lesson.progression.php deleted file mode 100644 index 1754d927ba..0000000000 --- a/tests/unit-tests/class.llms.test.controller.lesson.progression.php +++ /dev/null @@ -1,144 +0,0 @@ -<?php -/** - * Tests for LifterLMS Lesson Progression Forms & Functios - * @group controllers - * @group lessons - * @since 3.17.1 - * @version 3.17.1 - */ -class LLMS_Test_Controller_Lesson_Progression extends LLMS_UnitTestCase { - - public function setUp() { - llms_clear_notices(); - parent::setUp(); - } - - /** - * Setup Post data to mock post and request data - * @param array $vars mock post data - * @return void - * @since 3.17.1 - * @version 3.17.1 - */ - private function setup_post( $vars = array() ) { - putenv( 'REQUEST_METHOD=POST' ); - $_POST = array_merge( $_POST, $vars ); - $_REQUEST = array_merge( $_REQUEST, $vars ); - } - - /** - * Test the submission of the mark lesson complete form - * @return void - * @since 3.17.1 - * @version 3.17.1 - */ - public function test_handle_complete_form() { - - // form not submitted - $this->setup_post( array() ); - do_action( 'init' ); - $this->assertEquals( 0, did_action( 'llms_trigger_lesson_completion' ) ); - - // form submitted but missing required fields - $this->setup_post( array( - '_wpnonce' => wp_create_nonce( 'mark_complete' ), - ) ); - do_action( 'init' ); - $this->assertEquals( 0, did_action( 'llms_trigger_lesson_completion' ) ); - - // form submitted but invalid lesson id - $this->setup_post( array( - '_wpnonce' => wp_create_nonce( 'mark_complete' ), - 'mark-complete' => 'wut', // lesson id - 'mark_complete' => '', // button - ) ); - do_action( 'init' ); - $this->assertEquals( 0, did_action( 'llms_trigger_lesson_completion' ) ); - $this->assertEquals( 1, llms_notice_count( 'error' ) ); - - $course = llms_get_post( $this->generate_mock_courses( 1, 1, 1, 0, 0 )[0] ); - $lesson_id = $course->get_lessons( 'ids' )[0]; - - $student = $this->get_mock_student(); - $student->enroll( $course->get( 'id' ) ); - wp_set_current_user( $student->get_id() ); - - $this->setup_post( array( - '_wpnonce' => wp_create_nonce( 'mark_complete' ), - 'mark-complete' => $lesson_id, // lesson id - 'mark_complete' => '', // button - ) ); - do_action( 'init' ); - $this->assertEquals( 1, did_action( 'llms_trigger_lesson_completion' ) ); - $this->assertTrue( $student->is_complete( $lesson_id, 'lesson' ) ); - - } - - /** - * Test the submission of the mark lesson incomplete form - * @return void - * @since 3.17.1 - * @version 3.17.1 - */ - public function test_handle_inccomplete_form() { - - // form not submitted - $this->setup_post( array() ); - do_action( 'init' ); - $this->assertEquals( 0, did_action( 'llms_mark_incomplete' ) ); - - // form submitted but missing required fields - $this->setup_post( array( - '_wpnonce' => wp_create_nonce( 'mark_incomplete' ), - ) ); - do_action( 'init' ); - $this->assertEquals( 0, did_action( 'llms_mark_incomplete' ) ); - - // form submitted but invalid lesson id - $this->setup_post( array( - '_wpnonce' => wp_create_nonce( 'mark_incomplete' ), - 'mark-incomplete' => 'wut', // lesson id - 'mark_incomplete' => '', // button - ) ); - do_action( 'init' ); - $this->assertEquals( 0, did_action( 'llms_mark_incomplete' ) ); - $this->assertEquals( 1, llms_notice_count( 'error' ) ); - - $course = llms_get_post( $this->generate_mock_courses( 1, 1, 1, 0, 0 )[0] ); - $lesson_id = $course->get_lessons( 'ids' )[0]; - - $student = $this->get_mock_student(); - $student->enroll( $course->get( 'id' ) ); - $student->mark_complete( $lesson_id, 'lesson' ); - wp_set_current_user( $student->get_id() ); - - $this->setup_post( array( - '_wpnonce' => wp_create_nonce( 'mark_incomplete' ), - 'mark-incomplete' => $lesson_id, // lesson id - 'mark_incomplete' => '', // button - ) ); - do_action( 'init' ); - $this->assertFalse( $student->is_complete( $lesson_id, 'lesson' ) ); - - } - - /** - * Test the Mark Complete function as triggered by the `llms_trigger_lesson_completion` action - * @return void - * @since 3.17.1 - * @version 3.17.1 - */ - public function test_mark_complete() { - - $course = llms_get_post( $this->generate_mock_courses( 1, 1, 1, 0, 0 )[0] ); - $lesson_id = $course->get_lessons( 'ids' )[0]; - - $student = $this->get_mock_student(); - $student->enroll( $course->get( 'id' ) ); - - do_action( 'llms_trigger_lesson_completion', $student->get( 'id' ), $lesson_id ); - $this->assertTrue( $student->is_complete( $lesson_id, 'lesson' ) ); - - } - -} diff --git a/tests/unit-tests/class.llms.test.frontend.assets.php b/tests/unit-tests/class.llms.test.frontend.assets.php deleted file mode 100644 index 7685ae6cc6..0000000000 --- a/tests/unit-tests/class.llms.test.frontend.assets.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php -/** - * LLMS Frontend Assets Tests - */ - -class LLMS_Test_Frontend_Assets extends LLMS_UnitTestCase { - - /** - * Test inline script managment functions - * @return void - * @since 3.4.1 - * @version 3.4.1 - */ - public function test_inline_scripts() { - - // new script should return true - $this->assertTrue( LLMS_Frontend_Assets::enqueue_inline_script( 'test-id', 'alert("hello");', 'footer', 25 ) ); - - // script should be enqueued - $this->assertTrue( LLMS_Frontend_Assets::is_inline_script_enqueued( 'test-id' ) ); - - // duplicate should assert false - $this->assertFalse( LLMS_Frontend_Assets::enqueue_inline_script( 'test-id', 'alert("hello");', 'footer', 25 ) ); - - // fake script not enqueued - $this->assertFalse( LLMS_Frontend_Assets::is_inline_script_enqueued( 'fake-id' ) ); - - } - -} diff --git a/tests/unit-tests/class.llms.test.functions.access.php b/tests/unit-tests/class.llms.test.functions.access.php deleted file mode 100644 index 6a4fea069c..0000000000 --- a/tests/unit-tests/class.llms.test.functions.access.php +++ /dev/null @@ -1,256 +0,0 @@ -<?php -/** - * Tests for LifterLMS Access Functions - * @group access - * @since 3.7.3 - * @version 3.16.0 - */ -class LLMS_Test_Functions_Access extends LLMS_UnitTestCase { - - /** - * Get a formatted date for setting time period related restrictions - * @param string $offset adjust day via strtotime - * @param string $format desired retured format, passed to date() - * @return string - * @since 3.7.3 - * @version 3.7.3 - */ - private function get_date( $offset = '+7 days', $format = 'm/d/y' ) { - return date( $format, strtotime( $offset, current_time( 'timestamp' ) ) ); - } - - /** - * Test drip restrictions - * @return [type] - * @since 3.16.0 - * @version 3.16.0 - */ - public function test_llms_is_post_restricted_by_drip_settings() { - - $course_id = $this->generate_mock_courses( 1, 1, 2, 0 )[0]; - $course = llms_get_post( $course_id ); - $lesson = $course->get_lessons()[0]; - $lesson_id = $lesson->get( 'id' ); - $student = $this->get_mock_student(); - wp_set_current_user( $student->get_id() ); - $student->enroll( $course_id ); - - // no drip settings, lesson is currently available - $this->assertFalse( llms_is_post_restricted_by_drip_settings( $lesson_id ) ); - - // date in past so the lesson is available - $lesson = llms_get_post( $lesson_id ); - $lesson->set( 'drip_method', 'date' ); - $lesson->set( 'date_available', '12/12/2012' ); - $lesson->set( 'time_available', '12:12 AM' ); - $this->assertFalse( llms_is_post_restricted_by_drip_settings( $lesson_id ) ); - - // date in future so lesson not available - $lesson->set( 'date_available', date( 'm/d/Y', current_time( 'timestamp' ) + DAY_IN_SECONDS ) ); - $this->assertEquals( $lesson_id, llms_is_post_restricted_by_drip_settings( $lesson_id ) ); - - // available 3 days after enrollment - $lesson->set( 'drip_method', 'enrollment' ); - $lesson->set( 'days_before_available', '3' ); - $this->assertEquals( $lesson_id, llms_is_post_restricted_by_drip_settings( $lesson_id ) ); - - // now available - llms_mock_current_time( '+4 days' ); - $this->assertFalse( llms_is_post_restricted_by_drip_settings( $lesson_id ) ); - - llms_reset_current_time(); - $lesson->set( 'drip_method', 'start' ); - $course->set( 'start_date', date( 'm/d/Y', current_time( 'timestamp' ) + DAY_IN_SECONDS ) ); - - // not available until 3 days after course start date - $this->assertEquals( $lesson_id, llms_is_post_restricted_by_drip_settings( $lesson_id ) ); - - // now available - llms_mock_current_time( '+4 days' ); - $this->assertFalse( llms_is_post_restricted_by_drip_settings( $lesson_id ) ); - - } - - public function test_llms_is_post_restricted_by_membership() { - - $memberships = $this->factory->post->create_many( 2, array( - 'post_type' => 'llms_membership', - ) ); - $post_id = $this->factory->post->create(); - $student = $this->get_mock_student(); - $uid = $student->get_id(); - - - $this->assertFalse( llms_is_post_restricted_by_membership( $post_id ) ); - $this->assertFalse( llms_is_post_restricted_by_membership( $post_id, $uid ) ); - - update_post_meta( $post_id, '_llms_restricted_levels', $memberships ); - update_post_meta( $post_id, '_llms_is_restricted', 'yes' ); - - $this->assertEquals( $memberships[0], llms_is_post_restricted_by_membership( $post_id ) ); - $this->assertEquals( $memberships[0], llms_is_post_restricted_by_membership( $post_id, $uid ) ); - - $out = llms_is_post_restricted_by_membership( $post_id ); - $in = llms_is_post_restricted_by_membership( $post_id, $uid ); - - $student->enroll( $memberships[1] ); - $this->assertEquals( $memberships[1], llms_is_post_restricted_by_membership( $post_id, $uid ) ); - - } - - /** - * Test the llms_is_post_restricted_by_prerequisite() function - * @return void - * @since 3.8.0 - * @version 3.8.0 - */ - public function test_llms_is_post_restricted_by_prerequisite() { - - $courses = $this->generate_mock_courses( 3, 2, 1, 1 ); - - $prereq_course_id = $courses[0]; - - $course_id = $courses[1]; - $course = llms_get_post( $course_id ); - - $track = wp_insert_term( 'mock track', 'course_track' ); - $track_id = $track['term_id']; - $course_in_track_id = $courses[2]; - wp_set_post_terms( $course_in_track_id, $track_id, 'course_track' ); - - $lessons = $course->get_lessons( 'ids' ); - - $lesson_2 = llms_get_post( $lessons[1] ); - $lesson_2->set( 'has_prerequisite', 'yes' ); - $lesson_2->set( 'prerequisite', $lessons[0] ); - - $test_ids = array_merge( $lessons, $course->get_quizzes() ); - - $this->prereq_tests( $test_ids, $course, $prereq_course_id, $track_id ); - - $student_id = $this->factory->user->create( array( 'role' => 'student' ) ); - - // results should all be the same with the student b/c nothing completed - $this->prereq_tests( $test_ids, $course, $prereq_course_id, $track_id, $student_id ); - - // results differ once student completes coures - $this->complete_courses_for_student( $student_id, $courses ); - - $this->prereq_tests( $test_ids, $course, $prereq_course_id, $track_id, $student_id ); - - } - - /** - * test_llms_is_post_restricted_by_prerequisite() runs this series of assertions several times - * @param array $test_ids array of post ids to test the llms_is_post_restricted_by_prerequisite() against - * @param obj $course course objet - * @param int $prereq_course_id post id of the prereq course - * @param int $track_id term id of the prereq track - * @param int $user_id wp user id of a student - * @return void - * @since 3.7.3 - * @version 3.12.0 - */ - private function prereq_tests( $test_ids = array(), $course, $prereq_course_id, $track_id, $user_id = null ) { - - $student = $user_id ? new LLMS_Student( $user_id ) : null; - - foreach ( $test_ids as $test_id ) { - - $course->set( 'has_prerequisite', 'no' ); - $course->set( 'prerequisite', '' ); - $course->set( 'prerequisite_track', '' ); - - $post = llms_get_post( $test_id ); - - if ( 'lesson' === get_post_type( $test_id ) && $post->has_prerequisite() ) { - - $lesson_prereq_id = $post->get( 'prerequisite' ); - $lesson_res = $student && $student->is_complete( $lesson_prereq_id, 'lesson' ) ? false : array( - 'type' => 'lesson', - 'id' => $lesson_prereq_id, - ); - $this->assertEquals( $lesson_res, llms_is_post_restricted_by_prerequisite( $test_id, $user_id ) ); - - } - - // set a course prereq - $course->set( 'has_prerequisite', 'yes' ); - $course->set( 'prerequisite', $prereq_course_id ); - $prereq_course_res = $student && $student->is_complete( $prereq_course_id, 'course' ) ? false : array( - 'type' => 'course', - 'id' => $prereq_course_id, - ); - $this->assertEquals( $prereq_course_res, llms_is_post_restricted_by_prerequisite( $test_id, $user_id ) ); - - // set a track prereq - $course->set( 'prerequisite_track', $track_id ); - - // checks course prereq first and only returns one - $this->assertEquals( $prereq_course_res, llms_is_post_restricted_by_prerequisite( $test_id, $user_id ) ); - - // no course prereq, returns track id - $course->set( 'prerequisite', '' ); - $prereq_track_res = $student && $student->is_complete( $track_id, 'course_track' ) ? false : array( - 'type' => 'course_track', - 'id' => $track_id, - ); - $this->assertEquals( $prereq_track_res, llms_is_post_restricted_by_prerequisite( $test_id, $user_id ) ); - - } - - } - - /** - * Test the llms_is_post_restricted_by_time_period() function - * @return void - * @since 3.7.3 - * @version 3.7.3 - */ - public function test_llms_is_post_restricted_by_time_period() { - - $courses = $this->generate_mock_courses( 1, 1, 1, 1 ); - $course_id = $courses[0]; - $course = llms_get_post( $course_id ); - - $test_ids = array_merge( array( $course_id ), $course->get_lessons( 'ids' ), $course->get_quizzes() ); - - foreach ( $test_ids as $test_post_id ) { - - $course->set( 'time_period', 'no' ); - - // no time period - $this->assertFalse( llms_is_post_restricted_by_time_period( $test_post_id ) ); - - // enable the restriction - $course->set( 'time_period', 'yes' ); - - // no dates set the course is closed without dates - $this->assertEquals( $course_id, llms_is_post_restricted_by_time_period( $test_post_id ) ); - - // start date in the future - $course->set( 'start_date', $this->get_date( '+7 days' ) ); - $this->assertEquals( $course_id, llms_is_post_restricted_by_time_period( $test_post_id ) ); - - // start date in past - $course->set( 'start_date', $this->get_date( '-7 days' ) ); - $this->assertFalse( llms_is_post_restricted_by_time_period( $test_post_id ) ); - - // start date in past and end date in past - $course->set( 'end_date', $this->get_date( '-5 days' ) ); - $this->assertEquals( $course_id, llms_is_post_restricted_by_time_period( $test_post_id ) ); - - // no start date, end date in past - $course->set( 'start_date', '' ); - $this->assertEquals( $course_id, llms_is_post_restricted_by_time_period( $test_post_id ) ); - - // no start date end in future - $course->set( 'end_date', $this->get_date( '+7 days' ) ); - $this->assertEquals( $course_id, llms_is_post_restricted_by_time_period( $test_post_id ) ); - - } - - } - - -} diff --git a/tests/unit-tests/class.llms.test.functions.core.php b/tests/unit-tests/class.llms.test.functions.core.php deleted file mode 100644 index ffafc3bfa3..0000000000 --- a/tests/unit-tests/class.llms.test.functions.core.php +++ /dev/null @@ -1,419 +0,0 @@ -<?php -/** - * Tests for LifterLMS Core Functions - * @since 3.3.1 - * @version 3.6.0 - */ -class LLMS_Test_Functions_Core extends LLMS_UnitTestCase { - - /** - * Test llms_are_terms_and_conditions_required() - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_llms_are_terms_and_conditions_required() { - - // terms true & page id numeric - update_option( 'lifterlms_registration_require_agree_to_terms', 'yes' ); - update_option( 'lifterlms_terms_page_id', '1' ); - $this->assertTrue( llms_are_terms_and_conditions_required() ); - - // terms true & page id non-numeric - update_option( 'lifterlms_registration_require_agree_to_terms', 'yes' ); - update_option( 'lifterlms_terms_page_id', 'brick' ); - $this->assertFalse( llms_are_terms_and_conditions_required() ); - - // terms true & no page id - update_option( 'lifterlms_terms_page_id', '' ); - $this->assertFalse( llms_are_terms_and_conditions_required() ); - - // terms true & page id 0 - update_option( 'lifterlms_terms_page_id', '0' ); - $this->assertFalse( llms_are_terms_and_conditions_required() ); - - // terms false and page id good - update_option( 'lifterlms_registration_require_agree_to_terms', 'no' ); - update_option( 'lifterlms_terms_page_id', '1' ); - $this->assertFalse( llms_are_terms_and_conditions_required() ); - - update_option( 'lifterlms_registration_require_agree_to_terms', 'no' ); - update_option( 'lifterlms_terms_page_id', 'brick' ); - $this->assertFalse( llms_are_terms_and_conditions_required() ); - - } - - /** - * Test llms_get_core_supported_themes() - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_llms_get_core_supported_themes() { - - $this->assertFalse( empty( llms_get_core_supported_themes() ) ); - $this->assertTrue( is_array( llms_get_core_supported_themes() ) ); - - } - - /** - * test llms_get_date_diff() - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_llms_get_date_diff() { - - $this->assertEquals( '18 days', llms_get_date_diff( '2016-05-12', '2016-05-30' ) ); - $this->assertEquals( '1 year, 2 months', llms_get_date_diff( '2016-01-01', '2017-03-25 23:32:32' ) ); - $this->assertEquals( '10 months, 14 days', llms_get_date_diff( '2016-01-01', '2016-11-15' ) ); - $this->assertEquals( '4 years, 24 days', llms_get_date_diff( '2013-03-01', '2017-03-25' ) ); - $this->assertEquals( '3 years, 10 months', llms_get_date_diff( '2013-03-01', '2017-01-25' ) ); - $this->assertEquals( '24 seconds', llms_get_date_diff( '2016-05-12 01:01:01', '2016-05-12 01:01:25' ) ); - $this->assertEquals( '1 second', llms_get_date_diff( '2016-05-12 01:01:01', '2016-05-12 01:01:02' ) ); - $this->assertEquals( '59 seconds', llms_get_date_diff( '2016-05-12 01:01:01', '2016-05-12 01:02:00' ) ); - $this->assertEquals( '1 minute, 44 seconds', llms_get_date_diff( '2016-05-12 01:01:01', '2016-05-12 01:02:45' ) ); - $this->assertEquals( '1 minute, 14 seconds', llms_get_date_diff( '2016-05-12 01:01:01', '2016-05-12 01:02:15' ) ); - $this->assertEquals( '3 minutes, 59 seconds', llms_get_date_diff( '2016-05-12 01:01:01', '2016-05-12 01:05:00' ) ); - $this->assertEquals( '44 minutes, 33 seconds', llms_get_date_diff( '2016-05-12 01:01:01', '2016-05-12 01:45:34' ) ); - $this->assertEquals( '44 minutes, 33 seconds', llms_get_date_diff( '2016-05-12 01:45:34', '2016-05-12 01:01:01' ) ); - - } - - /** - * test llms_get_engagement_triggers() - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_llms_get_engagement_triggers() { - $this->assertFalse( empty( llms_get_engagement_triggers() ) ); - $this->assertTrue( is_array( llms_get_engagement_triggers() ) ); - } - - /** - * test llms_get_engagement_types() - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_llms_get_engagement_types() { - $this->assertFalse( empty( llms_get_engagement_types() ) ); - $this->assertTrue( is_array( llms_get_engagement_types() ) ); - } - - /** - * Test llms_get_product_visibility_options() - * @return void - * @since 3.6.0 - * @version 3.6.0 - */ - public function test_llms_get_product_visibility_options() { - $this->assertFalse( empty( llms_get_product_visibility_options() ) ); - $this->assertTrue( is_array( llms_get_product_visibility_options() ) ); - } - - /** - * Test llms_find_coupon() - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_llms_find_coupon() { - - // create a coupon - $id = $this->factory->post->create( array( - 'post_title' => 'coopond', - 'post_type' => 'llms_coupon', - ) ); - $this->assertEquals( $id, llms_find_coupon( 'coopond' ) ); - - // create a dup - $dup = $this->factory->post->create( array( - 'post_title' => 'coopond', - 'post_type' => 'llms_coupon', - ) ); - $this->assertEquals( $dup, llms_find_coupon( 'coopond' ) ); - - // test dupcheck - $this->assertEquals( $id, llms_find_coupon( 'coopond', $dup ) ); - - // delete the coupon - wp_delete_post( $id ); - wp_delete_post( $dup ); - $this->assertEmpty( llms_find_coupon( 'coopond' ) ); - - } - - /** - * Test llms_get_enrolled_students() - * @return void - * @since 3.6.0 - * @version 3.6.0 - */ - function test_llms_get_enrolled_students() { - - $course_id = $this->factory->post->create( array( - 'post_type' => 'course', - ) ); - - $students = $this->factory->user->create_many( 25, array( 'role' => 'student' ) ); - $students_copy = $students; - foreach ( $students as $student_id ) { - $student = new LLMS_Student( $student_id ); - $student->enroll( $course_id ); - } - - // test basic enrollment query passing in a string - $this->assertEquals( $students, llms_get_enrolled_students( $course_id, 'enrolled', 50, 0 ) ); - // test basic enrollment query passing in an array - $this->assertEquals( $students, llms_get_enrolled_students( $course_id, array( 'enrolled' ), 50, 0 ) ); - - // test pagination - $this->assertEquals( array_splice( $students, 0, 10 ), llms_get_enrolled_students( $course_id, 'enrolled', 10, 0 ) ); - $this->assertEquals( array_splice( $students, 0, 10 ), llms_get_enrolled_students( $course_id, 'enrolled', 10, 10 ) ); - $this->assertEquals( $students, llms_get_enrolled_students( $course_id, 'enrolled', 10, 20 ) ); - - // should be no one expired - $this->assertEquals( array(), llms_get_enrolled_students( $course_id, 'expired', 10, 0 ) ); - - // sleeping makes unerollment tests work - sleep( 1 ); - - $i = 0; - $expired = array(); - while ( $i < 5 ) { - $student = new LLMS_Student( $students_copy[ $i ] ); - $student->unenroll( $course_id, 'any', 'expired' ); - $expired[] = $students_copy[ $i ]; - $i++; - } - - // test expired alone - $this->assertEquals( $expired, llms_get_enrolled_students( $course_id, 'expired', 10, 0 ) ); - - // test multiple statuses - $this->assertEquals( $students_copy, llms_get_enrolled_students( $course_id, array( 'enrolled', 'expired' ), 50, 0 ) ); - - } - - /** - * test llms_get_enrollment_statuses() - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_llms_get_enrollment_statuses() { - $this->assertFalse( empty( llms_get_enrollment_statuses() ) ); - $this->assertTrue( is_array( llms_get_enrollment_statuses() ) ); - } - - /** - * Test llms_get_enrollment_status_name() - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_llms_get_enrollment_status_name() { - $this->assertNotEquals( 'asrt', llms_get_enrollment_status_name( 'cancelled' ) ); - $this->assertNotEquals( 'cancelled', llms_get_enrollment_status_name( 'Cancelled' ) ); - $this->assertEquals( 'Cancelled', llms_get_enrollment_status_name( 'cancelled' ) ); - $this->assertEquals( 'Cancelled', llms_get_enrollment_status_name( 'Cancelled' ) ); - $this->assertEquals( 'wut', llms_get_enrollment_status_name( 'wut' ) ); - } - - /** - * Test llms_get_ip_address() - * @return void - * @since 3.6.0 - * @version 3.6.0 - */ - public function test_llms_get_ip_address() { - - $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; - $this->assertEquals( '127.0.0.1', llms_get_ip_address() ); - - $_SERVER['HTTP_X_FORWARDED_FOR'] = '127.0.0.1, 192.168.1.1, 192.168.1.5'; - $this->assertEquals( '127.0.0.1', llms_get_ip_address() ); - - $_SERVER['X-Real-IP'] = '127.0.0.1'; - $this->assertEquals( '127.0.0.1', llms_get_ip_address() ); - - } - - /** - * Test llms_get_order_status_name() - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_llms_get_order_status_name() { - $this->assertNotEmpty( llms_get_order_status_name( 'llms-active' ) ); - $this->assertEquals( 'Active', llms_get_order_status_name( 'llms-active' ) ); - $this->assertEquals( 'wut', llms_get_order_status_name( 'wut' ) ); - } - - /** - * test llms_get_order_statuses() - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_llms_get_order_statuses() { - - $this->assertTrue( is_array( llms_get_order_statuses() ) ); - $this->assertFalse( empty( llms_get_order_statuses() ) ); - $this->assertEquals( array( - 'llms-active', - 'llms-cancelled', - 'llms-completed', - 'llms-expired', - 'llms-failed', - 'llms-on-hold', - 'llms-pending', - 'llms-refunded', - ), array_keys( llms_get_order_statuses() ) ); - - $this->assertTrue( is_array( llms_get_order_statuses( 'recurring' ) ) ); - $this->assertFalse( empty( llms_get_order_statuses( 'recurring' ) ) ); - $this->assertEquals( array( - 'llms-active', - 'llms-cancelled', - 'llms-expired', - 'llms-failed', - 'llms-on-hold', - 'llms-pending', - 'llms-refunded', - ), array_keys( llms_get_order_statuses( 'recurring' ) ) ); - - $this->assertTrue( is_array( llms_get_order_statuses( 'single' ) ) ); - $this->assertFalse( empty( llms_get_order_statuses( 'single' ) ) ); - $this->assertEquals( array( - 'llms-cancelled', - 'llms-completed', - 'llms-failed', - 'llms-pending', - 'llms-refunded', - ), array_keys( llms_get_order_statuses( 'single' ) ) ); - - } - - /** - * Test llms_get_post() - * @return void - * @since 3.3.1 - * @version 3.16.11 - */ - public function test_llms_get_post() { - - $types = array( - 'LLMS_Access_Plan' => 'llms_access_plan', - 'LLMS_Coupon' => 'llms_coupon', - 'LLMS_Course' => 'course', - 'LLMS_Lesson' => 'lesson', - 'LLMS_Membership' => 'llms_membership', - 'LLMS_Order' => 'llms_order', - 'LLMS_Quiz' => 'llms_quiz', - 'LLMS_Question' => 'llms_question', - 'LLMS_Section' => 'llms_section', - 'LLMS_Transaction' => 'llms_transaction', - ); - - foreach ( $types as $class => $type ) { - - $id = $this->factory->post->create( array( - 'post_type' => $type, - ) ); - $this->assertInstanceOf( $class, llms_get_post( $id ) ); - - } - - $this->assertInstanceOf( 'WP_Post', llms_get_post( $this->factory->post->create(), 'post' ) ); - $this->assertNull( llms_get_post( 'fail' ) ); - $this->assertNull( llms_get_post( 0 ) ); - - } - - /** - * Test llms_get_post_parent_course() - * @return void - * @since 3.6.0 - * @version 3.6.0 - */ - public function test_llms_get_post_parent_course() { - - $course = new LLMS_Course( 'new', 'title' ); - $section = new LLMS_Section( 'new', array( - 'post_title' => 'section', - 'meta_input' => array( - '_llms_parent_course' => $course->get( 'id' ) - ), - ) ); - $lesson = new LLMS_Lesson( 'new', array( - 'post_title' => 'lesson', - 'meta_input' => array( - '_llms_parent_course' => $course->get( 'id' ), - '_llms_parent_section' => $section->get( 'id' ), - ), - ) ); - - foreach ( array( $section, $lesson ) as $obj ) { - - $post = get_post( $obj->get( 'id' ) ); - - // pass in post id - $this->assertEquals( $course, llms_get_post_parent_course( $post->ID ) ); - - // pass in an object - $this->assertEquals( $course, llms_get_post_parent_course( $post ) ); - - } - - // other post types don't have a parent course - $reg_post = $this->factory->post->create(); - $this->assertNull( llms_get_post_parent_course( $reg_post ) ); - - } - - - /** - * test llms_get_transaction_statuses() - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_llms_get_transaction_statuses() { - $this->assertFalse( empty( llms_get_transaction_statuses() ) ); - $this->assertTrue( is_array( llms_get_transaction_statuses() ) ); - } - - /** - * Test llms_is_site_https() - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_llms_is_site_https() { - update_option( 'home', 'https://is.ssl' ); - $this->assertTrue( llms_is_site_https() ); - - update_option( 'home', 'http://is.ssl' ); - $this->assertFalse( llms_is_site_https() ); - } - - /** - * Test llms_trim_string() - * @return void - * @since 3.3.1 - * @version 3.6.0 - */ - public function test_llms_trim_string() { - - $this->assertEquals( 'yasssss', llms_trim_string( 'yasssss' ) ); - $this->assertEquals( 'y...', llms_trim_string( 'yasssss', 4 ) ); - $this->assertEquals( 'ya.', llms_trim_string( 'yasssss', 3, '.' ) ); - $this->assertEquals( 'yassss$', llms_trim_string( 'yassss$s', 7, '' ) ); - - } - -} diff --git a/tests/unit-tests/class.llms.test.functions.quiz.php b/tests/unit-tests/class.llms.test.functions.quiz.php deleted file mode 100644 index ee59d55bae..0000000000 --- a/tests/unit-tests/class.llms.test.functions.quiz.php +++ /dev/null @@ -1,86 +0,0 @@ -<?php -/** - * Tests for LifterLMS Core Functions - * @since 3.16.0 - * @version 3.16.12 - */ -class LLMS_Test_Functions_Quiz extends LLMS_UnitTestCase { - - /** - * Test picture choice columns - * @return void - * @since 3.16.0 - * @version 3.16.0 - */ - public function test_llms_get_picture_choice_question_cols() { - - $combos = array( - 1 => 1, - 2 => 2, - 3 => 3, - 4 => 4, - 5 => 3, - 6 => 3, - 7 => 4, - 8 => 4, - 9 => 3, - 10 => 5, - 11 => 4, - 12 => 4, - 13 => 5, - 14 => 5, - 15 => 5, - 16 => 4, - 17 => 3, - 18 => 3, - 19 => 5, - 20 => 5, - 21 => 3, - 22 => 4, - 23 => 4, - 24 => 4, - 25 => 5, - 26 => 5, - 27 => 5, - 45 => 5, - 999 => 5, - 9999 => 5, - ); - - foreach ( $combos as $choices => $expected_cols ) { - - $this->assertEquals( $expected_cols, llms_get_picture_choice_question_cols( $choices ) ); - - } - - } - - /** - * Test llms_shuffle_choices - * @return void - * @since 3.16.12 - * @version 3.16.12 - */ - public function test_llms_shuffle_choices() { - - // 0 & 1 elements can't really be shuffled... - $choices = array(); - $this->assertEquals( $choices, llms_shuffle_choices( $choices ) ); - - $choices = array( 1 ); - $this->assertEquals( $choices, llms_shuffle_choices( $choices ) ); - - // 2 or more items will never match the original after shuffling - $i = 2; - while( $i <= 26 ) { - - $choices = range( 0, $i ); - $this->assertNotEquals( $choices, llms_shuffle_choices( $choices ) ); - $i++; - - } - - - } - -} diff --git a/tests/unit-tests/class.llms.test.generator.php b/tests/unit-tests/class.llms.test.generator.php deleted file mode 100644 index 27fb593ac9..0000000000 --- a/tests/unit-tests/class.llms.test.generator.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php -/** - * LLMS Generator Tests - * @group generator - */ - -class LLMS_Test_Generator extends LLMS_UnitTestCase { - - public function test_generate() { - - $course = $this->get_mock_course_array( 1, 3, 5, 1, 5 ); - $course['author'] = array( - 'email' => 'test@test.tld', - 'id' => 12345, - ); - $course['categories'] = array( 'cat' ); - $course['tags'] = array( 'tag1', 'tag2' ); - $course['tracks'] = array( 'track' ); - $course['difficulty'] = 'hard'; - $course['access_plans'] = array( - array( - 'title' => 'plan1' - ), - array( - 'title' => 'plan2' - ), - ); - - $course['custom'] = array( - 'customdata' => array( 'yes' ), - 'customdata2' => array( 'no', 'yes', 'maybe' ), - 'customdata3' => array( serialize( array( 'no', 'yes', 'maybe' ) ) ), - ); - - $gen = new LLMS_Generator( $course ); - $gen->set_generator( 'LifterLMS/SingleCourseGenerator' ); - $gen->set_default_post_status( 'publish' ); - $gen->generate(); - - $this->assertEquals( array( - 'authors' => 1, - 'courses' => 1, - 'sections' => 3, - 'lessons' => 15, - 'quizzes' => 3, - 'questions' => 15, - 'terms' => 5, - 'plans' => 2, - ), $gen->get_results() ); - - // ensure custom data is properly added - $courses = $gen->get_generated_courses(); - $this->assertEquals( $course['custom'], get_post_custom( $courses[0] ) ); - - - } - - public function test_is_error() { - - // no generator - $gen = new LLMS_Generator( array() ); - $gen->generate(); - $this->assertTrue( $gen->is_error() ); - - // generator set but no data - $gen->set_generator( 'LifterLMS/BulkCourseGenerator' ); - $gen->generate(); - $this->assertTrue( $gen->is_error() ); - - // invalid generator format - $gen = new LLMS_Generator( array( 'title' => 'course title' ) ); - $gen->set_generator( 'LifterLMS/BulkCourseGenerator' ); - $gen->generate(); - $this->assertTrue( $gen->is_error() ); - - // good - $gen = new LLMS_Generator( array( 'title' => 'course title' ) ); - $gen->set_generator( 'LifterLMS/SingleCourseExporter' ); - $gen->generate(); - $this->assertFalse( $gen->is_error() ); - - } - -} diff --git a/tests/unit-tests/class.llms.test.hasher.php b/tests/unit-tests/class.llms.test.hasher.php deleted file mode 100644 index a42bb5b787..0000000000 --- a/tests/unit-tests/class.llms.test.hasher.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php -/** - * Tests for LLMS_Site - * @since 3.16.10 - * @version 3.16.10 - */ -class LLMS_Test_Hasher extends LLMS_UnitTestCase { - - private $ids = array(); - private $hashes = array(); - - private function get_random_id( $max = 99999999 ) { - - $id = rand( 1, $max ); - while ( ! in_array( $id, $this->ids ) ) { - array_push( $this->ids, $id ); - return $id; - } - return $max + 1; - - } - - /** - * Test the hashing/unhashing functions - * @return [type] - * @since 3.16.10 - * @version 3.16.10 - */ - public function test_hash_unhash() { - - foreach ( range( 1, 10000 ) as $i ) { - $id = $this->get_random_id(); - $hash = LLMS_Hasher::hash( $id ); - $this->assertFalse( in_array( $hash, $this->hashes ) ); - $this->assertEquals( $id, LLMS_Hasher::unhash( $hash ) ); - } - - } - -} diff --git a/tests/unit-tests/class.llms.test.install.php b/tests/unit-tests/class.llms.test.install.php deleted file mode 100644 index 2fe2c92e9c..0000000000 --- a/tests/unit-tests/class.llms.test.install.php +++ /dev/null @@ -1,286 +0,0 @@ -<?php -/** - * Tests for the LLMS_Install Class - * @since 3.3.1 - * @version 3.6.0 - */ -class LLMS_Test_Install extends LLMS_UnitTestCase { - - /** - * Tests for check_version() - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_check_version() { - - // ensure the database update runs - update_option( 'lifterlms_current_version', (float) LLMS()->version - 1 ); - update_option( 'lifterlms_db_version', LLMS()->version ); - LLMS_Install::check_version(); - $this->assertTrue( did_action( 'lifterlms_updated' ) === 1 ); - - // ensure that if both are equal the database doesn't run again - update_option( 'lifterlms_current_version', LLMS()->version ); - update_option( 'lifterlms_db_version', LLMS()->version ); - LLMS_Install::check_version(); - $this->assertTrue( did_action( 'lifterlms_updated' ) === 1 ); - - } - - /** - * Tests for create_cron_jobs() - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_create_cron_jobs() { - - // clear crons - wp_clear_scheduled_hook( 'lifterlms_cleanup_sessions' ); - wp_clear_scheduled_hook( 'llms_send_tracking_data' ); - - LLMS_Install::create_cron_jobs(); - $this->assertTrue( is_numeric( wp_next_scheduled( 'lifterlms_cleanup_sessions' ) ) ); - $this->assertTrue( is_numeric( wp_next_scheduled( 'llms_send_tracking_data' ) ) ); - - } - - /** - * Tests for create_difficulties() & remove_difficulties() - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_create_difficulties_crud() { - - // terms may or may not exist and should exist after creation - LLMS_Install::create_difficulties(); - foreach( LLMS_Install::get_difficulties() as $name ) { - $this->assertInstanceOf( 'WP_Term', get_term_by( 'name', $name, 'course_difficulty' ) ); - } - - // terms should not exist after deleting terms - LLMS_Install::remove_difficulties(); - foreach( LLMS_Install::get_difficulties() as $name ) { - $this->assertFalse( get_term_by( 'name', $name, 'course_difficulty' ) ); - } - - // terms should exist after creating difficulties - LLMS_Install::create_difficulties(); - foreach( LLMS_Install::get_difficulties() as $name ) { - $this->assertInstanceOf( 'WP_Term', get_term_by( 'name', $name, 'course_difficulty' ) ); - } - - } - - /** - * Test create_files() - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_create_files() { - - LLMS_Install::create_files(); - $this->assertTrue( file_exists( LLMS_LOG_DIR ) ); - $this->assertTrue( file_exists( LLMS_LOG_DIR . '.htaccess' ) ); - $this->assertTrue( file_exists( LLMS_LOG_DIR . 'index.html' ) ); - $this->assertFalse( file_exists( LLMS_LOG_DIR . 'fail.txt' ) ); - - } - - /** - * Tests for create_options() - * @return void - * @since 3.3.1 - * @version 3.5.1 - */ - public function test_create_options() { - - // clear options - global $wpdb; - $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE 'lifterlms\_%';" ); - - // install options - LLMS_Install::create_options(); - - // check they exist - $settings = LLMS_Admin_Settings::get_settings_tabs(); - - foreach ( $settings as $section ) { - // skip general settings since this screen doesn't actually have any settings on it - if ( 'general' === $section->id ) { - continue; - } - foreach ( $section->get_settings() as $value ) { - if ( isset( $value['default'] ) && isset( $value['id'] ) ) { - $this->assertEquals( $value['default'], get_option( $value['id'] ) ); - } - } - } - - } - - /** - * Tests for create_pages() - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_create_pages() { - - // clear options - delete_option( 'lifterlms_shop_page_id' ); - delete_option( 'lifterlms_memberships_page_id' ); - delete_option( 'lifterlms_checkout_page_id' ); - delete_option( 'lifterlms_myaccount_page_id' ); - - LLMS_Install::create_pages(); - - $this->assertGreaterThan( 0, get_option( 'lifterlms_shop_page_id' ) ); - $this->assertGreaterThan( 0, get_option( 'lifterlms_memberships_page_id' ) ); - $this->assertGreaterThan( 0, get_option( 'lifterlms_checkout_page_id' ) ); - $this->assertGreaterThan( 0, get_option( 'lifterlms_myaccount_page_id' ) ); - - // Delete pages - wp_delete_post( get_option( 'lifterlms_shop_page_id' ), true ); - wp_delete_post( get_option( 'lifterlms_memberships_page_id' ), true ); - wp_delete_post( get_option( 'lifterlms_checkout_page_id' ), true ); - wp_delete_post( get_option( 'lifterlms_myaccount_page_id' ), true ); - - // Clear options - delete_option( 'lifterlms_shop_page_id' ); - delete_option( 'lifterlms_memberships_page_id' ); - delete_option( 'lifterlms_checkout_page_id' ); - delete_option( 'lifterlms_myaccount_page_id' ); - - LLMS_Install::create_pages(); - - $this->assertGreaterThan( 0, get_option( 'lifterlms_shop_page_id' ) ); - $this->assertGreaterThan( 0, get_option( 'lifterlms_memberships_page_id' ) ); - $this->assertGreaterThan( 0, get_option( 'lifterlms_checkout_page_id' ) ); - $this->assertGreaterThan( 0, get_option( 'lifterlms_myaccount_page_id' ) ); - - } - - /** - * Tests for create_tables() - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_create_tables() { - - global $wpdb; - - // clear tables - $wpdb->query( - "DROP TABLE IF EXISTS - {$wpdb->prefix}lifterlms_user_postmeta, - {$wpdb->prefix}lifterlms_product_to_voucher, - {$wpdb->prefix}lifterlms_voucher_code_redemptions, - {$wpdb->prefix}lifterlms_vouchers_codes - ;" - ); - - // install tables - LLMS_Install::create_tables(); - - // ensure they exist - $this->assertEquals( "{$wpdb->prefix}lifterlms_user_postmeta", $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}lifterlms_user_postmeta'" ) ); - $this->assertEquals( "{$wpdb->prefix}lifterlms_product_to_voucher", $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}lifterlms_product_to_voucher'" ) ); - $this->assertEquals( "{$wpdb->prefix}lifterlms_voucher_code_redemptions", $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}lifterlms_voucher_code_redemptions'" ) ); - $this->assertEquals( "{$wpdb->prefix}lifterlms_vouchers_codes", $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}lifterlms_vouchers_codes'" ) ); - - } - - /** - * Test create_visibilities() - * @return void - * @since 3.6.0 - * @version 3.6.0 - */ - public function test_create_visibilities() { - - // terms may or may not exist and should exist after creation - LLMS_Install::create_visibilities(); - foreach( array_keys( llms_get_product_visibility_options() ) as $name ) { - $this->assertInstanceOf( 'WP_Term', get_term_by( 'name', $name, 'llms_product_visibility' ) ); - } - - } - - /** - * Test get_difficulties() - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_get_difficulties() { - - $this->assertTrue( ! empty( LLMS_Install::get_difficulties() ) ); - $this->assertTrue( is_array( LLMS_Install::get_difficulties() ) ); - - } - - /** - * Test update_db_version() - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_update_db_version() { - - LLMS_Install::update_db_version( '1' ); - $this->assertEquals( '1', get_option( 'lifterlms_db_version' ) ); - - LLMS_Install::update_db_version(); - $this->assertEquals( LLMS()->version, get_option( 'lifterlms_db_version' ) ); - - LLMS_Install::update_db_version( '1.2.3' ); - $this->assertEquals( '1.2.3', get_option( 'lifterlms_db_version' ) ); - - } - - /** - * Test update_llms_version() - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_update_llms_version() { - - LLMS_Install::update_llms_version( '1' ); - $this->assertEquals( '1', get_option( 'lifterlms_current_version' ) ); - - LLMS_Install::update_llms_version(); - $this->assertEquals( LLMS()->version, get_option( 'lifterlms_current_version' ) ); - - LLMS_Install::update_llms_version( '1.2.3' ); - $this->assertEquals( '1.2.3', get_option( 'lifterlms_current_version' ) ); - - } - - /** - * Tests for install() function - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_install() { - - // clean existing install first - if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) { - define( 'WP_UNINSTALL_PLUGIN', true ); - define( 'LLMS_REMOVE_ALL_DATA', true ); - } - - include( dirname( dirname( dirname( __FILE__ ) ) ) . '/uninstall.php' ); - - LLMS_Install::install(); - $this->assertTrue( get_option( 'lifterlms_current_version' ) === LLMS()->version ); - - } - -} diff --git a/tests/unit-tests/class.llms.test.integrations.php b/tests/unit-tests/class.llms.test.integrations.php deleted file mode 100644 index da4aedc466..0000000000 --- a/tests/unit-tests/class.llms.test.integrations.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php -/** - * Tests for the LLMS_Integrations class - * @group integrations - * @since [version] - * @version [version] - */ -class LLMS_Test_Integrations extends LLMS_UnitTestCase { - - /** - * test instance() method - * @return void - * @since [version] - * @version [version] - */ - public function test_instance() { - - $this->assertTrue( is_a( LLMS()->integrations(), 'LLMS_Integrations' ) ); - - } - - public function test_get_integration() {} - - /** - * test init() method - * @return void - * @since [version] - * @version [version] - */ - public function test_init() { - - $instance = LLMS()->integrations(); - $this->assertEquals( 2, count( $instance->integrations() ) ); - - } - - /** - * Test get available integrations - * @return void - * @since [version] - * @version [version] - */ - public function test_get_available_integrations() { - - $instance = LLMS()->integrations(); - $this->assertEquals( array(), $instance->get_available_integrations() ); - - // enable an integration - update_option( 'llms_integration_bbpress_enabled', 'yes' ); - - // option is enabled but it's not available b/c deps. don't exist - $this->assertEquals( 0, count( $instance->get_available_integrations() ) ); - - // deps exist now - $stub = $this->getMockBuilder( 'bbPress' )->getMock(); - $this->assertEquals( 1, count( $instance->get_available_integrations() ) ); - - } - - /** - * Test integrations() method - * @return [type] - * @since [version] - * @version [version] - */ - public function test_integrations() { - - $instance = LLMS()->integrations(); - $this->assertEquals( 2, count( $instance->integrations() ) ); - - } - - -} diff --git a/tests/unit-tests/class.llms.test.main.class.php b/tests/unit-tests/class.llms.test.main.class.php deleted file mode 100644 index 151f6c0c93..0000000000 --- a/tests/unit-tests/class.llms.test.main.class.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php -/** - * Tests for LifterLMS Main Class - * @since 3.3.1 - * @version 3.3.1 - */ -class LLMS_Test_Main_Class extends LLMS_UnitTestCase { - - /** - * Setup function - * @since 3.3.1 - * @version 3.3.1 - */ - public function setUp() { - parent::setUp(); - $this->llms = LLMS(); - } - - /** - * test the _instance variable - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_llms_instance() { - - $this->assertClassHasStaticAttribute( '_instance', 'LifterLMS' ); - - } - - /** - * Test class constants - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_constants() { - - $this->assertEquals( $this->llms->version, LLMS_VERSION ); - $this->assertNotEquals( LLMS_LOG_DIR, '' ); - $this->assertNotEquals( LLMS_SVG_DIR, '' ); - $this->assertNotEquals( LLMS_PLUGIN_DIR, '' ); - $this->assertNotEquals( LLMS_PLUGIN_FILE, '' ); - $this->assertNotEquals( LLMS_TEMPLATE_PATH, '' ); - - } - - /** - * Test main instants - * @return void - * @since 3.3.1 - * @version 3.3.1 - */ - public function test_instances() { - - $this->assertInstanceOf( 'LLMS_Payment_Gateways', $this->llms->payment_gateways() ); - $this->assertInstanceOf( 'LLMS_Emails', $this->llms->mailer() ); - $this->assertInstanceOf( 'LLMS_Integrations', $this->llms->integrations() ); - $this->assertInstanceOf( 'LLMS_Engagements', $this->llms->engagements() ); - $this->assertInstanceOf( 'LLMS_Certificates', $this->llms->certificates() ); - $this->assertInstanceOf( 'LLMS_Achievements', $this->llms->achievements() ); - - } - -} diff --git a/tests/unit-tests/class.llms.test.model.llms.quiz.attempt.php b/tests/unit-tests/class.llms.test.model.llms.quiz.attempt.php deleted file mode 100644 index e66e33df36..0000000000 --- a/tests/unit-tests/class.llms.test.model.llms.quiz.attempt.php +++ /dev/null @@ -1,328 +0,0 @@ -<?php -/** - * Tests for the LLMS_Install Class - * @group quizzes - * @since 3.9.0 - * @version 3.17.4 - */ -class LLMS_Test_Model_Quiz_Attempt extends LLMS_UnitTestCase { - - /** - * Get an initialized mock attempt - * @param integer $num_questions number of questions to add to the quiz - * @return obj - * @since 3.9.2 - * @version 3.16.11 - */ - private function get_mock_attempt( $num_questions = 5 ) { - - $uid = $this->factory->user->create(); - $courses = $this->generate_mock_courses( 1, 1, 1, 1, $num_questions ); - - $course = llms_get_post( $courses[0] ); - $lesson = $course->get_lessons()[0]; - $lid = $lesson->get( 'id' ); - $qid = $lesson->get( 'quiz' ); - - $attempt = LLMS_Quiz_Attempt::init( $qid, $lid, $uid ); - $attempt->save(); - return $attempt; - - } - - /** - * [take_a_quiz description] - * @param [type] $desired_grade grade for the attempt - * @param [type] $passing_percent required passing percentage - * @param integer $num_questions number of questions in the quiz - * @param string $rand whether to randomize question order - * @param string $passing_required whether passing grade is required to complete the associated lesson - * @return [type] [description] - * @since 3.9.2 - * @version 3.17.1 - */ - private function take_a_quiz( $desired_grade, $passing_percent, $num_questions = 15, $attempt = null, $rand = 'no', $passing_required = 'no' ) { - - if ( ! $attempt ) { - $attempt = $this->get_mock_attempt( $num_questions ); - } - - update_post_meta( $attempt->get( 'lesson_id' ), '_llms_require_passing_grade', $passing_required ); - - update_post_meta( $attempt->get( 'quiz_id' ), '_llms_random_questions', $rand ); - update_post_meta( $attempt->get( 'quiz_id' ), '_llms_passing_percent', $passing_percent ); - $to_answer_correctly = 0 === $desired_grade ? 0 : $desired_grade / 100 * $num_questions; - - $attempt->start(); - - $current_question = 1; - while ( $attempt->get_next_question() ) { - - $question_id = $attempt->get_next_question(); - $question = llms_get_post( $question_id ); - - $answer_type = ( $current_question <= $to_answer_correctly ); - - // answer correctly until we don't have to anymore - foreach( $question->get_choices() as $key => $choice ) { - if ( $answer_type === $choice->is_correct() ) { - $attempt->answer_question( $question_id, array( $choice->get( 'id' ) ) ); - break; - } - } - - $current_question++; - - } - - $attempt->end(); - - return $attempt; - - } - - - public function test_grading_with_floats() { - - $attempt = $this->get_mock_attempt( 6 ); - - $questions = $attempt->get_questions(); - - foreach ( $questions as $key => &$data ) { - $data['points'] = 3.3333; - } - - $attempt->set_questions( $questions, true ); - - $attempt = $this->take_a_quiz( 67, 65, 6, $attempt ); - $this->assertEquals( 66.67, $attempt->get( 'grade' ) ); - - } - - - /** - * Test counter functions - * @return void - * @since 3.9.2 - * @version 3.16.11 - */ - public function test_get_count() { - - $i = 1; - while ( $i <= 10 ) { - - $attempt = $this->get_mock_attempt( $i ); - - // num of questions and num available points will both be the same given the default mock quiz data - foreach ( array( 'available_points', 'questions' ) as $key ) { - $this->assertEquals( $i, $attempt->get_count( $key ) ); - } - - // update each question to have a random number of points and ensure the available points from getter is correct - $questions = $attempt->get_questions(); - $total_points = 0; - foreach( $questions as $key => $question ) { - $add = rand( 1, 100 ); - $questions[ $key ]['points'] = $add; - $total_points += $add; - } - - $attempt->set_questions( $questions, true ); - - $this->assertEquals( $total_points, $attempt->get_count( 'available_points' ) ); - - $i++; - - } - - - } - - - /** - * test get student function - * @return void - * @since 3.9.0 - * @version 3.9.0 - */ - public function test_get_student() { - - $uid = $this->factory->user->create(); - $courses = $this->generate_mock_courses( 1, 1, 1, 1 ); - - $course = llms_get_post( $courses[0] ); - $lesson = $course->get_lessons()[0]; - $lid = $lesson->get( 'id' ); - $qid = $lesson->get( 'quiz' ); - - $attempt = LLMS_Quiz_Attempt::init( $qid, $lid, $uid ); - - $this->assertTrue( is_a( $attempt->get_student(), 'LLMS_Student' ) ); - $this->assertEquals( $uid, $attempt->get_student()->get_id() ); - - } - - // /** - // * test getters and setters and save method - // * @return void - // * @since 3.9.0 - // * @version 3.9.2 - // */ - // public function test_getters_setters_and_save() { - - // $uid = $this->factory->user->create(); - // $courses = $this->generate_mock_courses( 1, 1, 1, 1 ); - - // $course = llms_get_post( $courses[0] ); - // $lesson = $course->get_lessons()[0]; - // $lid = $lesson->get( 'id' ); - // $qid = $lesson->get( 'quiz' ); - - // $attempt = LLMS_Quiz_Attempt::init( $qid, $lid, $uid ); - - // $data = array( - // 'attempt' => 5, - // 'current' => false, - // 'end_date' => current_time( 'mysql' ), - // 'grade' => 85.35, - // 'passed' => true, - // 'start_date' => current_time( 'mysql' ), - // ); - - // foreach ( $data as $key => $val ) { - - // $attempt->set( $key, $val ); - // $this->assertEquals( $data[ $key ], $attempt->get( $key ) ); - - // } - - // foreach ( $attempt->get( 'questions' ) as $key => $question ) { - - // $this->assertEquals( $key + 1, $attempt->get_question_order( $question['id'] ) ); - - // } - - // // save the attempt again and ensure persistence works - // $attempt->save(); - - // $student = llms_get_student( $uid ); - // $attempt = $student->quizzes()->get_attempt( $qid, $lid, $data['attempt'] ); - // foreach ( $data as $key => $val ) { - // $this->assertEquals( $data[ $key ], $attempt->get( $key ) ); - // } - - // } - - // /** - // * test static init function - // * @return void - // * @since 3.9.0 - // * @version 3.9.0 - // */ - // public function test_init() { - - // $uid = $this->factory->user->create(); - // $courses = $this->generate_mock_courses( 1, 1, 1, 1 ); - - // $course = llms_get_post( $courses[0] ); - // $lesson = $course->get_lessons()[0]; - // $lid = $lesson->get( 'id' ); - // $qid = $lesson->get( 'assigned_quiz' ); - - // $attempt = LLMS_Quiz_Attempt::init( $qid, $lid, $uid )->save(); - - // $att_num = $attempt->get( 'attempt' ); - // $student = llms_get_student( $uid ); - - // // attempt saved successfully - // $this->assertEquals( $student->quizzes()->get_attempt( $qid, $lid, $att_num ), $attempt ); - - // // no user, attempt throws exception - // try { - // $attempt = LLMS_Quiz_Attempt::init( $qid, $lid, null )->save(); - // } catch ( Exception $exception ) { - // $this->assertTrue( is_a( $exception, 'Exception' ) ); - // } - - // // no user but a current user exists - // wp_set_current_user( $uid ); - // $attempt = LLMS_Quiz_Attempt::init( $qid, $lid, null )->save(); - // $att_num = $attempt->get( 'attempt' ); - // $this->assertEquals( 1, $att_num ); // should not increment because the attempt already exists - // $this->assertEquals( $student->quizzes()->get_attempt( $qid, $lid, $att_num ), $attempt ); - - // // mark the new attempt as not-current - // $attempt->set( 'current', false )->save(); - // $attempt = LLMS_Quiz_Attempt::init( $qid, $lid, null )->save(); - // // new attempt should be #2 - // $this->assertEquals( 2, $attempt->get( 'attempt' ) ); - - // } - - // /** - // * test quiz start - // * @return void - // * @since 3.9.0 - // * @version 3.9.0 - // */ - // public function test_start() { - - // $attempt = $this->get_mock_attempt( 2 ); - // $attempt->start(); - - // $this->assertTrue( ! empty( $attempt->get( 'start_date' ) ) ); - - // } - - /** - * Take a bunch of quizzes - * quiz taking / ending functions - * Tests grade / point calculations - * pass/fail/complete actions - * @return void - * @since 3.9.2 - * @version 3.17.4 - */ - public function test_take_some_quizzes( ) { - - $i = 0; - $num_tests = 0; - $num_pass = 0; - $num_fail = 0; - while ( $i <= 100 ) { - - $rand = rand( 0, 1 ) ? 'yes' : 'no'; - $passing = $rand = rand( 0, 1 ) ? 'yes' : 'no'; - $attempt = $this->take_a_quiz( $i, 65, 25, null, $rand, $passing ); - - if ( 0 === $i ) { - $grade = 0; - } else { - $weight = ( 100 / $attempt->get_count( 'available_points' ) ); - $grade = floor( $i / 100 * 25 ) * $weight; - } - - $this->assertEquals( $grade, $attempt->get( 'grade' ) ); - $this->assertTrue( ! is_null( $attempt->get( 'end_date' ) ) ); - - if ( $grade < 65 ) { - $num_fail++; - $this->assertFalse( $attempt->is_passing() ); - $is_complete = llms_parse_bool( $passing ) ? false : true; - } else { - $num_pass++; - $this->assertTrue( $attempt->is_passing() ); - $is_complete = true; - } - - $this->assertEquals( $is_complete, llms_is_complete( $attempt->get( 'student_id' ), $attempt->get( 'lesson_id' ), 'lesson' ) ); - - $num_tests++; - - $i = $i + ( 5 * rand( 1, 20 ) ); - - } - - } - -} diff --git a/tests/unit-tests/class.llms.test.payment.gateways.php b/tests/unit-tests/class.llms.test.payment.gateways.php deleted file mode 100644 index 608133f6b1..0000000000 --- a/tests/unit-tests/class.llms.test.payment.gateways.php +++ /dev/null @@ -1,121 +0,0 @@ -<?php -/** - * Tests for the LLMS_Payment_Gateways class - * @since 3.10.0 - * @version 3.10.0 - */ -class LLMS_Test_Payment_Gateways extends LLMS_UnitTestCase { - - /** - * Enable or disable a payment gateway by ID - * @param string $id gateway id - * @param string $enabled on|off - * @return void - * @since 3.10.0 - * @version 3.10.0 - */ - private function toggle_gateway( $id, $enabled = 'on' ) { - - $enabled = 'on' === $enabled ? 'yes' : 'no'; - - $manual = LLMS()->payment_gateways()->get_gateway_by_id( 'manual' ); - update_option( $manual->get_option_name( 'enabled' ), $enabled ); - - } - - /** - * Test get_enabled_payment_gateways function - * @return void - * @since 3.10.0 - * @version 3.10.0 - */ - public function test_get_enabled_payment_gateways() { - - $gways = LLMS()->payment_gateways(); - - $this->toggle_gateway( 'manual', 'off' ); - - $this->assertEquals( array(), $gways->get_enabled_payment_gateways() ); - - // enable the manual gateway - $this->toggle_gateway( 'manual', 'on' ); - - // gateway should exist in the array - $this->assertTrue( is_array( $gways->get_enabled_payment_gateways() ) ); - $this->assertTrue( array_key_exists( 'manual', $gways->get_enabled_payment_gateways() ) ); - $this->assertEquals( 1, count( $gways->get_enabled_payment_gateways() ) ); - - } - - /** - * Test get_default_gateway() function - * @return void - * @since 3.10.0 - * @version 3.10.0 - */ - public function test_get_default_gateway() { - - // enable the manual gateway - $this->toggle_gateway( 'manual', 'on' ); - $this->assertEquals( 'manual', LLMS()->payment_gateways()->get_default_gateway() ); - - } - - /** - * Test get_payment_gateways() method - * @return void - * @since 3.10.0 - * @version 3.10.0 - */ - public function test_get_payment_gateways() { - - $gways = LLMS()->payment_gateways(); - - $this->assertTrue( is_array( $gways->get_payment_gateways() ) ); - $this->assertTrue( array_key_exists( 'manual', $gways->get_payment_gateways() ) ); - $this->assertEquals( 1, count( $gways->get_payment_gateways() ) ); - - } - - /** - * Test has_gateways() method - * @return void - * @since 3.10.0 - * @version 3.10.0 - */ - public function test_has_gateways() { - - $gways = LLMS()->payment_gateways(); - - // check all gateways (default) - $this->assertTrue( $gways->has_gateways() ); - // check all gateways passing false - $this->assertTrue( $gways->has_gateways( false ) ); - - // check enabled - $this->toggle_gateway( 'manual', 'off' ); - $this->assertFalse( $gways->has_gateways( true ) ); - - $this->toggle_gateway( 'manual', 'on' ); - $this->assertTrue( $gways->has_gateways( true ) ); - - } - - /** - * Test get_gateway_by_id() - * @return void - * @since 3.10.0 - * @version 3.10.0 - */ - public function test_get_gateway_by_id() { - - $gways = LLMS()->payment_gateways(); - $manual = $gways->get_gateway_by_id( 'manual' ); - $this->assertTrue( is_a( $manual, 'LLMS_Payment_Gateway' ) ); - $this->assertEquals( 'manual', $manual->get_id() ); - - $this->assertFalse( $gways->get_gateway_by_id( 'fake_gway' ) ); - - } - -} diff --git a/tests/unit-tests/class.llms.test.post.instructors.php b/tests/unit-tests/class.llms.test.post.instructors.php deleted file mode 100644 index 830ad72ed4..0000000000 --- a/tests/unit-tests/class.llms.test.post.instructors.php +++ /dev/null @@ -1,97 +0,0 @@ -<?php -/** - * Tests for LLMS_Post_Instructors model & functions - * @group LLMS_Post_Instructors - * @group LLMS_Course - * @group LLMS_Membership - * @since 3.13.0 - * @version 3.13.0 - */ -class LLMS_Test_Post_Instructors extends LLMS_UnitTestCase { - - private $post_types = array( 'course', 'llms_membership' ); - - public function test_interface() { - - foreach ( $this->post_types as $post_type ) { - - $post_id = $this->factory->post->create( array( - 'post_type' => $post_type, - ) ); - - $post = llms_get_post( $post_id ); - - $this->assertTrue( method_exists( $post, 'instructors' ) ); - $this->assertTrue( method_exists( $post, 'get_instructors' ) ); - $this->assertTrue( method_exists( $post, 'set_instructors' ) ); - - $this->assertTrue( is_a( $post->instructors(), 'LLMS_Post_Instructors' ) ); - - } - - } - - public function test_getters_setters() { - - $user_ids = $this->factory->user->create_many( 3 ); - - foreach ( $this->post_types as $post_type ) { - - $post_id = $this->factory->post->create( array( - 'post_type' => $post_type, - 'post_author' => $user_ids[0], - ) ); - - $post = llms_get_post( $post_id ); - - $defaults = $post->instructors()->get_defaults(); - - $this->assertTrue( is_array( $post->get_instructors() ) ); - - $post->set_instructors( array( - array( 'id' => $user_ids[0] ), - array( 'id' => $user_ids[1] ), - array( 'id' => $user_ids[2] ), - ) ); - - foreach ( $post->get_instructors() as $instructor ) { - - $this->assertTrue( in_array( $instructor['id'], $user_ids ) ); - $this->assertEquals( $defaults['label'], $instructor['label'] ); - $this->assertEquals( $defaults['visibility'], $instructor['visibility'] ); - - } - - $this->assertEquals( $post->get( 'author' ), $user_ids[0] ); - - $update = array( - array( - 'id' => $user_ids[1], - 'label' => 'mock label', - 'visibility' => 'visible', - ), - array( - 'id' => $user_ids[0], - 'label' => 'mock label', - 'visibility' => 'hidden', - ), - ); - $post->set_instructors( $update ); - $this->assertEquals( $update, $post->get_instructors() ); - - // check exclude hidden works right - unset( $update[1] ); - $this->assertEquals( $update, $post->get_instructors( true ) ); - - - // clear instructors, should respond with a default of the post_author - $post->set_instructors(); - $expect = $defaults; - $expect['id'] = $user_ids[1]; - $this->assertEquals( array( $expect ), $post->get_instructors() ); - - } - - } - -} diff --git a/tests/unit-tests/class.llms.test.post.relationships.php b/tests/unit-tests/class.llms.test.post.relationships.php deleted file mode 100644 index f9b530e8b2..0000000000 --- a/tests/unit-tests/class.llms.test.post.relationships.php +++ /dev/null @@ -1,111 +0,0 @@ -<?php -/** - * Tests for LLMS_Post_Instructors model & functions - * @group post_relationships - * @since 3.16.12 - * @version 3.16.12 - */ -class LLMS_Test_Post_Relationships extends LLMS_UnitTestCase { - - /** - * When deleting lessons - * A) Any lesson which has this lesson as a prereq should have that prereq removed - * And the has_prereq metavalue should be unset returning "no" - * B) Any quiz attached to this lesson should be detached (making it an orphan) - * @return [type] - * @since 3.16.12 - * @version 3.16.12 - */ - private function delete_lesson() { - - $courses = $this->generate_mock_courses( 1, 1, 4, 3, 1 ); - $lessons = llms_get_post( $courses[0] )->get_lessons(); - - // add prereqs to all the lessons except the first - foreach ( $lessons as $i => $lesson ) { - - if ( 0 === $i ) { - continue; - } - - $prev = $lessons[ $i - 1 ]; - - $lesson->set( 'has_prerequisite', 'yes' ); - $lesson->set( 'prerequisite', $prev->get( 'id' ) ); - - } - - // delete posts and run tests - foreach ( $lessons as $i => $lesson ) { - - $quiz = $lesson->get_quiz(); - - wp_delete_post( $lesson->get( 'id' ) ); - - // quizzes attached to the lesson should now be orphaned - if ( $quiz ) { - $this->assertTrue( $quiz->is_orphan() ); - } - - if ( $i === count( $lessons ) - 1 ) { - continue; - } - $next = $lessons[ $i + 1 ]; - - // prereqs should be removed - $this->assertEquals( 'no', $next->get( 'has_prerequisite' ) ); - $this->assertEquals( 0, $next->get( 'prerequisite' ) ); - $this->assertFalse( $next->has_prerequisite() ); - - } - - } - - /** - * When a quiz is deleted, all the child questions should be deleted too - * Lesson should switch quiz_enabled to "no" - * @return void - * @since 3.16.12 - * @version 3.16.12 - */ - private function delete_quiz() { - - $courses = $this->generate_mock_courses( 1, 1, 1, 1, 20 ); - $lesson = llms_get_post( llms_get_post( $courses[0] )->get_lessons( 'ids' )[0] ); - $quiz = $lesson->get_quiz(); - - $questions = $quiz->get_questions( 'ids' ); - - wp_delete_post( $quiz->get( 'id' ), true ); - - foreach ( $questions as $question_id ) { - - $this->assertNull( get_post( $question_id ) ); - - } - - $this->assertFalse( $lesson->is_quiz_enabled() ); - - } - - /** - * Test all relationships based on post types - * @return void - * @since 3.16.12 - * @version 3.16.12 - */ - public function test_maybe_update_relationships() { - - $funcs = array( - 'delete_quiz', - 'delete_lesson', - ); - foreach ( $funcs as $func ) { - - call_user_func( array( $this, $func ) ); - - } - - } - -} diff --git a/tests/unit-tests/class.llms.test.post.types.php b/tests/unit-tests/class.llms.test.post.types.php deleted file mode 100644 index c899781d26..0000000000 --- a/tests/unit-tests/class.llms.test.post.types.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php -/** - * Tests for LifterLMS Custom Post Types - * @group LLMS_Post_Types - * @since 3.13.0 - * @version 3.13.0 - */ -class LLMS_Test_Post_Types extends LLMS_UnitTestCase { - - public function test_register_post_taxonomies() { - - LLMS_Post_Types::register_taxonomies(); - - $taxonomies = array( - 'course_cat', - 'course_difficulty', - 'course_tag', - 'course_track', - 'membership_cat', - 'membership_tag', - 'llms_product_visibility', - 'llms_access_plan_visibility', - ); - - foreach ( $taxonomies as $name ) { - // var_dump( sprintf( '%s: %s', $name, taxonomy_exists( $name ) ) ); - $this->assertTrue( taxonomy_exists( $name ) ); - } - - } - - public function test_register_post_types() { - - LLMS_Post_Types::register_post_types(); - - $post_types = array( - 'course', - 'section', - 'lesson', - 'llms_membership', - 'llms_engagement', - 'llms_order', - 'llms_transaction', - 'llms_achievement', - 'llms_certificate', - 'llms_my_certificate', - 'llms_email', - 'llms_quiz', - 'llms_question', - 'llms_coupon', - 'llms_voucher', - 'llms_review', - 'llms_access_plan', - ); - - foreach ( $post_types as $name ) { - $this->assertTrue( post_type_exists( $name ) ); - } - - } - - public function test_register_post_statuses() { - - LLMS_Post_Types::register_post_statuses(); - - $statuses = array( - 'llms-completed', - 'llms-active', - 'llms-expired', - 'llms-on-hold', - 'llms-pending', - 'llms-cancelled', - 'llms-refunded', - 'llms-failed', - 'llms-txn-failed', - 'llms-txn-pending', - 'llms-txn-refunded', - 'llms-txn-succeeded', - ); - - foreach ( $statuses as $name ) { - $this->assertTrue( ! is_null( get_post_status_object( $name ) ) ); - } - - } - -} diff --git a/tests/unit-tests/class.llms.test.roles.php b/tests/unit-tests/class.llms.test.roles.php deleted file mode 100644 index b6edbaf846..0000000000 --- a/tests/unit-tests/class.llms.test.roles.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php -/** - * Tests for LifterLMS Custom Post Types - * @group LLMS_Roles - * @since 3.13.0 - * @version 3.14.0 - */ -class LLMS_Test_Roles extends LLMS_UnitTestCase { - - public function test_get_all_core_caps() { - - $this->assertTrue( is_array( LLMS_Roles::get_all_core_caps() ) ); - $this->assertTrue( ! empty( LLMS_Roles::get_all_core_caps() ) ); - - } - - public function test_get_roles() { - - $expect = array( - 'instructor' => __( 'Instructor', 'lifterlms' ), - 'instructors_assistant' => __( 'Instructor\'s Assistant', 'lifterlms' ), - 'lms_manager' => __( 'LMS Manager', 'lifterlms' ), - 'student' => __( 'Student', 'lifterlms' ), - ); - $this->assertEquals( $expect, LLMS_Roles::get_roles() ); - - } - - public function test_install() { - - $wp_roles = wp_roles(); - - // remove first - LLMS_Roles::remove_roles(); - - // install them - LLMS_Roles::install(); - - // ensure all the roles were installed - foreach ( array_keys( LLMS_Roles::get_roles() ) as $role ) { - $this->assertTrue( $wp_roles->is_role( $role ) ); - } - - // test admin caps were installed - $admin = $wp_roles->get_role( 'administrator' ); - foreach ( LLMS_Roles::get_all_core_caps() as $cap ) { - $this->assertTrue( $admin->has_cap( $cap ) ); - } - - // test instructor caps - $instructor = $wp_roles->get_role( 'instructor' ); - foreach ( LLMS_Roles::get_all_core_caps() as $cap ) { - $has = $instructor->has_cap( $cap ); - if ( in_array( $cap, array( 'view_lifterlms_reports', 'lifterlms_instructor' ) ) ) { - $this->assertTrue( $has ); - } else { - $this->assertFalse( $has ); - } - } - - } - - public function test_remove_roles() { - - $wp_roles = wp_roles(); - - // ensure roles are installed - LLMS_Roles::install(); - - // remove them - LLMS_Roles::remove_roles(); - - // make sure roles are gone - foreach ( array_keys( LLMS_Roles::get_roles() ) as $role ) { - $this->assertFalse( $wp_roles->is_role( $role ) ); - } - - // test admin caps were removed - $admin = $wp_roles->get_role( 'administrator' ); - foreach ( LLMS_Roles::get_all_core_caps() as $cap ) { - - $this->assertFalse( $admin->has_cap( $cap ) ); - } - - - } - -} diff --git a/tests/unit-tests/class.llms.test.shortcodes.php b/tests/unit-tests/class.llms.test.shortcodes.php deleted file mode 100644 index 4ccd81d1a9..0000000000 --- a/tests/unit-tests/class.llms.test.shortcodes.php +++ /dev/null @@ -1,100 +0,0 @@ -<?php -/** - * Test LifterLMS Shortcodes - */ - -class LLMS_Test_Shortcodes extends LLMS_UnitTestCase { - - /** - * Generic tests and a few tests on the abstract - * @return void - * @since 3.4.3 - * @version 3.4.3 - */ - public function test_shortcodes() { - - $shortcodes = array( - 'LLMS_Shortcode_Course_Author', - 'LLMS_Shortcode_Course_Continue', - 'LLMS_Shortcode_Course_Meta_Info', - 'LLMS_Shortcode_Course_Outline', - 'LLMS_Shortcode_Course_Prerequisites', - 'LLMS_Shortcode_Course_Reviews', - 'LLMS_Shortcode_Course_Syllabus', - 'LLMS_Shortcode_Hide_Content', - 'LLMS_Shortcode_Membership_Link', - 'LLMS_Shortcode_Registration', - ); - - foreach ( $shortcodes as $class ) { - - $obj = $class::instance(); - $this->assertTrue( shortcode_exists( $obj->tag ) ); - $this->assertTrue( is_a( $obj, 'LLMS_Shortcode' ) ); - $this->assertTrue( ! empty( $obj->tag ) ); - $this->assertTrue( is_string( $obj->output() ) ); - $this->assertTrue( is_array( $obj->get_attributes() ) ); - $this->assertTrue( is_string( $obj->get_content() ) ); - - } - - $this->assertClassHasStaticAttribute( '_instances', 'LLMS_Shortcode' ); - - } - - /** - * Test the registration shortcode - * @return void - * @since 3.4.3 - * @version 3.4.3 - */ - public function test_registration() { - - // our output should enqueue this - wp_dequeue_script( 'password-strength-meter' ); - - $obj = LLMS_Shortcode_Registration::instance(); - - // when logged out, there should be html content - $this->assertContains( 'llms-new-person-form-wrapper', $obj->output() ); - - // no html when logged in - $user_id = $this->factory->user->create( array( 'role' => 'administrator' ) ); - wp_set_current_user( $user_id ); - $this->assertEmpty( $obj->output() ); - - // ensure required scripts are enqueued - $this->assertTrue( wp_script_is( 'password-strength-meter', 'enqueued' ) ); - $this->assertTrue( LLMS_Frontend_Assets::is_inline_script_enqueued( 'llms-pw-strength' ) ); - - } - - /** - * Test lifterlms_membership_link shortcode - * @return void - * @since 3.4.3 - * @version 3.4.3 - */ - public function test_membership_link() { - - // create a membership that we can use for linking - $mid = $this->factory->post->create( array( - 'post_title' => 'Test Membership', - 'post_type' => 'llms_membership', - ) ); - - $obj = LLMS_Shortcode_Membership_Link::instance(); - - // test default settings - $this->assertContains( get_permalink( $mid ), $obj->output( array( 'id' => $mid ) ) ); - $this->assertContains( get_the_title( $mid ), $obj->output( array( 'id' => $mid ) ) ); - - $this->assertEquals( $mid, $obj->get_attribute( 'id' ) ); - - // check non default content - $this->assertContains( 'Alternate Text', $obj->output( array( 'id' => $mid ), 'Alternate Text' ) ); - $this->assertEquals( 'Alternate Text', $obj->get_content( 'Alternate Text' ) ); - - } - -} diff --git a/tests/unit-tests/class.llms.test.site.php b/tests/unit-tests/class.llms.test.site.php deleted file mode 100644 index 1b946b6569..0000000000 --- a/tests/unit-tests/class.llms.test.site.php +++ /dev/null @@ -1,142 +0,0 @@ -<?php -/** - * Tests for LLMS_Site - * @since 3.7.4 - * @version 3.7.4 - */ -class LLMS_Test_Site extends LLMS_UnitTestCase { - - /** - * Test clear_lock_url() function - * @return void - * @since 3.8.0 - * @version 3.8.0 - */ - public function test_clear_lock_url() { - - update_option( 'llms_site_url', 'http://mockurl.tld/' ); - LLMS_Site::clear_lock_url(); - $this->assertEquals( '', get_option( 'llms_site_url' ) ); - - } - - /** - * Test lock url getter and setter functions - * @return void - * @since 3.8.0 - * @version 3.8.0 - */ - public function test_get_set_lock_url() { - - $urls = array( - 'https://whatever.com', - 'http://whatever.com', - 'https://w.com', - 'https://whatever-with-a-dash.net', - 'http://wh.at', - 'http://wah.tld', - 'http://waht.tld', - ); - - foreach ( $urls as $url ) { - - update_option( 'siteurl', $url ); - - $site_url = get_site_url(); - - // this is what the lock url should be - $lock_url = substr_replace( $site_url, LLMS_Site::$lock_string, strlen( $site_url ) / 2, 0 ); - - // make sure they match - $this->assertEquals( $lock_url, LLMS_Site::get_lock_url() ); - - // save it - LLMS_Site::set_lock_url(); - - // make sure it saves the right option - $this->assertEquals( $lock_url, get_option( 'llms_site_url' ) ); - - // this should match the original URL - $this->assertEquals( $site_url, LLMS_Site::get_url() ); - - } - - } - - /** - * Test feature getter and setter functions - * @return void - * @since 3.8.0 - * @version 3.8.0 - */ - public function test_get_set_features() { - - // should return an array of defaults even when option doesnt exist - delete_option( 'llms_site_get_features' ); - $this->assertTrue( is_array( LLMS_Site::get_features() ) ); - - // fake feature always returns false - $this->assertFalse( LLMS_Site::get_feature( 'mock_feature' ) ); - - foreach ( array( 'recurring_payments' ) as $feature ) { - - // test getters/setters - LLMS_Site::update_feature( $feature, true ); - $this->assertTrue( LLMS_Site::get_feature( $feature ) ); - - LLMS_Site::update_feature( $feature, false ); - $this->assertFalse( LLMS_Site::get_feature( $feature ) ); - - } - - } - - /** - * Test is_clone() function - * @return void - * @since 3.7.4 - * @version 3.7.4 - */ - public function test_is_clone() { - - $original = get_site_url(); - - // not a clone because the url is the lock url - $this->assertFalse( LLMS_Site::is_clone() ); - - // the url has changed - update_option( 'siteurl', 'http://fakeurl.tld' ); - $this->assertTrue( LLMS_Site::is_clone() ); - - // change it back to the original - update_option( 'siteurl', $original ); - $this->assertFalse( LLMS_Site::is_clone() ); - - // change the schema (should not be identified as a clone) - update_option( 'siteurl', set_url_scheme( $original, 'https' ) ); - $this->assertFalse( LLMS_Site::is_clone() ); - - } - - /** - * Test is_clone_ignored() function - * @return void - * @since 3.8.0 - * @version 3.8.0 - */ - public function test_is_clone_ignored() { - - $this->assertFalse( LLMS_Site::is_clone_ignored() ); - - update_option( 'llms_site_url_ignore', 'yes' ); - $this->assertTrue( LLMS_Site::is_clone_ignored() ); - - update_option( 'llms_site_url_ignore', 'no' ); - $this->assertFalse( LLMS_Site::is_clone_ignored() ); - - update_option( 'llms_site_url_ignore', 'mock' ); - $this->assertFalse( LLMS_Site::is_clone_ignored() ) ; - - } - -} diff --git a/tests/unit-tests/class.llms.test.student.query.php b/tests/unit-tests/class.llms.test.student.query.php deleted file mode 100644 index 6b7a917f91..0000000000 --- a/tests/unit-tests/class.llms.test.student.query.php +++ /dev/null @@ -1,198 +0,0 @@ -<?php -/** - * Tests for the LLMS_Install Class - * @group LLMS_Student_Query - * @since 3.3.1 - * @version 3.13.0 - */ -class LLMS_Test_Student_Query extends LLMS_UnitTestCase { - - /** - * Create a new query for use in these tests - * @param array $args args to pass to the query - * @return obj - * @since 3.4.0 - * @version 3.4.0 - */ - private function query( $args = array() ) { - return new LLMS_Student_Query( $args ); - } - - /** - * Test get() and set() functions - * @return void - * @since 3.4.0 - * @version 3.4.0 - */ - public function test_getters_setters() { - - $args = array( - 'page' => 2, - 'per_page' => 25, - 'post_id' => 1234, - 'search' => 'a search string', - 'sort' => array( - 'id' => 'ASC', - ), - 'suppress_filters' => true, - 'statuses' => array( - 'enrolled', 'expired' - ), - ); - - $query = $this->query(); - - foreach ( $args as $key => $val ) { - - $query->set( $key, $val ); - $this->assertEquals( $args[ $key ], $query->get( $key ) ); - - // test defaults - unset( $query->query_vars[ $key ] ); - $this->assertEquals( 'default_val', $query->get( $key, 'default_val' ) ); - - } - - } - - /** - * Test some real queries - * @return void - * @since 3.13.0 - * @version 3.13.0 - */ - public function test_get_students() { - - $course_id = $this->generate_mock_courses( 1, 1, 1, 0 )[0]; - - $students = $this->factory->user->create_many( 25, array( 'role' => 'student' ) ); - foreach ( $students as $sid ) { - llms_enroll_student( $sid, $course_id, 'testing' ); - } - - // 25 students enrolled - $query = $this->query( array( - 'post_id' => $course_id, - 'per_page' => 10, - ) ); - - $this->assertEquals( 25, $query->found_results ); - $this->assertEquals( 10, $query->number_results ); - $this->assertEquals( 3, $query->max_pages ); - - sleep( 1 ); // sleep because timestamps can't be the same for the next queries to work correctly - - // unenroll 10 students & results should stay the same - foreach ( $query->get_students() as $student ) { - $student->unenroll( $course_id, 'testing' ); - } - - // check for expired from any courses - $query = $this->query( array( - 'per_page' => 10, - 'statuses' => 'expired', - ) ); - $this->assertEquals( 10, $query->found_results ); - - // check for any status again - $query = $this->query( array( - 'post_id' => $course_id, - 'per_page' => 10, - ) ); - $this->assertEquals( 25, $query->found_results ); - $this->assertEquals( 10, $query->number_results ); - $this->assertEquals( 3, $query->max_pages ); - - // check for enrolled only - $query = $this->query( array( - 'post_id' => $course_id, - 'per_page' => 10, - 'statuses' => 'enrolled', - ) ); - $this->assertEquals( 15, $query->found_results ); - $this->assertEquals( 10, $query->number_results ); - $this->assertEquals( 2, $query->max_pages ); - - - // second course - $course_id2 = $this->generate_mock_courses( 1, 1, 1, 0 )[0]; - $students2 = $this->factory->user->create_many( 25, array( 'role' => 'student' ) ); - foreach ( array_merge( $students, $students2 ) as $sid ) { - llms_enroll_student( $sid, $course_id2, 'testing' ); - } - - // check for enrolled only - $query = $this->query( array( - 'post_id' => array( $course_id, $course_id2 ), - 'per_page' => 10, - // 'statuses' => 'enrolled', - ) ); - $this->assertEquals( 50, $query->found_results ); - $this->assertEquals( 10, $query->number_results ); - $this->assertEquals( 5, $query->max_pages ); - - // more students who aren't enrolled - $students3 = $this->factory->user->create_many( 25, array( 'role' => 'student' ) ); - - // anything in any course - $query = $this->query( array( - 'per_page' => 10, - ) ); - $this->assertEquals( 50, $query->found_results ); - - // cancelled in any course (shouldn't have anything here) - $query = $this->query( array( - 'per_page' => 10, - 'statuses' => 'cancelled', - ) ); - $this->assertEquals( 0, $query->found_results ); - - - // test some searches - $query = $this->query( array( - 'search' => 'No Results Found Plz' - ) ); - $this->assertEquals( 0, $query->found_results ); - - // should hit all the mock users - $query = $this->query( array( - 'search' => 'user_' - ) ); - $this->assertEquals( 50, $query->found_results ); - - - update_user_meta( $students2[5], 'first_name', 'testymcname' ); - $query = $this->query( array( - 'search' => 'testymcname' - ) ); - $this->assertEquals( 1, $query->found_results ); - $this->assertEquals( $students2[5], $query->get_students()[0]->get_id() ); - - } - - /** - * Test the parse_setup_args() function - * @return void - * @since 3.4.0 - * @version 3.4.0 - */ - public function test_parse_setup_args() { - - $query = $this->query(); - $this->assertEquals( array_keys( llms_get_enrollment_statuses() ), $query->get( 'statuses' ) ); - - // ensure valid string is converted to array - $query = $this->query( array( 'statuses' => 'enrolled' ) ); - $this->assertEquals( array( 'enrolled' ), $query->get( 'statuses' ) ); - - // ensure invalid status is removed - $query = $this->query( array( 'statuses' => array( 'ooboi', 'enrolled' ) ) ); - $this->assertFalse( in_array( 'ooboi', $query->get( 'statuses' ) ) ); - - // ensure at least one status is returned - $query = $this->query( array( 'statuses' => array( 'ooboi', 'fake' ) ) ); - $this->assertGreaterThanOrEqual( 1, count( $query->get( 'statuses' ) ) ); - - } - -} diff --git a/tests/unit-tests/class.llms.test.template.functions.php b/tests/unit-tests/class.llms.test.template.functions.php deleted file mode 100644 index f01e159934..0000000000 --- a/tests/unit-tests/class.llms.test.template.functions.php +++ /dev/null @@ -1,86 +0,0 @@ -<?php -/** - * Tests for template functions - * @group LLMS_Functions_Templates - * @since 3.15.0 - * @version 3.15.0 - */ -class LLMS_Functions_Templates extends LLMS_UnitTestCase { - - private function get_output( $func, $params = array() ) { - - ob_start(); - call_user_func_array( $func, $params ); - return ob_get_clean(); - - } - - /** - * Test lifterlms_course_continue_button() func - * @return void - * @since 3.15.0 - * @version 3.15.0 - */ - public function test_lifterlms_course_continue_button() { - - global $post; - $func = 'lifterlms_course_continue_button'; - - // student to use - $student = $this->get_mock_student(); - - // course to use - $course_id = $this->generate_mock_courses()[0]; - $course = llms_get_post( $course_id ); - - // blog post to test globals against - $post_id = $this->factory->post->create( array( - 'post_title' => 'Test Post', - ) ); - - - // call function with no parameters (using only defaults) - // no student and no post set right now - $this->assertEmpty( $this->get_output( $func ) ); - - // set the global post to be a blog post - $post = get_post( $post_id ); - - // call function with no parameters (using only defaults) - // post is a blog post & no student - $this->assertEmpty( $this->get_output( $func ) ); - - // set global to be a course but still no student - $post = get_post( $course_id ); - $this->assertEmpty( $this->get_output( $func ) ); - - // set the current student (should display a continue button) - wp_set_current_user( $student->get_id() ); - - // student setup but no enrollment - $this->assertEmpty( $this->get_output( $func ) ); - - // enroll student - llms_enroll_student( $student->get_id(), $course_id ); - - // 0 progress, "Get Started" text displays in button - $this->assertTrue( ( false !== strpos( $this->get_output( $func ), 'Get Started' ) ) ); - - // Progress > 0, "Continue" text displays in button - $this->complete_courses_for_student( $student->get_id(), array( $course_id ), 85 ); - $this->assertTrue( ( false !== strpos( $this->get_output( $func ), 'Continue' ) ) ); - - // 100% progress, "Course Complete" text displays - $this->complete_courses_for_student( $student->get_id(), array( $course_id ), 100 ); - $this->assertTrue( ( false !== strpos( $this->get_output( $func ), 'Course Complete' ) ) ); - - // use a lesson, same result as last - $post = get_post( $course->get_lessons( 'ids' )[0] ); - $this->assertTrue( ( false !== strpos( $this->get_output( $func ), 'Course Complete' ) ) ); - - // reset global - $post = null; - - } - -} diff --git a/tests/unit-tests/models/class.llms.test.model.llms.coupon.php b/tests/unit-tests/models/class.llms.test.model.llms.coupon.php deleted file mode 100644 index 540b665ca2..0000000000 --- a/tests/unit-tests/models/class.llms.test.model.llms.coupon.php +++ /dev/null @@ -1,144 +0,0 @@ -<?php -/** - * Tests for LifterLMS Coupon Model - * @since 3.4.0 - * @version 3.4.0 - */ -class LLMS_Test_LLMS_Coupon extends LLMS_PostModelUnitTestCase { - - /** - * class name for the model being tested by the class - * @var string - */ - protected $class_name = 'LLMS_Coupon'; - - /** - * db post type of the model being tested - * @var string - */ - protected $post_type = 'llms_coupon'; - - /** - * Get properties, used by test_getters_setters - * This should match, exactly, the object's $properties array - * @return array - * @since 3.4.0 - * @version 3.4.0 - */ - protected function get_properties() { - return array( - 'coupon_amount' => 'float', - 'coupon_courses' => 'array', - 'coupon_membership' => 'array', - 'description' => 'string', - 'discount_type' => 'string', - 'enable_trial_discount' => 'yesno', - 'expiration_date' => 'string', - 'plan_type' => 'string', - 'trial_amount' => 'float', - 'usage_limit' => 'absint', - ); - } - - /** - * Get data to fill a create post with - * This is used by test_getters_setters - * @return array - * @since 3.4.0 - * @version 3.4.0 - */ - protected function get_data() { - return array( - 'coupon_amount' => 50, - 'coupon_courses' => array(), - 'coupon_membership' => array(), - 'description' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', - 'discount_type' => 'percent', - 'enable_trial_discount' => 'no', - 'expiration_date' => '02/17/2017', - 'plan_type' => 'any', - 'trial_amount' => 5, - 'usage_limit' => 25, - ); - } - - - /* - /$$ /$$ - | $$ | $$ - /$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$$ - |_ $$_/ /$$__ $$ /$$_____/|_ $$_/ /$$_____/ - | $$ | $$$$$$$$| $$$$$$ | $$ | $$$$$$ - | $$ /$$| $$_____/ \____ $$ | $$ /$$\____ $$ - | $$$$/| $$$$$$$ /$$$$$$$/ | $$$$//$$$$$$$/ - \___/ \_______/|_______/ \___/ |_______/ - */ - - - /** - * Test get_products() function - * @return void - * @since 3.4.0 - * @version 3.4.0 - */ - public function test_get_products() { - $this->create(); - $this->obj->set( 'coupon_courses', array( 1, 2, 3 ) ); - $this->obj->set( 'coupon_membership', array( 4, 5, 6 ) ); - $this->assertEquals( array( 1, 2, 3, 4, 5, 6 ), $this->obj->get_products() ); - } - - /** - * Test has_trial_discount() function - * @return void - * @since 3.4.0 - * @version 3.4.0 - */ - public function test_has_trial_discount() { - - $this->create(); - - // trial discount enabled - $this->obj->set( 'enable_trial_discount', 'yes' ); - $this->assertTrue( $this->obj->has_trial_discount() ); - - // trial discount not enabled - $this->obj->set( 'enable_trial_discount', 'no' ); - $this->assertFalse( $this->obj->has_trial_discount() ); - $this->obj->set( 'enable_trial_discount', '' ); - $this->assertFalse( $this->obj->has_trial_discount() ); - $this->obj->set( 'enable_trial_discount', 'string' ); - $this->assertFalse( $this->obj->has_trial_discount() ); - - } - - /** - * Test is_expired function - * @return void - * @since 3.2.2 - * @version 3.2.2 - */ - public function test_is_expired() { - - $this->create(); - - // no date set so it's not expired - $this->assertFalse( $this->obj->is_expired() ); - - // date empty, not expired - $this->obj->set( 'expiration_date', '' ); - $this->assertFalse( $this->obj->is_expired() ); - - // should be expired - llms_mock_current_time( '2016-01-02' ); - $this->obj->set( 'expiration_date', '01/01/2016' ); - $this->assertTrue( $this->obj->is_expired() ); - - // should not be expired - llms_mock_current_time( '2015-01-01' ); - $this->obj->set( 'expiration_date', '01/01/2016' ); - $this->assertFalse( $this->obj->is_expired() ); - - } - -} diff --git a/tests/unit-tests/models/class.llms.test.model.llms.course.php b/tests/unit-tests/models/class.llms.test.model.llms.course.php deleted file mode 100644 index 3a27e7a825..0000000000 --- a/tests/unit-tests/models/class.llms.test.model.llms.course.php +++ /dev/null @@ -1,357 +0,0 @@ -<?php -/** - * Tests for LifterLMS Course Model - * @group LLMS_Course - * @group LLMS_Post_Model - * @since 3.4.0 - * @version 3.17.2 - */ -class LLMS_Test_LLMS_Course extends LLMS_PostModelUnitTestCase { - - /** - * class name for the model being tested by the class - * @var string - */ - protected $class_name = 'LLMS_Course'; - - /** - * db post type of the model being tested - * @var string - */ - protected $post_type = 'course'; - - /** - * Get properties, used by test_getters_setters - * This should match, exactly, the object's $properties array - * @return array - * @since 3.4.0 - * @version 3.4.0 - */ - protected function get_properties() { - return array( - 'audio_embed' => 'text', - 'capacity' => 'absint', - 'capacity_message' => 'text', - 'course_closed_message' => 'text', - 'course_opens_message' => 'text', - 'content_restricted_message' => 'text', - 'enable_capacity' => 'yesno', - 'end_date' => 'text', - 'enrollment_closed_message' => 'text', - 'enrollment_end_date' => 'text', - 'enrollment_opens_message' => 'text', - 'enrollment_period' => 'yesno', - 'enrollment_start_date' => 'text', - 'has_prerequisite' => 'yesno', - 'length' => 'text', - 'prerequisite' => 'absint', - 'prerequisite_track' => 'absint', - 'tile_featured_video' => 'yesno', - 'time_period' => 'yesno', - 'start_date' => 'text', - 'video_embed' => 'text', - ); - } - - /** - * Get data to fill a create post with - * This is used by test_getters_setters - * @return array - * @since 3.4.0 - * @version 3.4.0 - */ - protected function get_data() { - return array( - 'audio_embed' => 'http://example.tld/audio_embed', - 'capacity' => 25, - 'capacity_message' => 'Capacity Reached', - 'course_closed_message' => 'Course has closed', - 'course_opens_message' => 'Course is not yet open', - 'content_restricted_message' => 'You cannot access this content', - 'enable_capacity' => 'yes', - 'end_date' => '2017-05-05', - 'enrollment_closed_message' => 'Enrollment is closed', - 'enrollment_end_date' => '2017-05-05', - 'enrollment_opens_message' => 'Enrollment opens later', - 'enrollment_period' => 'yes', - 'enrollment_start_date' => '2017-05-01', - 'has_prerequisite' => 'no', - 'length' => '1 year', - 'prerequisite' => 0, - 'prerequisite_track' => 0, - 'tile_featured_video' => 'yes', - 'time_period' => 'yes', - 'start_date' => '2017-05-01', - 'video_embed' => 'http://example.tld/video_embed', - ); - } - - /** - * Test Audio and Video Embeds - * @return void - * @since 3.4.0 - * @version 3.4.0 - */ - public function test_get_embeds() { - - $audio_url = 'https://open.spotify.com/track/1rNUOtuCWv1qswqsMFvzvz'; - $video_url = 'https://www.youtube.com/watch?v=MhQlNwxn5oo'; - - $course = new LLMS_Course( 'new', 'Course With Embeds' ); - - // empty string when none set - $this->assertEmpty( $course->get_audio() ); - $this->assertEmpty( $course->get_video() ); - - $course->set( 'audio_embed', $audio_url ); - $course->set( 'video_embed', $video_url ); - - $audio_embed = $course->get_audio(); - $video_embed = $course->get_video(); - - // string - $this->assertTrue( is_string( $audio_embed ) ); - $this->assertTrue( is_string( $video_embed ) ); - - // should be an iframe for valid embeds - $this->assertEquals( 0, strpos( $audio_embed, '<iframe' ) ); - $this->assertEquals( 0, strpos( $video_embed, '<iframe' ) ); - - // fallbacks should be a link to the URL - $course->set( 'audio_embed', 'http://lifterlms.com/not/embeddable' ); - $course->set( 'video_embed', 'http://lifterlms.com/not/embeddable' ); - $this->assertEquals( 0, strpos( $audio_embed, '<a' ) ); - $this->assertEquals( 0, strpos( $video_embed, '<a' ) ); - - } - - /** - * Test get percent complete from course - * @return void - * @since 3.17.2 - * @version 3.17.2 - */ - public function test_get_percent_complete() { - - $course = llms_get_post( $this->generate_mock_courses( 1, 4, 4, 0, 0 )[0] ); - $student = $this->get_mock_student(); - - $student->enroll( $course->get( 'id' ) ); - - // get student by ID - $this->assertEquals( 0, $course->get_percent_complete( $student->get( 'id' ) ) ); - - // get from current user - $this->assertEquals( 0, $course->get_percent_complete() ); - - // complete some courses - $this->complete_courses_for_student( $student->get_id(), $course->get( 'id' ), 75 ); - - // get by id - $this->assertEquals( 75, $course->get_percent_complete( $student->get( 'id' ) ) ); - - // get from current user - $this->assertEquals( 0, $course->get_percent_complete() ); - - // log the user in - wp_set_current_user( $student->get_id() ); - - // get from current user - $this->assertEquals( 75, $course->get_percent_complete() ); - - - } - - /** - * Test perequisite functions related to courses - * @return void - * @since 3.4.0 - * @version 3.7.3 - */ - public function test_get_prerequisites() { - - $course = new LLMS_Course( 'new', 'Course Name' ); - $prereq_course = new LLMS_Course( 'new', 'Course Prereq' ); - $prereq_track = wp_create_term( 'test track', 'course_track' ); - - // no prereqs - $this->assertFalse( $course->has_prerequisite( 'any' ) ); - $this->assertFalse( $course->has_prerequisite( 'course' ) ); - $this->assertFalse( $course->has_prerequisite( 'course_track' ) ); - $this->assertFalse( $course->get_prerequisite_id( 'course' ) ); - $this->assertFalse( $course->get_prerequisite_id( 'course_track' ) ); - - $course->set( 'prerequisite', $prereq_course->get( 'id' ) ); - $course->set( 'prerequisite_track', $prereq_track['term_id'] ); - - // still no prereqs - $this->assertFalse( $course->has_prerequisite( 'any' ) ); - $this->assertFalse( $course->has_prerequisite( 'course' ) ); - $this->assertFalse( $course->has_prerequisite( 'course_track' ) ); - $this->assertFalse( $course->get_prerequisite_id( 'course' ) ); - $this->assertFalse( $course->get_prerequisite_id( 'course_track' ) ); - - $course->set( 'has_prerequisite', 'yes' ); - - // have prereqs - $this->assertTrue( $course->has_prerequisite( 'any' ) ); - $this->assertTrue( $course->has_prerequisite( 'course' ) ); - $this->assertTrue( $course->has_prerequisite( 'course_track' ) ); - $this->assertEquals( $prereq_course->get( 'id' ), $course->get_prerequisite_id( 'course' ) ); - $this->assertEquals( $prereq_track['term_id'], $course->get_prerequisite_id( 'course_track' ) ); - - $course->set( 'prerequisite', 0 ); - - $this->assertTrue( $course->has_prerequisite( 'any' ) ); - $this->assertFalse( $course->has_prerequisite( 'course' ) ); - $this->assertTrue( $course->has_prerequisite( 'course_track' ) ); - $this->assertEquals( 0, $course->get_prerequisite_id( 'course' ) ); - - $course->set( 'prerequisite', 'string' ); - $this->assertFalse( $course->has_prerequisite( 'course' ) ); - $this->assertEquals( 0, $course->get_prerequisite_id( 'course' ) ); - - } - - /** - * Test the get lessons function - * @return void - * @since 3.12.0 - * @version 3.12.0 - */ - public function test_get_lessons() { - - $course = llms_get_post( $this->generate_mock_courses( 1, 2, 2, 0, 0 )[0] ); - - // get just ids - $lessons = $course->get_lessons( 'ids' ); - $this->assertEquals( 4, count( $lessons ) ); - array_map( function( $id ) { - $this->assertTrue( is_numeric( $id ) ); - }, $lessons ); - - // wp post objects - $lessons = $course->get_lessons( 'posts' ); - $this->assertEquals( 4, count( $lessons ) ); - array_map( function( $post ) { - $this->assertTrue( is_a( $post, 'WP_Post' ) ); - }, $lessons ); - - // lesson objects - $lessons = $course->get_lessons( 'lessons' ); - $this->assertEquals( 4, count( $lessons ) ); - array_map( function( $lesson ) { - $this->assertTrue( is_a( $lesson, 'LLMS_Lesson' ) ); - }, $lessons ); - - } - - /** - * Test the get quizzes function - * @return void - * @since 3.12.0 - * @version 3.12.0 - */ - public function test_get_quizzes() { - - $course = llms_get_post( $this->generate_mock_courses( 1, 1, 5, 3, 1 )[0] ); - - $quizzes = $course->get_quizzes(); - $this->assertEquals( 3, count( $quizzes ) ); - array_map( function( $id ) { - $this->assertTrue( is_numeric( $id ) ); - }, $quizzes ); - - } - - /** - * Test the get sections function - * @return void - * @since 3.12.0 - * @version 3.12.0 - */ - public function test_get_sections() { - - $course = llms_get_post( $this->generate_mock_courses( 1, 4, 0, 0, 0 )[0] ); - - // get just ids - $sections = $course->get_sections( 'ids' ); - $this->assertEquals( 4, count( $sections ) ); - array_map( function( $id ) { - $this->assertTrue( is_numeric( $id ) ); - }, $sections ); - - // wp post objects - $sections = $course->get_sections( 'posts' ); - $this->assertEquals( 4, count( $sections ) ); - array_map( function( $post ) { - $this->assertTrue( is_a( $post, 'WP_Post' ) ); - }, $sections ); - - // section objects - $sections = $course->get_sections( 'sections' ); - $this->assertEquals( 4, count( $sections ) ); - array_map( function( $section ) { - $this->assertTrue( is_a( $section, 'LLMS_Section' ) ); - }, $sections ); - - } - - /** - * Test the get students function - * @return void - * @since 3.12.0 - * @version 3.12.0 - */ - public function test_get_students() { - - $this->create(); - - $students = $this->factory->user->create_many( 10, array( 'role' => 'student' ) ); - foreach ( $students as $sid ) { - llms_enroll_student( $sid, $this->obj->get( 'id' ), 'testing' ); - } - - $this->assertEquals( 5, count( $this->obj->get_students( array( 'enrolled' ), 5 ) ) ); - $this->assertEquals( 10, count( $this->obj->get_students() ) ); - - } - - /** - * Test the has_capacity function - * @return void - * @since 3.12.0 - * @version 3.12.0 - */ - public function test_has_capacity() { - - $this->create(); - // has capacity when nothing set - $this->assertTrue( $this->obj->has_capacity() ); - - $students = $this->factory->user->create_many( 10, array( 'role' => 'student' ) ); - foreach ( $students as $sid ) { - llms_enroll_student( $sid, $this->obj->get( 'id' ), 'testing' ); - } - - // has capacity when students enrolled and nothing set - $this->assertTrue( $this->obj->has_capacity() ); - - // enabled capacity - $this->obj->set( 'enable_capacity', 'yes' ); - $this->obj->set( 'capacity', 25 ); - - // still open - $this->assertTrue( $this->obj->has_capacity() ); - - // over capacity - $this->obj->set( 'capacity', 5 ); - $this->assertFalse( $this->obj->has_capacity() ); - - // disable capacity - $this->obj->set( 'enable_capacity', 'no' ); - $this->assertTrue( $this->obj->has_capacity() ); - - } - -} diff --git a/tests/unit-tests/models/class.llms.test.model.llms.lesson.php b/tests/unit-tests/models/class.llms.test.model.llms.lesson.php deleted file mode 100644 index c8ffb4986a..0000000000 --- a/tests/unit-tests/models/class.llms.test.model.llms.lesson.php +++ /dev/null @@ -1,377 +0,0 @@ -<?php -/** - * Tests for LifterLMS Lesson Model - * @group post_models - * @group lessons - * @since 3.14.8 - * @version 3.16.11 - */ -class LLMS_Test_LLMS_Lesson extends LLMS_PostModelUnitTestCase { - - /** - * class name for the model being tested by the class - * @var string - */ - protected $class_name = 'LLMS_Lesson'; - - /** - * db post type of the model being tested - * @var string - */ - protected $post_type = 'lesson'; - - /** - * Get properties, used by test_getters_setters - * This should match, exactly, the object's $properties array - * @return array - * @since 3.14.8 - * @version 3.16.11 - */ - protected function get_properties() { - return array( - - 'order' => 'absint', - - // drippable - 'days_before_available' => 'absint', - 'date_available' => 'text', - 'drip_method' => 'text', - 'time_available' => 'text', - - // parent element - 'parent_course' => 'absint', - 'parent_section' => 'absint', - - 'audio_embed' => 'text', - 'free_lesson' => 'yesno', - 'has_prerequisite' => 'yesno', - 'prerequisite' => 'absint', - 'require_passing_grade' => 'yesno', - 'video_embed' => 'text', - - // quizzes - 'quiz' => 'absint', - 'quiz_enabled' => 'yesno', - - ); - } - - /** - * Get data to fill a create post with - * This is used by test_getters_setters - * @return array - * @since 3.14.8 - * @version 3.16.11 - */ - protected function get_data() { - return array( - 'audio_embed' => 'http://example.tld/audio_embed', - 'date_available' => '11/21/2018', - 'days_before_available' => '24', - 'drip_method' => 'date', - 'free_lesson' => 'no', - 'has_prerequisite' => 'yes', - 'order' => 1, - 'parent_course' => 85, - 'parent_section' => 32, - 'prerequisite' => 344, - 'quiz' => 123, - 'quiz_enabled' => 'yes', - 'require_passing_grade' => 'yes', - 'time_available' => '12:34 PM', - 'video_embed' => 'http://example.tld/video_embed', - ); - } - - - /* - /$$ /$$ - | $$ | $$ - /$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$$ - |_ $$_/ /$$__ $$ /$$_____/|_ $$_/ /$$_____/ - | $$ | $$$$$$$$| $$$$$$ | $$ | $$$$$$ - | $$ /$$| $$_____/ \____ $$ | $$ /$$\____ $$ - | $$$$/| $$$$$$$ /$$$$$$$/ | $$$$//$$$$$$$/ - \___/ \_______/|_______/ \___/ |_______/ - */ - - public function test_get_available_date() { - - $format = 'Y-m-d'; - - $course_id = $this->generate_mock_courses( 1, 1, 2, 0 )[0]; - $course = llms_get_post( $course_id ); - $lesson = $course->get_lessons()[0]; - $lesson_id = $lesson->get( 'id' ); - $student = $this->get_mock_student(); - wp_set_current_user( $student->get_id() ); - $student->enroll( $course_id ); - - // no drip settings, lesson is currently available - $this->assertEquals( current_time( $format ), $lesson->get_available_date( $format ) ); - - $lesson->set( 'drip_method', 'date' ); - $lesson->set( 'date_available', '12/12/2012' ); - $lesson->set( 'time_available', '12:12 AM' ); - $this->assertEquals( date( $format, strtotime( '12/12/2012' ) ), $lesson->get_available_date( $format ) ); - $this->assertEquals( date( 'U', strtotime( '12/12/2012 12:12 AM' ) ), $lesson->get_available_date( 'U' ) ); - - $lesson->set( 'drip_method', 'enrollment' ); - $lesson->set( 'days_before_available', '3' ); - $this->assertEquals( $student->get_enrollment_date( $course_id, 'enrolled', 'U' ) + ( DAY_IN_SECONDS * 3 ), $lesson->get_available_date( 'U' ) ); - - $lesson->set( 'drip_method', 'start' ); - $start = current_time( 'm/d/Y' ); - $course->set( 'start_date', $start ); - $this->assertEquals( strtotime( $start ) + ( DAY_IN_SECONDS * 3 ), $lesson->get_available_date( 'U' ) ); - - $prereq_id = $lesson_id; - $student->mark_complete( $lesson_id, 'lesson' ); - - $lesson = $course->get_lessons()[1]; - - $lesson->set( 'has_prerequisite', 'yes' ); - $lesson->set( 'prerequisite', $lesson_id ); - - $lesson->set( 'drip_method', 'prerequisite' ); - $lesson->set( 'days_before_available', '3' ); - $this->assertEquals( $student->get_completion_date( $prereq_id, 'U' ) + ( DAY_IN_SECONDS * 3 ), $lesson->get_available_date( 'U' ) ); - - } - - public function test_get_course() { - - $course = llms_get_post( $this->generate_mock_courses( 1, 1, 1, 0, 0 )[0] ); - $lesson = llms_get_post( $course->get_lessons( 'ids' )[0] ); - - // returns a course when everything's okay - $this->assertTrue( is_a( $lesson->get_course(), 'LLMS_Course' ) ); - - // course trashed / doesn't exist, returns null - wp_delete_post( $course->get( 'id' ), true ); - $this->assertNull( $lesson->get_course() ); - - } - - /** - * Test Audio and Video Embeds - * @return void - * @since 3.14.8 - * @version 3.14.8 - */ - public function test_get_embeds() { - - $audio_url = 'https://open.spotify.com/track/1rNUOtuCWv1qswqsMFvzvz'; - $video_url = 'https://www.youtube.com/watch?v=MhQlNwxn5oo'; - - $lesson = new LLMS_Lesson( 'new', 'Lesson With Embeds' ); - - // empty string when none set - $this->assertEmpty( $lesson->get_audio() ); - $this->assertEmpty( $lesson->get_video() ); - - $lesson->set( 'audio_embed', $audio_url ); - $lesson->set( 'video_embed', $video_url ); - - $audio_embed = $lesson->get_audio(); - $video_embed = $lesson->get_video(); - - // string - $this->assertTrue( is_string( $audio_embed ) ); - $this->assertTrue( is_string( $video_embed ) ); - - // should be an iframe for valid embeds - $this->assertEquals( 0, strpos( $audio_embed, '<iframe' ) ); - $this->assertEquals( 0, strpos( $video_embed, '<iframe' ) ); - - // fallbacks should be a link to the URL - $lesson->set( 'audio_embed', 'http://lifterlms.com/not/embeddable' ); - $lesson->set( 'video_embed', 'http://lifterlms.com/not/embeddable' ); - $this->assertEquals( 0, strpos( $audio_embed, '<a' ) ); - $this->assertEquals( 0, strpos( $video_embed, '<a' ) ); - - } - - public function test_get_section() { - - $course = llms_get_post( $this->generate_mock_courses( 1, 1, 1, 0, 0 )[0] ); - $lesson = llms_get_post( $course->get_lessons( 'ids' )[0] ); - - // returns a course when everything's okay - $this->assertTrue( is_a( $lesson->get_section(), 'LLMS_Section' ) ); - - // section trashed / doesn't exist, returns null - wp_delete_post( $lesson->get( 'parent_section' ), true ); - $this->assertNull( $lesson->get_section() ); - - } - - /** - * Test has_modified_slug function - * @return void - * @since 3.14.8 - * @version 3.14.8 - */ - public function test_has_modified_slug() { - - $lesson = new LLMS_Lesson( 'new', 'New Lesson' ); - - // default unmodified slug - $this->assertFalse( $lesson->has_modified_slug() ); - - // default unmodifed slug with a unique int at the end - $lesson->set( 'name', 'new-lesson-123' ); - - $this->assertFalse( $lesson->has_modified_slug() ); - - // renamed slug - $lesson->set( 'name', 'modified-slug' ); - - $this->assertTrue( $lesson->has_modified_slug() ); - - } - - public function test_is_available() { - - $course_id = $this->generate_mock_courses( 1, 1, 2, 0 )[0]; - $course = llms_get_post( $course_id ); - $lesson = $course->get_lessons()[0]; - $lesson_id = $lesson->get( 'id' ); - $student = $this->get_mock_student(); - wp_set_current_user( $student->get_id() ); - $student->enroll( $course_id ); - - // no drip settings, lesson is currently available - $this->assertTrue( $lesson->is_available() ); - - // date in past so the lesson is available - $lesson = llms_get_post( $lesson_id ); - $lesson->set( 'drip_method', 'date' ); - $lesson->set( 'date_available', '12/12/2012' ); - $lesson->set( 'time_available', '12:12 AM' ); - $this->assertTrue( $lesson->is_available() ); - - // date in future so lesson not available - $lesson->set( 'date_available', date( 'm/d/Y', current_time( 'timestamp' ) + DAY_IN_SECONDS ) ); - $this->assertFalse( $lesson->is_available() ); - - // available 3 days after enrollment - $lesson->set( 'drip_method', 'enrollment' ); - $lesson->set( 'days_before_available', '3' ); - $this->assertFalse( $lesson->is_available() ); - - // now available - llms_mock_current_time( '+4 days' ); - $this->assertTrue( $lesson->is_available() ); - - llms_reset_current_time(); - $lesson->set( 'drip_method', 'start' ); - $course->set( 'start_date', date( 'm/d/Y', current_time( 'timestamp' ) + DAY_IN_SECONDS ) ); - - // not available until 3 days after course start date - $this->assertFalse( $lesson->is_available() ); - - // now available - llms_mock_current_time( '+4 days' ); - $this->assertTrue( $lesson->is_available() ); - llms_reset_current_time(); - - $prereq_id = $lesson_id; - $student->mark_complete( $lesson_id, 'lesson' ); - - // second lesson not available until 3 days after lesson 1 is complete - $lesson = $course->get_lessons()[1]; - - $lesson->set( 'has_prerequisite', 'yes' ); - $lesson->set( 'prerequisite', $lesson_id ); - - $lesson->set( 'drip_method', 'prerequisite' ); - $lesson->set( 'days_before_available', '3' ); - - $this->assertFalse( $lesson->is_available() ); - - llms_mock_current_time( '+4 days' ); - $this->assertTrue( $lesson->is_available() ); - - } - - /** - * test the is_orphan function - * @return [type] - * @since 3.14.8 - * @version 3.14.8 - */ - public function test_is_orphan() { - - $course = llms_get_post( $this->generate_mock_courses( 1, 1, 1, 0, 0 )[0] ); - $section = llms_get_post( $course->get_sections( 'ids' )[0] ); - $lesson = llms_get_post( $course->get_lessons( 'ids' )[0] ); - - // not an orphan - $this->assertFalse( $lesson->is_orphan() ); - - $test_statuses = get_post_stati( array( '_builtin' => true ) ); - foreach ( array_keys( $test_statuses ) as $status ) { - - $assert = in_array( $status, array( 'publish', 'future', 'draft', 'pending', 'private', 'auto-draft' ) ) ? 'assertFalse' : 'assertTrue'; - - // check parent course - wp_update_post( array( - 'ID' => $course->get( 'id' ), - 'post_status' => $status, - ) ); - $this->$assert( $lesson->is_orphan() ); - wp_update_post( array( - 'ID' => $course->get( 'id' ), - 'post_status' => 'publish', - ) ); - - // check parent section - wp_update_post( array( - 'ID' => $section->get( 'id' ), - 'post_status' => $status, - ) ); - $this->$assert( $lesson->is_orphan() ); - wp_update_post( array( - 'ID' => $section->get( 'id' ), - 'post_status' => 'publish', - ) ); - - } - - // parent course doesn't exist - $lesson->set( 'parent_course', 123456789 ); - $this->assertTrue( $lesson->is_orphan() ); - $lesson->set( 'parent_course', $course->get( 'id' ) ); - - // parent section doesn't exist - $lesson->set( 'parent_section', 123456789 ); - $this->assertTrue( $lesson->is_orphan() ); - $lesson->set( 'parent_section', $section->get( 'id' ) ); - - // parent course isn't set - $lesson->set( 'parent_course', '' ); - $this->assertTrue( $lesson->is_orphan() ); - $lesson->set( 'parent_course', $course->get( 'id' ) ); - - // parent section isn't set - $lesson->set( 'parent_section', '' ); - $this->assertTrue( $lesson->is_orphan() ); - $lesson->set( 'parent_section', $section->get( 'id' ) ); - - // metakey for parent course doesn't exist - delete_post_meta( $lesson->get( 'id' ), '_llms_parent_course' ); - $this->assertTrue( $lesson->is_orphan() ); - $lesson->set( 'parent_course', $course->get( 'id' ) ); - - // metakey for parent section doesn't exist - delete_post_meta( $lesson->get( 'id' ), '_llms_parent_section' ); - $this->assertTrue( $lesson->is_orphan() ); - $lesson->set( 'parent_section', $section->get( 'id' ) ); - - // not an orphan - $this->assertFalse( $lesson->is_orphan() ); - - } - -} diff --git a/tests/unit-tests/models/class.llms.test.model.llms.order.php b/tests/unit-tests/models/class.llms.test.model.llms.order.php deleted file mode 100644 index 68f4337972..0000000000 --- a/tests/unit-tests/models/class.llms.test.model.llms.order.php +++ /dev/null @@ -1,815 +0,0 @@ -<?php -/** - * Tests for LifterLMS Course Model - * @group LLMS_Order - * @group LLMS_Post_Model - * @since 3.10.0 - * @version 3.10.0 - */ -class LLMS_Test_LLMS_Order extends LLMS_PostModelUnitTestCase { - - /** - * Consider dates equal for +/- 2 mins - * @var integer - */ - private $date_delta = 120; - - public function setUp() { - - parent::setUp(); - $this->create(); - - } - - private function mock_gateway_support( $feature ) { - - global $llms_mock_gateway_feature; - $llms_mock_gateway_feature = $feature; - - add_filter( 'llms_get_gateway_supported_features', function( $features ) { - global $llms_mock_gateway_feature; - $features[ $llms_mock_gateway_feature ] = true; - return $features; - } ); - - } - - private function get_plan( $price = 25.99, $frequency = 1, $expiration = 'lifetime', $on_sale = false, $trial = false ) { - - $course = $this->generate_mock_courses( 1 ); - $course_id = $course[0]; - - $plan = new LLMS_Access_Plan( 'new', 'Test Access Plan' ); - $plan_data = array( - 'access_expiration' => $expiration, - 'access_expires' => ( 'limited-date' === $expiration ) ? date( 'm/d/Y', current_time( 'timestamp' ) + DAY_IN_SECONDS ) : '', - 'access_length' => '1', - 'access_period' => 'year', - 'frequency' => $frequency, - 'is_free' => 'no', - 'length' => 0, - 'on_sale' => $on_sale ? 'yes' : 'no', - 'period' => 'day', - 'price' => $price, - 'product_id' => $course_id, - 'sale_price' => round( $price - ( $price * .1 ), 2 ), - 'sku' => 'accessplansku', - 'trial_length' => 1, - 'trial_offer' => $trial ? 'yes' : 'no', - 'trial_period' => 'week', - 'trial_price' => 1.00, - ); - - foreach ( $plan_data as $key => $val ) { - $plan->set( $key, $val ); - } - - return $plan; - - } - - private function get_order( $plan = null, $coupon = false ) { - - $gateway = LLMS()->payment_gateways()->get_gateway_by_id( 'manual' ); - update_option( $gateway->get_option_name( 'enabled' ), 'yes' ); - - if ( ! $plan ) { - $plan = $this->get_plan(); - } - - if ( $coupon ) { - $coupon = new LLMS_Coupon( 'new', 'couponcode' ); - $coupon_data = array( - 'coupon_amount' => 10, - 'discount_type' => 'percent', - 'plan_type' => 'any', - ); - foreach ( $coupon_data as $key => $val ) { - $coupon->set( $key, $val ); - } - } - - $order = new LLMS_Order( 'new' ); - return $order->init( $this->get_mock_student(), $plan, $gateway, $coupon ); - - } - - /** - * class name for the model being tested by the class - * @var string - */ - protected $class_name = 'LLMS_Order'; - - /** - * db post type of the model being tested - * @var string - */ - protected $post_type = 'llms_order'; - - /** - * Get properties, used by test_getters_setters - * This should match, exactly, the object's $properties array - * @return array - * @since 3.10.0 - * @version 3.10.0 - */ - protected function get_properties() { - return array( - - 'coupon_amount' => 'float', - 'coupon_amout_trial' => 'float', - 'coupon_value' => 'float', - 'coupon_value_trial' => 'float', - 'original_total' => 'float', - 'sale_price' => 'float', - 'sale_value' => 'float', - 'total' => 'float', - 'trial_original_total' => 'float', - 'trial_total' => 'float', - - 'access_length' => 'absint', - 'billing_frequency' => 'absint', - 'billing_length' => 'absint', - 'coupon_id' => 'absint', - 'plan_id' => 'absint', - 'product_id' => 'absint', - 'trial_length' => 'absint', - 'user_id' => 'absint', - - 'access_expiration' => 'text', - 'access_expires' => 'text', - 'access_period' => 'text', - 'billing_address_1' => 'text', - 'billing_address_2' => 'text', - 'billing_city' => 'text', - 'billing_country' => 'text', - 'billing_email' => 'text', - 'billing_first_name' => 'text', - 'billing_last_name' => 'text', - 'billing_state' => 'text', - 'billing_zip' => 'text', - 'billing_period' => 'text', - 'coupon_code' => 'text', - 'coupon_type' => 'text', - 'coupon_used' => 'text', - 'currency' => 'text', - 'on_sale' => 'text', - 'order_key' => 'text', - 'order_type' => 'text', - 'payment_gateway' => 'text', - 'plan_sku' => 'text', - 'plan_title' => 'text', - 'product_sku' => 'text', - 'product_type' => 'text', - 'title' => 'text', - 'gateway_api_mode' => 'text', - 'gateway_customer_id' => 'text', - 'trial_offer' => 'text', - 'trial_period' => 'text', - 'user_ip_address' => 'text', - - ); - } - - /** - * Get data to fill a create post with - * This is used by test_getters_setters - * @return array - * @since 3.10.0 - * @version 3.10.0 - */ - protected function get_data() { - return array( - - 'coupon_amount' => 1.00, - 'coupon_amout_trial' => 0.50, - 'coupon_value' => 1.00, - 'coupon_value_trial' => 1234234.00, - 'original_total' => 25.93, - 'sale_price' => 25.23, - 'sale_value' => 2325.00, - 'total' => 12325.00, - 'trial_original_total' => 25.00, - 'trial_total' => 123.43, - - 'access_length' => 1, - 'billing_frequency' => 1, - 'billing_length' => 1, - 'coupon_id' => 1, - 'plan_id' => 1, - 'product_id' => 1, - 'trial_length' => 1, - 'user_id' => 1, - - 'access_expiration' => 'text', - 'access_expires' => 'text', - 'access_period' => 'text', - 'billing_address_1' => 'text', - 'billing_address_2' => 'text', - 'billing_city' => 'text', - 'billing_country' => 'text', - 'billing_email' => 'text', - 'billing_first_name' => 'text', - 'billing_last_name' => 'text', - 'billing_state' => 'text', - 'billing_zip' => 'text', - 'billing_period' => 'text', - 'coupon_code' => 'text', - 'coupon_type' => 'text', - 'coupon_used' => 'text', - 'currency' => 'text', - 'on_sale' => 'text', - 'order_key' => 'text', - 'order_type' => 'text', - 'payment_gateway' => 'text', - 'plan_sku' => 'text', - 'plan_title' => 'text', - 'product_sku' => 'text', - 'product_type' => 'text', - 'title' => 'test title', - 'gateway_api_mode' => 'text', - 'gateway_customer_id' => 'text', - 'trial_offer' => 'text', - 'trial_period' => 'text', - 'user_ip_address' => 'text', - - ); - } - - /** - * Test the add_note() method - * @return [type] [description] - * @since 3.10.0 - * @version 3.10.0 - */ - public function test_add_note() { - - // don't create empty notes - $this->assertNull( $this->obj->add_note( '' ) ); - - $note_text = 'This is an order note'; - $id = $this->obj->add_note( $note_text ); - - // should return the comment id - $this->assertTrue( is_numeric( $id ) ); - - $note = get_comment( $id ); - - // should be a comment - $this->assertTrue( is_a( $note, 'WP_Comment' ) ); - - // comment content should be our orignal note - $this->assertEquals( $note->comment_content, $note_text ); - // author should be the system (LifterLMS) - $this->assertEquals( $note->comment_author, 'LifterLMS' ); - - // create a new note by a user - $id = $this->obj->add_note( $note_text, true ); - $note = get_comment( $id ); - $this->assertEquals( get_current_user_id(), $note->user_id ); - - // 1 for original creation note, 2 for our test notes - $this->assertEquals( 3, did_action( 'llms_new_order_note_added' ) ); - - } - - public function test_can_be_retried() { - - $order = $this->get_order(); - - // pending order can't be retried - $this->assertFalse( $order->can_be_retried() ); - - // active can be retried - $order->set_status( 'llms-active' ); - - // gateway doesn't support retries - $this->assertFalse( $order->can_be_retried() ); - - // allow the gateway to support retries - $this->mock_gateway_support( 'recurring_retry' ); - - // can be retried now - $this->assertTrue( $order->can_be_retried() ); - - // on hold can be retried - $order->set_status( 'llms-on-hold' ); - $this->assertTrue( $order->can_be_retried() ); - - } - - /** - * Test the generate_order_key() method - * @return [type] [description] - * @since 3.10.0 - * @version 3.10.0 - */ - public function test_generate_order_key() { - - $this->assertTrue( is_string( $this->obj->generate_order_key() ) ); - $this->assertEquals( 0, strpos( $this->obj->generate_order_key(), 'order-' ) ); - - } - - /** - * Test the get_access_expiration_date() method - * @return [type] [description] - * @since 3.10.0 - * @version 3.10.0 - */ - public function test_get_access_expiration_date() { - - // lifetime responds with a string not a date - $this->obj->set( 'access_expiration', 'lifetime' ); - $this->assertEquals( 'Lifetime Access', $this->obj->get_access_expiration_date() ); - - // expires on a specific datae - $this->obj->set( 'access_expiration', 'limited-date' ); - $this->obj->set( 'access_expires', '12/01/2020' ); // m/d/Y format (from datepicker) - $this->assertEquals( '2020-12-01', $this->obj->get_access_expiration_date() ); - - - // expires after a period of time - $this->obj->set( 'access_expiration', 'limited-period' ); - - $tests = array( - array( - 'start' => '05/25/2015', - 'length' => '1', - 'period' => 'week', - 'expect' => '06/01/2015', - ), - array( - 'start' => '12/21/2017', - 'length' => '1', - 'period' => 'day', - 'expect' => '12/22/2017', - ), - array( - 'start' => '02/05/2017', - 'length' => '1', - 'period' => 'year', - 'expect' => '02/05/2018', - ), - array( - 'start' => '12/31/2017', - 'length' => '1', - 'period' => 'day', - 'expect' => '01/01/2018', - ), - array( - 'start' => '05/01/2017', - 'length' => '2', - 'period' => 'month', - 'expect' => '07/01/2017', - ), - ); - - foreach ( $tests as $data ) { - - $this->obj->set( 'start_date', $data['start'] ); - $this->obj->set( 'access_length', $data['length'] ); - $this->obj->set( 'access_period', $data['period'] ); - $this->assertEquals( date_i18n( 'Y-m-d', strtotime( $data['expect'] ) ), $this->obj->get_access_expiration_date() ); - - } - - } - - public function test_get_access_status() { - - $this->assertEquals( 'inactive', $this->obj->get_access_status() ); - - $this->obj->set( 'status', 'llms-completed' ); - $this->obj->set( 'access_expiration', 'lifetime' ); - $this->assertEquals( 'active', $this->obj->get_access_status() ); - - // past should still grant access - llms_mock_current_time( '2010-05-05' ); - $this->assertEquals( 'active', $this->obj->get_access_status() ); - - // future should still grant access - llms_mock_current_time( '2525-05-05' ); - $this->assertEquals( 'active', $this->obj->get_access_status() ); - - - // check limited access by date - $this->obj->set( 'access_expiration', 'limited-date' ); - $tests = array( - array( - 'now' => '2010-05-05', - 'expires' => '05/06/2010', // m/d/Y from datepicker - 'expect' => 'active', - ), - array( - 'now' => '2015-05-05', - 'expires' => '05/06/2010', // m/d/Y from datepicker - 'expect' => 'expired', - ), - array( - 'now' => '2010-05-05', - 'expires' => '05/05/2010', // m/d/Y from datepicker - 'expect' => 'active', - ), - array( - 'now' => '2010-05-06', - 'expires' => '05/05/2010', // m/d/Y from datepicker - 'expect' => 'expired', - ), - ); - - foreach ( $tests as $data ) { - llms_mock_current_time( $data['now'] ); - $this->obj->set( 'access_expires', $data['expires'] ); - $this->assertEquals( $data['expect'], $this->obj->get_access_status() ); - if ( 'active' === $data['expect'] ) { - $this->assertTrue( $this->obj->has_access() ); - } else { - $this->assertFalse( $this->obj->has_access() ); - } - } - - } - - // public function test_get_coupon_amount() {} - - public function test_get_customer_name() { - $first = 'Jeffrey'; - $last = 'Lebowski'; - $this->obj->set( 'billing_first_name', $first ); - $this->obj->set( 'billing_last_name', $last ); - $this->assertEquals( $first . ' ' . $last, $this->obj->get_customer_name() ); - } - - public function test_get_gateway() { - - // gateway doesn't exist - $this->obj->set( 'payment_gateway', 'garbage' ); - $this->assertTrue( is_a( $this->obj->get_gateway(), 'WP_Error' ) ); - - $manual = LLMS()->payment_gateways()->get_gateway_by_id( 'manual' ); - $this->obj->set( 'payment_gateway', 'manual' ); - - // real gateway that's not enabled - update_option( $manual->get_option_name( 'enabled' ), 'no' ); - $this->assertTrue( is_a( $this->obj->get_gateway(), 'WP_Error' ) ); - - // enabled gateway responds with the gateway instance - update_option( $manual->get_option_name( 'enabled' ), 'yes' ); - $this->assertTrue( is_a( $this->obj->get_gateway(), 'LLMS_Payment_Gateway_Manual' ) ); - - } - - public function test_get_initial_price() { - - // no trial - $order = $this->get_order(); - $this->assertEquals( 25.99, $order->get_initial_price( array(), 'float' ) ); - - // with trial - $trial_plan = $this->get_plan( 25.99, 1, 'lifetime', false, true ); - $order = $this->get_order( $trial_plan ); - $this->assertEquals( 1.00, $order->get_initial_price( array(), 'float' ) ); - - } - - public function test_get_notes() { - - $i = 1; - while( $i <= 10 ) { - - $this->obj->add_note( sprintf( 'note %d', $i ) ); - $i++; - - } - - // remove filter so we can test order notes - remove_filter( 'comments_clauses', array( 'LLMS_Comments', 'exclude_order_comments' ) ); - - $notes = $this->obj->get_notes( 1, 1 ); - - $this->assertCount( 1, $notes ); - $this->assertTrue( is_a( $notes[0], 'WP_Comment' ) ); - - $notes_p_1 = $this->obj->get_notes( 5, 1 ); - $notes_p_2 = $this->obj->get_notes( 5, 2 ); - $this->assertCount( 5, $notes_p_1 ); - $this->assertCount( 5, $notes_p_2 ); - $this->assertTrue( $notes_p_2 !== $notes_p_1 ); - - add_filter( 'comments_clauses', array( 'LLMS_Comments', 'exclude_order_comments' ) ); - - } - - public function test_get_product() { - - $course = new LLMS_Course( 'new' ); - - $this->obj->set( 'product_id', $course->get( 'id' ) ); - $this->assertTrue( is_a( $this->obj->get_product(), 'LLMS_Course' ) ); - - } - - // public function test_get_last_transaction() {} - - // public function test_get_last_transaction_date() {} - - public function test_get_next_payment_due_date() { - - // one-time payments - $plan = $this->get_plan( 25.99, 0 ); - $order = $this->get_order( $plan ); - $this->assertTrue( is_a( $order->get_next_payment_due_date(), 'WP_Error' ) ); - - - $original_time = current_time( 'Y-m-d H:i:s' ); - // recurring - $plan = $this->get_plan(); - foreach ( array( 'day', 'week', 'month', 'year' ) as $period ) { - - llms_mock_current_time( $original_time ); - - $plan->set( 'period', $period ); - - // test due date with a trial - $plan->set( 'trial_offer', 'yes' ); - $order = $this->get_order( $plan ); - $this->assertEquals( strtotime( $order->get_trial_end_date() ), strtotime( $order->get_next_payment_due_date() ), '', $this->date_delta ); - $plan->set( 'trial_offer', 'no' ); - - // perform calculation tests against different frequencies - $i = 1; - while ( $i <= 3 ) { - - $plan->set( 'frequency', $i ); - - $order = $this->get_order( $plan ); - - $expect = strtotime( "+{$i} {$period}", $order->get_date( 'date', 'U' ) ); - $this->assertEquals( $expect, $order->get_next_payment_due_date( 'U') ); - - // time travel a bit and recalculate the time - llms_mock_current_time( date( 'Y-m-d H:i:s', $expect + HOUR_IN_SECONDS * 2 ) ); - $future_expect = strtotime( "+{$i} {$period}", $expect ); - - // this will calculate the next payment date based off of the saved next payment date (which is now in the past) - $order->maybe_schedule_payment( true ); - $this->assertEquals( $future_expect, $order->get_next_payment_due_date( 'U' ) ); - - // recalculate off a transaction -- this is the fallback for pre 3.10 orders - // occurs only when no date_next_payment is set - $order->set( 'date_next_payment', '' ); - $order->record_transaction( array( - 'amount' => 25.99, - 'completed_date' => $original_time, - 'status' => 'llms-txn-succeeded', - 'payment_type' => 'recurring', - ) ); - $order->maybe_schedule_payment( true ); - - $this->assertEquals( strtotime( date( 'Y-m-d H:i', $future_expect ) ), strtotime( $order->get_next_payment_due_date( 'Y-m-d H:i' ) ), '', $this->date_delta ); - - // plan ends so func should return a WP_Error - $order->set( 'date_billing_end', date( 'Y-m-d H:i:s', $future_expect - DAY_IN_SECONDS ) ); - $order->maybe_schedule_payment( true ); - $this->assertTrue( is_a( $order->get_next_payment_due_date(), 'WP_Error' ) ); - $order->set( 'date_billing_end', 0 ); - - $i++; - - } - - } - - } - - // public function test_get_transaction_total() {} - - // public function test_get_start_date() {} - - // public function test_get_transactions() {} - - public function test_get_trial_end_date() { - - $this->obj->set( 'order_type', 'recurring' ); - - // no trial so false for end date - $this->assertEmpty( $this->obj->get_trial_end_date() ); - - // enable trial - $this->obj->set( 'trial_offer', 'yes' ); - $start = $this->obj->get_start_date( 'U' ); - - // when the date is saved the getter shouldn't calculate a new date and should return the saved date - $set = '2017-05-05 13:42:19'; - $this->obj->set( 'date_trial_end', $set ); - $this->assertEquals( $set, $this->obj->get_trial_end_date() ); - $this->obj->set( 'date_trial_end', '' ); - - // run a bunch of tests testing the dynamic calculations for various periods and whatever... - foreach ( array( 'day', 'week', 'month', 'year' ) as $period ) { - - $this->obj->set( 'trial_period', $period ); - $i = 1; - while ( $i <= 3 ) { - - llms_mock_current_time( date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ) ); - - $this->obj->set( 'trial_length', $i ); - $expect = strtotime( '+' . $i . ' ' . $period, $start ); - $this->assertEquals( $expect, $this->obj->get_trial_end_date( 'U' ) ); - - // trial is not over - $this->assertFalse( $this->obj->has_trial_ended() ); - - // change date to future - llms_mock_current_time( date( 'Y-m-d H:i:s', $this->obj->get_trial_end_date( 'U' ) + HOUR_IN_SECONDS ) ); - $this->assertTrue( $this->obj->has_trial_ended() ); - - $i++; - - } - - } - - } - - // public function test_get_revenue() {} - - public function test_has_coupon() { - - $this->obj->set( 'coupon_used', 'whatarst' ); - $this->assertFalse( $this->obj->has_coupon() ); - - $this->obj->set( 'coupon_used', 'no' ); - $this->assertFalse( $this->obj->has_coupon() ); - - $this->obj->set( 'coupon_used', '' ); - $this->assertFalse( $this->obj->has_coupon() ); - - $this->obj->set( 'coupon_used', 'yes' ); - $this->assertTrue( $this->obj->has_coupon() ); - - } - - public function test_has_discount() { - - $this->obj->set( 'coupon_used', 'yes' ); - $this->assertTrue( $this->obj->has_discount() ); - - $this->obj->set( 'coupon_used', 'no' ); - $this->assertFalse( $this->obj->has_discount() ); - - $this->obj->set( 'on_sale', 'yes' ); - $this->assertTrue( $this->obj->has_discount() ); - - $this->obj->set( 'on_sale', 'no' ); - $this->assertFalse( $this->obj->has_discount() ); - - } - - public function test_has_sale() { - - $this->obj->set( 'on_sale', 'whatarst' ); - $this->assertFalse( $this->obj->has_sale() ); - - $this->obj->set( 'on_sale', 'no' ); - $this->assertFalse( $this->obj->has_sale() ); - - $this->obj->set( 'on_sale', '' ); - $this->assertFalse( $this->obj->has_sale() ); - - $this->obj->set( 'on_sale', 'yes' ); - $this->assertTrue( $this->obj->has_sale() ); - - } - - // public function test_has_scheduled_payment() {} - - public function test_has_trial() { - - $this->obj->set( 'order_type', 'recurring' ); - - $this->obj->set( 'trial_offer', 'whatarst' ); - $this->assertFalse( $this->obj->has_trial() ); - - $this->obj->set( 'trial_offer', 'no' ); - $this->assertFalse( $this->obj->has_trial() ); - - $this->obj->set( 'trial_offer', '' ); - $this->assertFalse( $this->obj->has_trial() ); - - $this->obj->set( 'trial_offer', 'yes' ); - $this->assertTrue( $this->obj->has_trial() ); - - } - - public function test_init() { - - // test initialization of a trial - $plan = $this->get_plan( 25.99, 1, 'lifetime', false, true ); - $order = $this->get_order( $plan ); - - $this->assertTrue( $order->has_trial() ); - $this->assertNotEmpty( $order->get( 'date_trial_end' ) ); - - - // test initialization of an order with a plan that ends - $plan = $this->get_plan(); - $plan->set( 'length', 5 ); - $order = $this->get_order( $plan ); - $this->assertNotEmpty( $order->get( 'date_billing_end' ) ); - - } - - public function test_is_recurring() { - - $this->assertFalse( $this->obj->is_recurring() ); - $this->obj->set( 'order_type', 'recurring' ); - $this->assertTrue( $this->obj->is_recurring() ); - - } - - // public function test_maybe_schedule_payment() {} - public function test_maybe_schedule_retry() { - - $this->mock_gateway_support( 'recurring_retry' ); - - $order = $this->get_order(); - $order->set_status( 'on-hold' ); - - $i = 1; - while ( $i <= 5 ) { - - $original_next_date = $order->get_next_payment_due_date( 'U' ); - - $txn = $order->record_transaction( array( - 'amount' => 25.99, - 'status' => 'llms-txn-pending', - 'payment_type' => 'recurring', - ) ); - $txn->set( 'status', 'llms-txn-failed' ); - - $order = llms_get_post( $order->get( 'id' ) ); - - if ( $i <= 4 ) { - - $this->assertEquals( $i, did_action( 'llms_automatic_payment_retry_scheduled' ) ); - $this->assertEquals( $i - 1, $order->get( 'last_retry_rule' ) ); - $this->assertNotEquals( $original_next_date, $order->get_next_payment_due_date( 'U' ) ); - - } else { - - $this->assertEquals( 1, did_action( 'llms_automatic_payment_maximum_retries_reached' ) ); - $this->assertEquals( '', $order->get( 'last_retry_rule' ) ); - $this->assertEquals( 'llms-failed', $order->get( 'status' ) ); - - } - - - $i++; - - } - - } - - public function test_record_transaction() { - - $order = $this->get_order(); - $txn = $order->record_transaction( array( - 'amount' => 25.99, - 'status' => 'llms-txn-succeeded', - 'payment_type' => 'recurring', - ) ); - $this->assertTrue( is_a( $txn, 'LLMS_Transaction' ) ); - $order = llms_get_post( $order->get( 'id' ) ); - $this->assertEquals( 'llms-active', $order->get( 'status' ) ); - $this->assertEquals( 1, did_action( 'lifterlms_transaction_status_succeeded' ) ); - $this->assertEquals( 1, did_action( 'lifterlms_order_status_active' ) ); - - } - - public function test_set_status() { - - $this->obj->set_status( 'fakestatus' ); - $this->assertNotEquals( 'fakestatus', $this->obj->get( 'status' ) ); - - $this->obj->set( 'order_type', 'single' ); - foreach ( array_keys( llms_get_order_statuses( 'single' ) ) as $status ) { - - $this->obj->set_status( $status ); - $this->assertEquals( $status, $this->obj->get( 'status' ) ); - - $unprefixed = str_replace( 'llms-', '', $status ); - $this->obj->set_status( $unprefixed ); - $this->assertEquals( $status, $this->obj->get( 'status' ) ); - - } - - } - - // public function test_start_access() {} - - // public function test_unschedule_recurring_payment() {} - -} diff --git a/tests/unit-tests/models/class.llms.test.model.llms.questions.php b/tests/unit-tests/models/class.llms.test.model.llms.questions.php deleted file mode 100644 index 7763f89bac..0000000000 --- a/tests/unit-tests/models/class.llms.test.model.llms.questions.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php -/** - * Tests for LifterLMS Quiz Model - * @group post_models - * @group quizzes - * @group questions - * @since 3.16.12 - * @version 3.16.12 - */ -class LLMS_Test_LLMS_Question extends LLMS_PostModelUnitTestCase { - - /** - * class name for the model being tested by the class - * @var string - */ - protected $class_name = 'LLMS_Question'; - - /** - * db post type of the model being tested - * @var string - */ - protected $post_type = 'llms_question'; - - /** - * Get properties, used by test_getters_setters - * This should match, exactly, the object's $properties array - * @return array - * @since 3.16.12 - * @version 3.16.12 - */ - protected function get_properties() { - return array( - 'clarifications' => 'html', - 'clarifications_enabled' => 'yesno', - 'description_enabled' => 'yesno', - // 'image' => 'array', - 'multi_choices' => 'yesno', - 'parent_id' => 'absint', - 'points' => 'absint', - 'question_type' => 'string', - 'title' => 'html', - 'video_enabled' => 'yesno', - 'video_src' => 'string', - ); - } - - /** - * Get data to fill a create post with - * This is used by test_getters_setters - * @return array - * @since 3.16.12 - * @version 3.16.12 - */ - protected function get_data() { - return array( - 'clarifications' => '<p>this is <b>a</b> clarification</p>', - 'clarifications_enabled' => 'yes', - 'description_enabled' => 'yes', - // 'image' => 'array', - 'multi_choices' => 'no', - 'parent_id' => 123, - 'points' => 3, - 'question_type' => 'choice', - 'title' => 'this <b>is</b> <i>a</i> question', - 'video_enabled' => 'yes', - 'video_src' => 'http://example.tld/video_embed', - ); - } - - - public function test_has_description() { - - $this->create( 'title' ); - $this->assertFalse( $this->obj->has_description() ); - - $this->obj->set( 'content', 'arstarst' ); - $this->assertFalse( $this->obj->has_description() ); - - $this->obj->set( 'description_enabled', 'yes' ); - $this->assertTrue( $this->obj->has_description() ); - - $this->obj->set( 'content', '' ); - $this->assertFalse( $this->obj->has_description() ); - - } - - public function test_has_video() { - - $this->create( 'title' ); - $this->assertFalse( $this->obj->has_video() ); - - $this->obj->set( 'video_src', 'http://example.tld/video_embed' ); - $this->assertFalse( $this->obj->has_video() ); - - $this->obj->set( 'video_enabled', 'yes' ); - $this->assertTrue( $this->obj->has_video() ); - - $this->obj->set( 'video_src', '' ); - $this->assertFalse( $this->obj->has_video() ); - - } - -} diff --git a/tests/unit-tests/models/class.llms.test.model.llms.quiz.php b/tests/unit-tests/models/class.llms.test.model.llms.quiz.php deleted file mode 100644 index 4a1fc9ae46..0000000000 --- a/tests/unit-tests/models/class.llms.test.model.llms.quiz.php +++ /dev/null @@ -1,138 +0,0 @@ -<?php -/** - * Tests for LifterLMS Quiz Model - * @group post_models - * @group quizzes - * @group quiz - * @since 3.16.0 - * @version 3.16.0 - */ -class LLMS_Test_LLMS_Quiz extends LLMS_PostModelUnitTestCase { - - /** - * class name for the model being tested by the class - * @var string - */ - protected $class_name = 'LLMS_Quiz'; - - /** - * db post type of the model being tested - * @var string - */ - protected $post_type = 'llms_quiz'; - - /** - * Get properties, used by test_getters_setters - * This should match, exactly, the object's $properties array - * @return array - * @since 3.14.8 - * @version 3.14.8 - */ - protected function get_properties() { - return array( - 'lesson_id' => 'absint', - ); - } - - /** - * Get data to fill a create post with - * This is used by test_getters_setters - * @return array - * @since 3.14.8 - * @version 3.14.8 - */ - protected function get_data() { - return array( - 'lesson_id' => 123, - ); - } - - - - public function test_create_question() { - - $this->create( 'test title' ); - $this->assertTrue( is_numeric( $this->obj->questions()->create_question() ) ); - - } - - public function test_delete_question() { - - $this->create( 'test title' ); - $qid = $this->obj->questions()->create_question(); - $this->assertTrue( $this->obj->questions()->delete_question( $qid ) ); - - // belongs to another quiz, can't delete - $this->create( 'second question' ); - $this->assertFalse( $this->obj->questions()->delete_question( $qid ) ); - - // doesn't exist - $this->assertFalse( $this->obj->questions()->delete_question( 999999999 ) ); - - } - - public function test_get_question() { - - $this->create( 'test title' ); - $qid = $this->obj->questions()->create_question(); - $this->assertTrue( is_a( $this->obj->questions()->get_question( $qid ), 'LLMS_Question' ) ); - - // question doesn't belong to quiz so it should return false - $this->create( 'second question' ); - $this->assertFalse( $this->obj->questions()->get_question( $qid ) ); - - // question doesn't exist - $this->assertFalse( $this->obj->questions()->get_question( 9999999 ) ); - - } - - public function test_get_questions() { - - $this->create( 'test title' ); - $i = 1; - while( $i <= 3 ) { - $this->obj->questions()->create_question(); - $i++; - } - - // check default 'questions' - $questions = $this->obj->get_questions(); - $this->assertEquals( 3, count( $questions ) ); - foreach ( $questions as $question ) { - $this->assertInstanceOf( 'LLMS_Question', $question ); - } - - // check posts return - $questions = $this->obj->get_questions( 'posts' ); - $this->assertEquals( 3, count( $questions ) ); - foreach ( $questions as $question ) { - $this->assertInstanceOf( 'WP_Post', $question ); - } - - // check id return - $questions = $this->obj->get_questions( 'ids' ); - $this->assertEquals( 3, count( $questions ) ); - foreach ( $questions as $question ) { - $this->assertTrue( is_numeric( $question ) ); - } - - } - - public function test_update_question() { - - $this->create( 'test title' ); - - // create when no id supplied - $id = $this->obj->questions()->update_question(); - $this->assertTrue( is_numeric( $id ) ); - - // update should return it's own id - $this->assertEquals( $id, $this->obj->questions()->update_question( array( 'id' => $id ) ) ); - - // can't update from another quiz - $this->create( 'second question' ); - $this->assertFalse( $this->obj->questions()->update_question( array( 'id' => $id ) ) ); - - } - -} diff --git a/tests/unit-tests/notifications/class.llms.test.notification.achievement.earned.php b/tests/unit-tests/notifications/class.llms.test.notification.achievement.earned.php deleted file mode 100644 index 6774d4e123..0000000000 --- a/tests/unit-tests/notifications/class.llms.test.notification.achievement.earned.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php -/** - * LLMS_Notification Achievement Earned - */ - -class LLMS_Test_Notification_Achievement_Earned extends LLMS_NotificationTestCase { - - protected $notification_id = 'achievement_earned'; - -} diff --git a/tests/unit-tests/notifications/class.llms.test.notifications.php b/tests/unit-tests/notifications/class.llms.test.notifications.php deleted file mode 100644 index 92b1b54326..0000000000 --- a/tests/unit-tests/notifications/class.llms.test.notifications.php +++ /dev/null @@ -1,96 +0,0 @@ -<?php -/** - * LLMS_Notifications Tests - */ - -class LLMS_Test_Notifications extends LLMS_UnitTestCase { - - // public function test_dispatch_processors() {} - - /** - * Test the get_controller() method - * @return void - * @since 3.8.0 - * @version 3.8.0 - */ - public function test_get_controller() { - - $main = LLMS()->notifications(); - - // return the controller instance - $this->assertTrue( is_a( $main->get_controller( 'lesson_complete' ), 'LLMS_Notification_Controller_Lesson_Complete' ) ); - - // return false - $this->assertFalse( $main->get_controller( 'thisisveryveryfake' ) ); - - } - - /** - * Test get_controllers() method - * @return void - * @since 3.8.0 - * @version 3.8.0 - */ - public function test_get_controllers() { - - $main = LLMS()->notifications(); - - // should always return an array - $this->assertTrue( is_array( $main->get_controllers() ) ); - - // each item in the array must extend the controller abstract - foreach ( $main->get_controllers() as $controller ) { - $this->assertTrue( is_subclass_of( $controller, 'LLMS_Abstract_Notification_Controller' ) ); - } - - } - - /** - * Test get_processor() method - * @return void - * @since 3.8.0 - * @version 3.8.0 - */ - public function test_get_processor() { - - $main = LLMS()->notifications(); - - // return the controller instance - $this->assertTrue( is_a( $main->get_processor( 'email' ), 'LLMS_Notification_Processor_Email' ) ); - - // return false - $this->assertFalse( $main->get_processor( 'thisisveryveryfake' ) ); - - } - - /** - * test get_processors() method - * @return void - * @since 3.8.0 - * @version 3.8.0 - */ - public function test_get_processors() { - - $main = LLMS()->notifications(); - - // should always return an array - $this->assertTrue( is_array( $main->get_processors() ) ); - - // each item in the array must extend the processor abstract - foreach ( $main->get_processors() as $processor ) { - $this->assertTrue( is_subclass_of( $processor, 'LLMS_Abstract_Notification_Processor' ) ); - } - - } - - // public function get_view( $notification ) {} - - // public function load_controller( $trigger, $path = null ) {} - - // public function load_processor( $type, $path = null ) {} - - // public function load_view( $trigger, $path = null ) {} - - // public function schedule_processing( $type ) {} - -} diff --git a/tests/unit-tests/user/class.llms.test.abstract.student.data.php b/tests/unit-tests/user/class.llms.test.abstract.student.data.php deleted file mode 100644 index 8368f851e1..0000000000 --- a/tests/unit-tests/user/class.llms.test.abstract.student.data.php +++ /dev/null @@ -1,94 +0,0 @@ -<?php -/** - * Tests for LLMS_Abstract_User_Data - * @group LLMS_Student - * @since 3.9.0 - * @version 3.9.0 - */ -class LLMS_Test_Abstract_User_Data extends LLMS_UnitTestCase { - - /** - * Test exists funciton - * @return void - * @since 3.9.0 - * @version 3.9.0 - */ - public function text_exists() { - - $uid = $this->factory->user->create(); - - $student = new LLMS_Student( $uid ); - $this->assertTrue( $student->exists() ); - - $fake_student = new LLMS_Student( $uid + 1 ); - $this->assertFalse( $fake_student->exists() ); - - } - - /** - * test get_id method - * @return [type] [description] - * @since 3.9.0 - * @version 3.9.0 - */ - public function test_get_id() { - - $uid = $this->factory->user->create(); - $student = new LLMS_Student( $uid ); - $this->assertEquals( $uid, $student->get_id() ); - - } - - /** - * test get_user method - * @return [type] [description] - * @since 3.9.0 - * @version 3.9.0 - */ - public function test_get_user() { - - $uid = $this->factory->user->create(); - $student = new LLMS_Student( $uid ); - $this->assertTrue( is_a( $student->get_user(), 'WP_User' ) ); - - } - - /** - * Test Student Getters and Setters - * @return void - * @since 3.9.0 - * @version 3.9.0 - */ - public function test_getters_setters() { - - $uid = $this->factory->user->create( array( 'role' => 'student' ) ); - $user = new WP_User( $uid ); - $student = new LLMS_Student( $uid ); - - // test some core prefixed stuff from the usermeta table - $student->set( 'first_name', 'Student' ); - $student->set( 'last_name', 'McStudentFace' ); - $this->assertEquals( get_user_meta( $uid, 'first_name', true ), $student->get( 'first_name' ) ); - $this->assertEquals( get_user_meta( $uid, 'last_name', true ), $student->get( 'last_name' ) ); - - // stuff from the user table - $this->assertEquals( $user->user_email, $student->get( 'user_email' ) ); - - // llms custom user meta - $student->set( 'billing_address', '123 Student Place' ); - $this->assertEquals( get_user_meta( $uid, 'llms_billing_address', true ), $student->get( 'billing_address' ) ); - - // don't prefix - $student->set( 'this_is_third_party', '123456', false ); - add_filter( 'llms_student_unprefixed_metas', function( $metas ) { - $metas[] = 'this_is_third_party'; - return $metas; - } ); - $this->assertEquals( get_user_meta( $uid, 'this_is_third_party', true ), $student->get( 'this_is_third_party' ) ); - - } - - - - -} diff --git a/tests/unit-tests/user/class.llms.test.functions.person.php b/tests/unit-tests/user/class.llms.test.functions.person.php deleted file mode 100644 index c20bd5c5b7..0000000000 --- a/tests/unit-tests/user/class.llms.test.functions.person.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php -/** - * Tests for LifterLMS Core Functions - * @group LLMS_Student - * @since 3.7.0 - * @version 3.9.0 - */ -class LLMS_Test_Functions_Person extends LLMS_UnitTestCase { - - /** - * Test llms_can_user_bypass_restrictions() - * @return void - * @since 3.8.0 - * @version 3.8.0 - */ - public function test_llms_can_user_bypass_restrictions() { - - // allow admins to bypass - update_option( 'llms_grant_site_access', array( 'administrator' ) ); - - $admin = $this->factory->user->create( array( 'role' => 'administrator' ) ); - $student = $this->factory->user->create( array( 'role' => 'student' ) ); - - $this->assertTrue( llms_can_user_bypass_restrictions( $admin ) ); - $this->assertFalse( llms_can_user_bypass_restrictions( $student ) ); - - $this->assertFalse( llms_can_user_bypass_restrictions( 'fake' ) ); - - // pass in a student - $this->assertTrue( llms_can_user_bypass_restrictions( $admin ) ); - - // should still work with two roles - update_option( 'llms_grant_site_access', array( 'administrator', 'editor' ) ); - $this->assertTrue( llms_can_user_bypass_restrictions( $admin ) ); - - } - - /** - * Test llms_get_student - * @return void - * @since 3.9.0 - * @version 3.9.0 - */ - public function test_llms_get_student() { - - $uid = $this->factory->user->create(); - - $this->assertTrue( is_a( llms_get_student( $uid ), 'LLMS_Student' ) ); - $this->assertTrue( is_a( llms_get_student( new WP_User( $uid ) ), 'LLMS_Student' ) ); - $this->assertTrue( is_a( llms_get_student( new LLMS_Student( $uid ) ), 'LLMS_Student' ) ); - - $this->assertFalse( is_a( llms_get_student( $uid + 1 ), 'LLMS_Student' ) ); - $this->assertFalse( is_a( llms_get_student( 'string' ), 'LLMS_Student' ) ); - - } - -} diff --git a/tests/unit-tests/user/class.llms.test.student.php b/tests/unit-tests/user/class.llms.test.student.php deleted file mode 100644 index 74866cb612..0000000000 --- a/tests/unit-tests/user/class.llms.test.student.php +++ /dev/null @@ -1,396 +0,0 @@ -<?php -/** - * Tests for LifterLMS Student Functions - * @group LLMS_Student - * @since 3.5.0 - * @version 3.17.0 - */ -class LLMS_Test_Student extends LLMS_UnitTestCase { - - /** - * Test mark_complete() and mark_incomplete() on a tracks, courses, sections, and lessons - * - * @return void - * @since 3.5.0 - * @version 3.17.0 - */ - public function test_completion_incompletion() { - - $courses = $this->generate_mock_courses( 3, 3, 3, 0 ); - $student = $this->factory->user->create( array( 'role' => 'student' ) ); - $track = wp_insert_term( 'test track', 'course_track' ); - - // nothing completed - foreach ( $courses as $c_i => $cid ) { - - wp_set_object_terms( $cid, array( $track['term_id'] ), 'course_track', false ); - - $this->assertFalse( llms_is_complete( $student, $cid, 'course' ) ); - - // check sections - $course = llms_get_post( $cid ); - foreach ( $course->get_sections( 'ids' ) as $s_i => $sid ) { - - // no data recorded - $this->assertFalse( llms_is_complete( $student, $sid, 'section' ) ); - - // check lessons - $section = llms_get_post( $sid ); - foreach ( $section->get_lessons( 'ids' ) as $l_i => $lid ) { - - // no data recorded (incomplete) - $this->assertFalse( llms_is_complete( $student, $sid, 'lesson' ) ); - - // marked completed - llms_mark_complete( $student, $lid, 'lesson' ); - $this->assertTrue( llms_is_complete( $student, $lid, 'lesson' ) ); - - // marked incompleted - llms_mark_incomplete( $student, $lid, 'lesson' ); - $this->assertFalse( llms_is_complete( $student, $sid, 'lesson' ) ); - - // complete it again to check parents - llms_mark_complete( $student, $lid, 'lesson' ); - $this->assertTrue( llms_is_complete( $student, $lid, 'lesson' ) ); - - // parent should still be incomplete - if ( $l_i <= 1 ) { - $this->assertFalse( llms_is_complete( $student, $sid, 'section' ) ); - } - - } - - // all lessons complete - $this->assertTrue( llms_is_complete( $student, $sid, 'section' ) ); - - // mark last lesson as incomplete - llms_mark_incomplete( $student, $lid, 'lesson' ); - $this->assertFalse( llms_is_complete( $student, $sid, 'section' ) ); - - // mark complete again for parent checks - llms_mark_complete( $student, $lid, 'lesson' ); - $this->assertTrue( llms_is_complete( $student, $sid, 'section' ) ); - - // parent should still be incomplete - if ( $s_i <= 1 ) { - $this->assertFalse( llms_is_complete( $student, $cid, 'course' ) ); - $this->assertFalse( llms_is_complete( $student, $track['term_id'], 'course_track' ) ); - } - - } - - $this->assertTrue( llms_is_complete( $student, $cid, 'course' ) ); - $this->assertTrue( llms_is_complete( $student, $track['term_id'], 'course_track' ) ); - - // mark last lesson as incomplete - llms_mark_incomplete( $student, $lid, 'lesson' ); - $this->assertFalse( llms_is_complete( $student, $cid, 'course' ) ); - $this->assertFalse( llms_is_complete( $student, $track['term_id'], 'course_track' ) ); - - // mark complete again for parents - llms_mark_complete( $student, $lid, 'lesson' ); - $this->assertTrue( llms_is_complete( $student, $cid, 'course' ) ); - $this->assertTrue( llms_is_complete( $student, $track['term_id'], 'course_track' ) ); - - } - - } - - /** - * Test whether a user is_enrolled() in a course or membership - * @return void - * @since 3.5.0 - * @version 3.17.4 - */ - public function test_enrollment() { - - llms_set_test_time_limit( 8000 ); - - // Create new user - $user_id = $this->factory->user->create( array( 'role' => 'subscriber' ) ); - - // Create new course - $course_id = $this->factory->post->create( array( 'post_type' => 'course' ) ); - - // Create new membership - $memb_id = $this->factory->post->create( array( 'post_type' => 'llms_membership' ) ); - - // Student shouldn't be enrolled in newly created course/membership - $this->assertFalse( llms_is_user_enrolled( $user_id, $course_id ) ); - $this->assertFalse( llms_is_user_enrolled( $user_id, $memb_id ) ); - - // Enroll Student in newly created course/membership - llms_enroll_student( $user_id, $course_id, 'test_is_enrolled' ); - llms_enroll_student( $user_id, $memb_id, 'test_is_enrolled' ); - - // Student should be enrolled in course/membership - $this->assertTrue( llms_is_user_enrolled( $user_id, $course_id ) ); - $this->assertTrue( llms_is_user_enrolled( $user_id, $memb_id ) ); - - // Wait 1 second before unenrolling Student - // otherwise, enrollment and unenrollment postmeta will have identical timestamps - sleep( 1 ); - - // Unenroll Student in newly created course/membership - llms_unenroll_student( $user_id, $course_id, 'cancelled', 'test_is_enrolled'); - llms_unenroll_student( $user_id, $memb_id, 'cancelled', 'test_is_enrolled' ); - - // Student should be not enrolled in newly created course/membership - $this->assertFalse( llms_is_user_enrolled( $user_id, $course_id ) ); - $this->assertFalse( llms_is_user_enrolled( $user_id, $memb_id ) ); - - - // these were tests against now deprectaed has_access - sleep( 1 ); - - $student = $this->get_mock_student(); - - $course_id = $this->generate_mock_courses()[0]; - - // no access - $this->assertFalse( $student->is_enrolled( $course_id ) ); - - // has access - llms_enroll_student( $student->get_id(), $course_id ); - $this->assertTrue( $student->is_enrolled( $course_id ) ); - - // check access after an access plan has expired access - $gateway = LLMS()->payment_gateways()->get_gateway_by_id( 'manual' ); - update_option( $gateway->get_option_name( 'enabled' ), 'yes' ); - - // new student - $student = $this->get_mock_student(); - - // create an access plan - $plan = new LLMS_Access_Plan( 'new', 'Test Access Plan' ); - $plan_data = array( - 'access_expiration' => 'limited-period', - 'access_length' => '1', - 'access_period' => 'month', - 'frequency' => 25, - 'is_free' => 'no', - 'length' => 0, - 'on_sale' => 'no', - 'period' => 'day', - 'price' => 25.00, - 'product_id' => $course_id, - 'sku' => 'accessplansku', - 'trial_offer' => 'no', - ); - foreach ( $plan_data as $key => $val ) { - $plan->set( $key, $val ); - } - - $order = new LLMS_Order( 'new' ); - $order->init( $student, $plan, $gateway ); - - $order->set( 'status', 'llms-completed' ); - update_option( $gateway->get_option_name( 'enabled' ), 'no' ); // prevent potential issues elsewhere - - // should be enrolled with no issues - $this->assertTrue( $student->is_enrolled( $course_id ) ); - - // fast forward - llms_mock_current_time( date( 'Y-m-d', current_time( 'timestamp' ) + YEAR_IN_SECONDS ) ); - - sleep( 1 ); // so the expiration status is later than the enrollment - - // trigger expiration - do_action( 'llms_access_plan_expiration', $order->get( 'id' ) ); - - $this->assertFalse( $student->is_enrolled( $course_id ) ); - - sleep( 1 ); - - // manually re-enroll the student, admin enrollment should take precendence here even though they no longer have access - llms_enroll_student( $student->get_id(), $course_id ); - $this->assertTrue( $student->is_enrolled( $course_id ) ); - - } - - /** - * Test get_enrollment_date() - * @return void - * @since 3.17.0 - * @version 3.17.0 - */ - public function test_get_enrollment_date() { - - $courses = $this->generate_mock_courses( 3, 0, 0, 0 ); - $student = $this->get_mock_student(); - - $now = time(); - $format = 'Y-m-d H:i:s'; - - // nothing completed - foreach ( $courses as $cid ) { - - $ts = $now + ( DAY_IN_SECONDS * rand( 1, 50 ) ); - $date = date( $format, $ts ); - - llms_mock_current_time( $date ); - - // enrollment date should match currently mocked date - $student->enroll( $cid ); - $this->assertEquals( $date, $student->get_enrollment_date( $cid, 'enrolled', $format ) ); - - $ts += HOUR_IN_SECONDS; - $new_date = date( $format, $ts ); - llms_mock_current_time( $new_date ); - - // updated date should be an hour later - $student->unenroll( $cid ); - $this->assertEquals( $new_date, $student->get_enrollment_date( $cid, 'updated', $format ) ); - - // enrollment date should still be the original date - $this->assertEquals( $date, $student->get_enrollment_date( $cid, 'enrolled', $format ) ); - - } - - } - - /** - * Test Student Getters and Setters - * @return void - * @since 3.5.1 - * @version 3.5.1 - */ - public function test_getters_setters() { - - $uid = $this->factory->user->create( array( 'role' => 'student' ) ); - $user = new WP_User( $uid ); - $student = new LLMS_Student( $uid ); - - // test some core prefixed stuff from the usermeta table - $student->set( 'first_name', 'Student' ); - $student->set( 'last_name', 'McStudentFace' ); - $this->assertEquals( get_user_meta( $uid, 'first_name', true ), $student->get( 'first_name' ) ); - $this->assertEquals( get_user_meta( $uid, 'last_name', true ), $student->get( 'last_name' ) ); - - // stuff from the user table - $this->assertEquals( $user->user_email, $student->get( 'user_email' ) ); - - // llms custom user meta - $student->set( 'billing_address', '123 Student Place' ); - $this->assertEquals( get_user_meta( $uid, 'llms_billing_address', true ), $student->get( 'billing_address' ) ); - - } - - /** - * Test get_name() function - * @return void - * @since 3.5.1 - * @version 3.5.1 - */ - public function test_get_name() { - - $uid = $this->factory->user->create( array( - 'role' => 'student' - ) ); - $user = new WP_User( $uid ); - $student = new LLMS_Student( $uid ); - - // no first/last name set, should return display name - $this->assertEquals( $user->display_name, $student->get_name() ); - - // set a first & last name - $uid = $this->factory->user->create( array( - 'first_name' => 'Student', - 'last_name' => 'McStudentFace', - 'role' => 'student' - ) ); - $student = new LLMS_Student( $uid ); - $this->assertEquals( 'Student McStudentFace', $student->get_name() ); - - } - - /** - * Test get_enrollment_status() - * @return void - * @since 3.17.0 - * @version 3.17.0 - */ - public function test_get_enrollment_status() { - - $course_id = $this->generate_mock_courses( 1, 1, 1, 0 )[0]; - $course = llms_get_post( $course_id ); - $student = llms_get_student( $this->factory->user->create( array( 'role' => 'student' ) ) ); - - // no status - $this->assertFalse( $student->get_enrollment_status( $course_id ) ); - - // enrolled - $student->enroll( $course_id ); - $this->assertEquals( 'enrolled', $student->get_enrollment_status( $course_id ) ); - $this->assertEquals( 'enrolled', $student->get_enrollment_status( $course_id, false ) ); - // check from a lesson - $this->assertEquals( 'enrolled', $student->get_enrollment_status( $course->get_lessons( 'ids' )[0] ) ); - $this->assertEquals( 'enrolled', $student->get_enrollment_status( $course->get_lessons( 'ids' )[0] ), false ); - - sleep( 1 ); - - // expired - $student->unenroll( $course_id ); - $this->assertEquals( 'expired', $student->get_enrollment_status( $course_id ) ); - $this->assertEquals( 'expired', $student->get_enrollment_status( $course_id, false ) ); - - } - - /** - * Test get_progress() - * @return void - * @since 3.15.0 - * @version 3.15.0 - */ - public function test_get_progress() { - - $student = $this->get_mock_student(); - - $courses = $this->generate_mock_courses( 3, 2, 5, 0 ); - - - // create a track and add all 3 courses to it - $track_id = wp_insert_term( 'Test Course Track', 'course_track' )['term_id']; - foreach ( $courses as $cid ) { - wp_set_post_terms( $cid, array( $track_id ), 'course_track' ); - } - - // course for most of our tests - $course_id = $courses[0]; - $course = llms_get_post( $course_id ); - - // check progress through course - $i = 0; - while ( $i <= 100 ) { - - $this->complete_courses_for_student( $student->get( 'id' ), array( $course_id ), $i ); - $this->assertEquals( $i, $student->get_progress( $course_id, 'course' ) ); - - $i += 10; - - } - - // check track progress - $this->assertEquals( 33.33, $student->get_progress( $track_id, 'course_track' ), '', 0.01 ); - $this->complete_courses_for_student( $student->get( 'id' ), array( $courses[1], $courses[2] ), 100 ); - $this->assertEquals( 100, $student->get_progress( $track_id, 'course_track' ), '', 0.01 ); - - // test the progress through a section - $student = $this->get_mock_student(); - foreach ( $course->get_sections( 'ids' ) as $i => $section_id ) { - - $this->assertEquals( 0, $student->get_progress( $section_id, 'section' ) ); - - if ( 0 === $i ) { - $this->complete_courses_for_student( $student->get( 'id' ), array( $course_id ), 50 ); - $this->assertEquals( 100, $student->get_progress( $section_id, 'section' ) ); - } else { - $this->complete_courses_for_student( $student->get( 'id' ), array( $course_id ), 80 ); - $this->assertEquals( 60, $student->get_progress( $section_id, 'section' ) ); - } - - } - - } - -} diff --git a/tests/unit-tests/user/class.llms.test.student.quizzes.php b/tests/unit-tests/user/class.llms.test.student.quizzes.php deleted file mode 100644 index e0ebf44292..0000000000 --- a/tests/unit-tests/user/class.llms.test.student.quizzes.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php -/** - * Tests for LifterLMS Student Functions - * @group quizzes - * @group LLMS_Student - * @since 3.9.0 - * @version 3.16.11 - */ -class LLMS_Test_Student_Quizzes extends LLMS_UnitTestCase { - - private function get_student_with_quizzes() { - - $uid = $this->factory->user->create(); - $student = llms_get_student( $uid ); - $courses = $this->generate_mock_courses( 3, 1, 1, 1 ); - $this->complete_courses_for_student( $uid, $courses ); - return $student; - - } - - /** - * test delet_attempt method - * @return void - * @since 3.9.0 - * @version 3.16.11 - */ - public function test_delete_attempt() { - - $i = 1; - while ( $i <= 5 ) { - - $student = $this->get_student_with_quizzes(); - $attempts = $student->quizzes()->get_all(); - $id = rand( 0, count( $attempts ) - 1 ); - $attempt = $attempts[ $id ]; - $this->assertTrue( $student->quizzes()->delete_attempt( $attempt->get( 'id' ) ) ); - $this->assertFalse( $attempt->exists() ); - - $i++; - - } - - } - -} diff --git a/vendor/autoload.php b/vendor/autoload.php new file mode 100644 index 0000000000..2b66a7005b --- /dev/null +++ b/vendor/autoload.php @@ -0,0 +1,7 @@ +<?php + +// autoload.php @generated by Composer + +require_once __DIR__ . '/composer/autoload_real.php'; + +return ComposerAutoloaderInit2e92416fee1d72f76e039c132274679a::getLoader(); diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php new file mode 100644 index 0000000000..2c72175e77 --- /dev/null +++ b/vendor/composer/ClassLoader.php @@ -0,0 +1,445 @@ +<?php + +/* + * This file is part of Composer. + * + * (c) Nils Adermann <naderman@naderman.de> + * Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Jordi Boggiano <j.boggiano@seld.be> + * @see http://www.php-fig.org/psr/psr-0/ + * @see http://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + // PSR-4 + private $prefixLengthsPsr4 = array(); + private $prefixDirsPsr4 = array(); + private $fallbackDirsPsr4 = array(); + + // PSR-0 + private $prefixesPsr0 = array(); + private $fallbackDirsPsr0 = array(); + + private $useIncludePath = false; + private $classMap = array(); + private $classMapAuthoritative = false; + private $missingClasses = array(); + private $apcuPrefix; + + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', $this->prefixesPsr0); + } + + return array(); + } + + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * APCu prefix to use to cache found/not-found classes, if the extension is enabled. + * + * @param string|null $apcuPrefix + */ + public function setApcuPrefix($apcuPrefix) + { + $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null; + } + + /** + * The APCu prefix in use, or null if APCu caching is not enabled. + * + * @return string|null + */ + public function getApcuPrefix() + { + return $this->apcuPrefix; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return bool|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { + return false; + } + if (null !== $this->apcuPrefix) { + $file = apcu_fetch($this->apcuPrefix.$class, $hit); + if ($hit) { + return $file; + } + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if (false === $file && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if (null !== $this->apcuPrefix) { + apcu_add($this->apcuPrefix.$class, $file); + } + + if (false === $file) { + // Remember that this class does not exist. + $this->missingClasses[$class] = true; + } + + return $file; + } + + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + $subPath = $class; + while (false !== $lastPos = strrpos($subPath, '\\')) { + $subPath = substr($subPath, 0, $lastPos); + $search = $subPath.'\\'; + if (isset($this->prefixDirsPsr4[$search])) { + foreach ($this->prefixDirsPsr4[$search] as $dir) { + $length = $this->prefixLengthsPsr4[$first][$search]; + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + + return false; + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ +function includeFile($file) +{ + include $file; +} diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php new file mode 100644 index 0000000000..7a91153b0d --- /dev/null +++ b/vendor/composer/autoload_classmap.php @@ -0,0 +1,9 @@ +<?php + +// autoload_classmap.php @generated by Composer + +$vendorDir = dirname(dirname(__FILE__)); +$baseDir = dirname($vendorDir); + +return array( +); diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php new file mode 100644 index 0000000000..b7fc0125db --- /dev/null +++ b/vendor/composer/autoload_namespaces.php @@ -0,0 +1,9 @@ +<?php + +// autoload_namespaces.php @generated by Composer + +$vendorDir = dirname(dirname(__FILE__)); +$baseDir = dirname($vendorDir); + +return array( +); diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php new file mode 100644 index 0000000000..d3b16091ec --- /dev/null +++ b/vendor/composer/autoload_psr4.php @@ -0,0 +1,10 @@ +<?php + +// autoload_psr4.php @generated by Composer + +$vendorDir = dirname(dirname(__FILE__)); +$baseDir = dirname($vendorDir); + +return array( + 'LLMS\\' => array($baseDir . '/includes'), +); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php new file mode 100644 index 0000000000..98977b0b42 --- /dev/null +++ b/vendor/composer/autoload_real.php @@ -0,0 +1,52 @@ +<?php + +// autoload_real.php @generated by Composer + +class ComposerAutoloaderInit2e92416fee1d72f76e039c132274679a +{ + private static $loader; + + public static function loadClassLoader($class) + { + if ('Composer\Autoload\ClassLoader' === $class) { + require __DIR__ . '/ClassLoader.php'; + } + } + + public static function getLoader() + { + if (null !== self::$loader) { + return self::$loader; + } + + spl_autoload_register(array('ComposerAutoloaderInit2e92416fee1d72f76e039c132274679a', 'loadClassLoader'), true, true); + self::$loader = $loader = new \Composer\Autoload\ClassLoader(); + spl_autoload_unregister(array('ComposerAutoloaderInit2e92416fee1d72f76e039c132274679a', 'loadClassLoader')); + + $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); + if ($useStaticLoader) { + require_once __DIR__ . '/autoload_static.php'; + + call_user_func(\Composer\Autoload\ComposerStaticInit2e92416fee1d72f76e039c132274679a::getInitializer($loader)); + } else { + $map = require __DIR__ . '/autoload_namespaces.php'; + foreach ($map as $namespace => $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + } + + $loader->register(true); + + return $loader; + } +} diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php new file mode 100644 index 0000000000..a2d77e2353 --- /dev/null +++ b/vendor/composer/autoload_static.php @@ -0,0 +1,31 @@ +<?php + +// autoload_static.php @generated by Composer + +namespace Composer\Autoload; + +class ComposerStaticInit2e92416fee1d72f76e039c132274679a +{ + public static $prefixLengthsPsr4 = array ( + 'L' => + array ( + 'LLMS\\' => 5, + ), + ); + + public static $prefixDirsPsr4 = array ( + 'LLMS\\' => + array ( + 0 => __DIR__ . '/../..' . '/includes', + ), + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->prefixLengthsPsr4 = ComposerStaticInit2e92416fee1d72f76e039c132274679a::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInit2e92416fee1d72f76e039c132274679a::$prefixDirsPsr4; + + }, null, ClassLoader::class); + } +} diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json new file mode 100644 index 0000000000..ae79557dbf --- /dev/null +++ b/vendor/composer/installed.json @@ -0,0 +1,70 @@ +[ + { + "name": "ericmann/wp-session-manager", + "version": "dev-master", + "version_normalized": "9999999-dev", + "source": { + "type": "git", + "url": "https://github.com/ericmann/wp-session-manager.git", + "reference": "8a4aacd25e4a89429e93a85df70a068052853cae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ericmann/wp-session-manager/zipball/8a4aacd25e4a89429e93a85df70a068052853cae", + "reference": "8a4aacd25e4a89429e93a85df70a068052853cae", + "shasum": "" + }, + "time": "2017-04-26T13:27:37+00:00", + "type": "wordpress-plugin", + "installation-source": "source", + "license": [ + "GPLv2.0+" + ], + "authors": [ + { + "name": "Eric Mann", + "email": "eric@eamann.com", + "homepage": "https://eamann.com", + "role": "Developer" + } + ], + "description": "Prototype session management for WordPress.", + "homepage": "https://github.com/ericmann/wp-session-manager", + "keywords": [ + "session" + ], + "support": { + "source": "https://github.com/ericmann/wp-session-manager/tree/1.2.2", + "issues": "https://github.com/ericmann/wp-session-manager/issues" + } + }, + { + "name": "gocodebox/action-scheduler", + "version": "dev-master", + "version_normalized": "9999999-dev", + "source": { + "type": "git", + "url": "https://github.com/gocodebox/action-scheduler.git", + "reference": "d7b66cbf2d423bec4d4129a45f9969261ec1d2af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/gocodebox/action-scheduler/zipball/d7b66cbf2d423bec4d4129a45f9969261ec1d2af", + "reference": "d7b66cbf2d423bec4d4129a45f9969261ec1d2af", + "shasum": "" + }, + "time": "2017-03-10T23:45:17+00:00", + "type": "library", + "installation-source": "source", + "authors": [ + { + "name": "Thomas Patrick Levy", + "email": "thomasplevy@gmail.com" + } + ], + "description": "Fork of https://github.com/Prospress/action-scheduler", + "support": { + "source": "https://github.com/gocodebox/action-scheduler/tree/master" + } + } +] diff --git a/vendor/ericmann/wp-session-manager/includes/class-recursive-arrayaccess.php b/vendor/ericmann/wp-session-manager/includes/class-recursive-arrayaccess.php new file mode 100644 index 0000000000..be6294e133 --- /dev/null +++ b/vendor/ericmann/wp-session-manager/includes/class-recursive-arrayaccess.php @@ -0,0 +1,213 @@ +<?php +/** + * Multidimensional ArrayAccess + * + * Allows ArrayAccess-like functionality with multidimensional arrays. Fully supports + * both sets and unsets. + * + * @package WordPress + * @subpackage Session + * @since 3.7.0 + */ + +/** + * Recursive array class to allow multidimensional array access. + * + * @package WordPress + * @since 3.7.0 + */ +class Recursive_ArrayAccess implements ArrayAccess, Iterator, Countable { + /** + * Internal data collection. + * + * @var array + */ + protected $container = array(); + + /** + * Flag whether or not the internal collection has been changed. + * + * @var bool + */ + protected $dirty = false; + + /** + * Default object constructor. + * + * @param array $data + */ + protected function __construct( $data = array() ) { + foreach ( $data as $key => $value ) { + $this[ $key ] = $value; + } + } + + /** + * Allow deep copies of objects + */ + public function __clone() { + foreach ( $this->container as $key => $value ) { + if ( $value instanceof self ) { + $this[ $key ] = clone $value; + } + } + } + + /** + * Output the data container as a multidimensional array. + * + * @return array + */ + public function toArray() { + $data = $this->container; + foreach ( $data as $key => $value ) { + if ( $value instanceof self ) { + $data[ $key ] = $value->toArray(); + } + } + return $data; + } + + /*****************************************************************/ + /* ArrayAccess Implementation */ + /*****************************************************************/ + + /** + * Whether a offset exists + * + * @link http://php.net/manual/en/arrayaccess.offsetexists.php + * + * @param mixed $offset An offset to check for. + * + * @return boolean true on success or false on failure. + */ + public function offsetExists( $offset ) { + return isset( $this->container[ $offset ]) ; + } + + /** + * Offset to retrieve + * + * @link http://php.net/manual/en/arrayaccess.offsetget.php + * + * @param mixed $offset The offset to retrieve. + * + * @return mixed Can return all value types. + */ + public function offsetGet( $offset ) { + return isset( $this->container[ $offset ] ) ? $this->container[ $offset ] : null; + } + + /** + * Offset to set + * + * @link http://php.net/manual/en/arrayaccess.offsetset.php + * + * @param mixed $offset The offset to assign the value to. + * @param mixed $value The value to set. + * + * @return void + */ + public function offsetSet( $offset, $data ) { + if ( is_array( $data ) ) { + $data = new self( $data ); + } + if ( $offset === null ) { // don't forget this! + $this->container[] = $data; + } else { + $this->container[ $offset ] = $data; + } + + $this->dirty = true; + } + + /** + * Offset to unset + * + * @link http://php.net/manual/en/arrayaccess.offsetunset.php + * + * @param mixed $offset The offset to unset. + * + * @return void + */ + public function offsetUnset( $offset ) { + unset( $this->container[ $offset ] ); + + $this->dirty = true; + } + + + /*****************************************************************/ + /* Iterator Implementation */ + /*****************************************************************/ + + /** + * Current position of the array. + * + * @link http://php.net/manual/en/iterator.current.php + * + * @return mixed + */ + public function current() { + return current( $this->container ); + } + + /** + * Key of the current element. + * + * @link http://php.net/manual/en/iterator.key.php + * + * @return mixed + */ + public function key() { + return key( $this->container ); + } + + /** + * Move the internal point of the container array to the next item + * + * @link http://php.net/manual/en/iterator.next.php + * + * @return void + */ + public function next() { + next( $this->container ); + } + + /** + * Rewind the internal point of the container array. + * + * @link http://php.net/manual/en/iterator.rewind.php + * + * @return void + */ + public function rewind() { + reset( $this->container ); + } + + /** + * Is the current key valid? + * + * @link http://php.net/manual/en/iterator.rewind.php + * + * @return bool + */ + public function valid() { + return $this->offsetExists( $this->key() ); + } + + /*****************************************************************/ + /* Countable Implementation */ + /*****************************************************************/ + + /** + * Get the count of elements in the container array. + * + * @link http://php.net/manual/en/countable.count.php + * + * @return int + */ + public function count() { + return count( $this->container ); + } +} diff --git a/vendor/ericmann/wp-session-manager/includes/class-wp-session-utils.php b/vendor/ericmann/wp-session-manager/includes/class-wp-session-utils.php new file mode 100644 index 0000000000..48d68325b0 --- /dev/null +++ b/vendor/ericmann/wp-session-manager/includes/class-wp-session-utils.php @@ -0,0 +1,139 @@ +<?php + +/** + * Utility class for sesion utilities + * + * THIS CLASS SHOULD NEVER BE INSTANTIATED + */ +class WP_Session_Utils { + /** + * Count the total sessions in the database. + * + * @global wpdb $wpdb + * + * @return int + */ + public static function count_sessions() { + global $wpdb; + + $query = "SELECT COUNT(*) FROM $wpdb->options WHERE option_name LIKE '_wp_session_expires_%'"; + + /** + * Filter the query in case tables are non-standard. + * + * @param string $query Database count query + */ + $query = apply_filters( 'wp_session_count_query', $query ); + + $sessions = $wpdb->get_var( $query ); + + return absint( $sessions ); + } + + /** + * Create a new, random session in the database. + * + * @param null|string $date + */ + public static function create_dummy_session( $date = null ) { + // Generate our date + if ( null !== $date ) { + $time = strtotime( $date ); + + if ( false === $time ) { + $date = null; + } else { + $expires = date( 'U', strtotime( $date ) ); + } + } + + // If null was passed, or if the string parsing failed, fall back on a default + if ( null === $date ) { + /** + * Filter the expiration of the session in the database + * + * @param int + */ + $expires = time() + (int) apply_filters( 'wp_session_expiration', 30 * 60 ); + } + + $session_id = self::generate_id(); + + // Store the session + add_option( "_wp_session_{$session_id}", array(), '', 'no' ); + add_option( "_wp_session_expires_{$session_id}", $expires, '', 'no' ); + } + + /** + * Delete old sessions from the database. + * + * @param int $limit Maximum number of sessions to delete. + * + * @global wpdb $wpdb + * + * @return int Sessions deleted. + */ + public static function delete_old_sessions( $limit = 1000 ) { + global $wpdb; + + $limit = absint( $limit ); + $keys = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options WHERE option_name LIKE '_wp_session_expires_%' ORDER BY option_value ASC LIMIT 0, {$limit}" ); + + $now = time(); + $expired = array(); + $count = 0; + + foreach( $keys as $expiration ) { + $key = $expiration->option_name; + $expires = $expiration->option_value; + + if ( $now > $expires ) { + $session_id = preg_replace("/[^A-Za-z0-9_]/", '', substr( $key, 20 ) ); + + $expired[] = $key; + $expired[] = "_wp_session_{$session_id}"; + + $count += 1; + } + } + + // Delete expired sessions + if ( ! empty( $expired ) ) { + $placeholders = array_fill( 0, count( $expired ), '%s' ); + $format = implode( ', ', $placeholders ); + $query = "DELETE FROM $wpdb->options WHERE option_name IN ($format)"; + + $prepared = $wpdb->prepare( $query, $expired ); + $wpdb->query( $prepared ); + } + + return $count; + } + + /** + * Remove all sessions from the database, regardless of expiration. + * + * @global wpdb $wpdb + * + * @return int Sessions deleted + */ + public static function delete_all_sessions() { + global $wpdb; + + $count = $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE '_wp_session_%'" ); + + return (int) ( $count / 2 ); + } + + /** + * Generate a new, random session ID. + * + * @return string + */ + public static function generate_id() { + require_once( ABSPATH . 'wp-includes/class-phpass.php' ); + $hash = new PasswordHash( 8, false ); + + return md5( $hash->get_random_bytes( 32 ) ); + } +} \ No newline at end of file diff --git a/vendor/ericmann/wp-session-manager/includes/class-wp-session.php b/vendor/ericmann/wp-session-manager/includes/class-wp-session.php new file mode 100644 index 0000000000..ef2a6ab243 --- /dev/null +++ b/vendor/ericmann/wp-session-manager/includes/class-wp-session.php @@ -0,0 +1,225 @@ +<?php +/** + * WordPress session managment. + * + * Standardizes WordPress session data using database-backed options for storage. + * for storing user session information. + * + * @package WordPress + * @subpackage Session + * @since 3.7.0 + */ + +/** + * WordPress Session class for managing user session data. + * + * @package WordPress + * @since 3.7.0 + */ +final class WP_Session extends Recursive_ArrayAccess { + /** + * ID of the current session. + * + * @var string + */ + public $session_id; + + /** + * Unix timestamp when session expires. + * + * @var int + */ + protected $expires; + + /** + * Unix timestamp indicating when the expiration time needs to be reset. + * + * @var int + */ + protected $exp_variant; + + /** + * Singleton instance. + * + * @var bool|WP_Session + */ + private static $instance = false; + + /** + * Retrieve the current session instance. + * + * @param bool $session_id Session ID from which to populate data. + * + * @return bool|WP_Session + */ + public static function get_instance() { + if ( ! self::$instance ) { + self::$instance = new self(); + } + + return self::$instance; + } + + /** + * Default constructor. + * Will rebuild the session collection from the given session ID if it exists. Otherwise, will + * create a new session with that ID. + * + * @param $session_id + * @uses apply_filters Calls `wp_session_expiration` to determine how long until sessions expire. + */ + protected function __construct() { + if ( isset( $_COOKIE[WP_SESSION_COOKIE] ) ) { + $cookie = stripslashes( $_COOKIE[WP_SESSION_COOKIE] ); + $cookie_crumbs = explode( '||', $cookie ); + + $this->session_id = preg_replace("/[^A-Za-z0-9_]/", '', $cookie_crumbs[0] ); + $this->expires = absint( $cookie_crumbs[1] ); + $this->exp_variant = absint( $cookie_crumbs[2] ); + + // Update the session expiration if we're past the variant time + if ( time() > $this->exp_variant ) { + $this->set_expiration(); + delete_option( "_wp_session_expires_{$this->session_id}" ); + add_option( "_wp_session_expires_{$this->session_id}", $this->expires, '', 'no' ); + } + } else { + $this->session_id = WP_Session_Utils::generate_id(); + $this->set_expiration(); + } + + $this->read_data(); + + $this->set_cookie(); + + } + + /** + * Set both the expiration time and the expiration variant. + * + * If the current time is below the variant, we don't update the session's expiration time. If it's + * greater than the variant, then we update the expiration time in the database. This prevents + * writing to the database on every page load for active sessions and only updates the expiration + * time if we're nearing when the session actually expires. + * + * By default, the expiration time is set to 30 minutes. + * By default, the expiration variant is set to 24 minutes. + * + * As a result, the session expiration time - at a maximum - will only be written to the database once + * every 24 minutes. After 30 minutes, the session will have been expired. No cookie will be sent by + * the browser, and the old session will be queued for deletion by the garbage collector. + * + * @uses apply_filters Calls `wp_session_expiration_variant` to get the max update window for session data. + * @uses apply_filters Calls `wp_session_expiration` to get the standard expiration time for sessions. + */ + protected function set_expiration() { + $this->exp_variant = time() + (int) apply_filters( 'wp_session_expiration_variant', 24 * 60 ); + $this->expires = time() + (int) apply_filters( 'wp_session_expiration', 30 * 60 ); + } + + /** + * Set the session cookie + * @uses apply_filters Calls `wp_session_cookie_secure` to set the $secure parameter of setcookie() + * @uses apply_filters Calls `wp_session_cookie_httponly` to set the $httponly parameter of setcookie() + */ + protected function set_cookie() { + $secure = apply_filters('wp_session_cookie_secure', false); + $httponly = apply_filters('wp_session_cookie_httponly', false); + setcookie( WP_SESSION_COOKIE, $this->session_id . '||' . $this->expires . '||' . $this->exp_variant , $this->expires, COOKIEPATH, COOKIE_DOMAIN, $secure, $httponly ); + } + + /** + * Read data from a transient for the current session. + * + * Automatically resets the expiration time for the session transient to some time in the future. + * + * @return array + */ + protected function read_data() { + $this->container = get_option( "_wp_session_{$this->session_id}", array() ); + + return $this->container; + } + + /** + * Write the data from the current session to the data storage system. + */ + public function write_data() { + $option_key = "_wp_session_{$this->session_id}"; + + if ( false === get_option( $option_key ) ) { + add_option( "_wp_session_{$this->session_id}", $this->container, '', 'no' ); + add_option( "_wp_session_expires_{$this->session_id}", $this->expires, '', 'no' ); + } else { + delete_option( "_wp_session_{$this->session_id}" ); + add_option( "_wp_session_{$this->session_id}", $this->container, '', 'no' ); + } + } + + /** + * Output the current container contents as a JSON-encoded string. + * + * @return string + */ + public function json_out() { + return json_encode( $this->container ); + } + + /** + * Decodes a JSON string and, if the object is an array, overwrites the session container with its contents. + * + * @param string $data + * + * @return bool + */ + public function json_in( $data ) { + $array = json_decode( $data ); + + if ( is_array( $array ) ) { + $this->container = $array; + return true; + } + + return false; + } + + /** + * Regenerate the current session's ID. + * + * @param bool $delete_old Flag whether or not to delete the old session data from the server. + */ + public function regenerate_id( $delete_old = false ) { + if ( $delete_old ) { + delete_option( "_wp_session_{$this->session_id}" ); + } + + $this->session_id = WP_Session_Utils::generate_id(); + + $this->set_cookie(); + } + + /** + * Check if a session has been initialized. + * + * @return bool + */ + public function session_started() { + return !!self::$instance; + } + + /** + * Return the read-only cache expiration value. + * + * @return int + */ + public function cache_expiration() { + return $this->expires; + } + + /** + * Flushes all session variables. + */ + public function reset() { + $this->container = array(); + } +} diff --git a/vendor/ericmann/wp-session-manager/includes/wp-cli.php b/vendor/ericmann/wp-session-manager/includes/wp-cli.php new file mode 100644 index 0000000000..3f5f4561d7 --- /dev/null +++ b/vendor/ericmann/wp-session-manager/includes/wp-cli.php @@ -0,0 +1,158 @@ +<?php + +/** + * CLI commands for WP Session Manager + * + * @package WP_Session + * @subpackage Commands + */ +class WP_Session_Command extends \WP_CLI_Command { + + /** + * Count the total number of sessions stored in the database. + * + * + * ## EXAMPLES + * + * wp session count + * + * @global wpdb $wpdb + * + * @param array $args + * @param array $assoc_args + */ + public function count( $args, $assoc_args ) { + $sessions = WP_Session_Utils::count_sessions(); + + \WP_CLI::line( sprintf( '%d sessions currently exist.', absint( $sessions ) ) ); + } + + /** + * Delete sessions from the database. + * + * ## OPTIONS + * + * [--all] + * : Flag whether or not to purge all sessions from the database. + * + * [--batch=<batch>] + * : Set the batch size for deleting old sessions + * + * [--limit=<limit>] + * : Delete just this number of old sessions + * + * ## EXAMPLES + * + * wp session delete + * wp session delete [--batch=<batch>] + * wp session delete [--limit=<limit>] + * wp session delete [--all] + * + * @synopsis [--all] [--batch=<batch>] [--limit=<limit>] + * + * @param array $args + * @param array $assoc_args + */ + public function delete( $args, $assoc_args ) { + if ( isset( $assoc_args['limit'] ) ) { + $limit = absint( $assoc_args['limit'] ); + + $count = WP_Session_Utils::delete_old_sessions( $limit ); + + if ( $count > 0 ) { + \WP_CLI::line( sprintf( 'Deleted %d sessions.', $count ) ); + } + + // Clear memory + self::free_up_memory(); + return; + } + + // Determine if we're deleting all sessions or just a subset. + $all = isset( $assoc_args['all'] ); + + /** + * Determine the size of each batch for deletion. + * + * @param int + */ + $batch = isset( $assoc_args['batch'] ) ? absint( $assoc_args['batch'] ) : apply_filters( 'wp_session_delete_batch_size', 1000 ); + + switch ( $all ) { + case true: + $count = WP_Session_Utils::delete_all_sessions(); + + \WP_CLI::line( sprintf( 'Deleted all %d sessions.', $count ) ); + break; + case false: + do { + $count = WP_Session_Utils::delete_old_sessions( $batch ); + + if ( $count > 0 ) { + \WP_CLI::line( sprintf( 'Deleted %d sessions.', $count ) ); + } + + // Clear memory + self::free_up_memory(); + } while ( $count > 0 ); + break; + } + } + + /** + * Generate a number of dummy sessions for testing purposes. + * + * ## OPTIONS + * + * <count> + * : Number of sessions to create. + * + * [--expires=<date>] + * : Optional expiration time tagged for each session. Will use WordPress' local time. + * + * ## EXAMPLES + * + * wp session generate 5000 + * wp session generate 5000 --expires="2014-11-09T08:00" + * + * @synopsis <count> [--expires=<date>] + * + * @param array $args + * @param array $assoc_args + */ + public function generate( $args, $assoc_args ) { + $count = absint( $args[0] ); + $date = isset( $assoc_args['expires'] ) ? $assoc_args['expires'] : null; + + $notify = \WP_CLI\Utils\make_progress_bar( 'Generating sessions', $count ); + + for ( $i = 0; $i < $count; $i ++ ) { + WP_Session_Utils::create_dummy_session( $date ); + $notify->tick(); + } + + $notify->finish(); + } + + /** + * Free up memory + * + * @global WP_Object_Cache $wp_object_cache + * @global wpdb $wpdb + */ + private function free_up_memory() { + global $wp_object_cache, $wpdb; + $wpdb->queries = array(); + + if ( ! is_object( $wp_object_cache ) ) { + return; + } + + $wp_object_cache->group_ops = array(); + $wp_object_cache->stats = array(); + $wp_object_cache->memcache_debug = array(); + $wp_object_cache->cache = array(); + } +} + +\WP_CLI::add_command( 'session', 'WP_Session_Command' ); \ No newline at end of file diff --git a/vendor/ericmann/wp-session-manager/includes/wp-session.php b/vendor/ericmann/wp-session-manager/includes/wp-session.php new file mode 100644 index 0000000000..6ebb683b64 --- /dev/null +++ b/vendor/ericmann/wp-session-manager/includes/wp-session.php @@ -0,0 +1,159 @@ +<?php +/** + * WordPress session managment. + * + * Standardizes WordPress session data and uses either database transients or in-memory caching + * for storing user session information. + * + * @package WordPress + * @subpackage Session + * @since 3.7.0 + */ + +/** + * Return the current cache expire setting. + * + * @return int + */ +function wp_session_cache_expire() { + $wp_session = WP_Session::get_instance(); + + return $wp_session->cache_expiration(); +} + +/** + * Alias of wp_session_write_close() + */ +function wp_session_commit() { + wp_session_write_close(); +} + +/** + * Load a JSON-encoded string into the current session. + * + * @param string $data + */ +function wp_session_decode( $data ) { + $wp_session = WP_Session::get_instance(); + + return $wp_session->json_in( $data ); +} + +/** + * Encode the current session's data as a JSON string. + * + * @return string + */ +function wp_session_encode() { + $wp_session = WP_Session::get_instance(); + + return $wp_session->json_out(); +} + +/** + * Regenerate the session ID. + * + * @param bool $delete_old_session + * + * @return bool + */ +function wp_session_regenerate_id( $delete_old_session = false ) { + $wp_session = WP_Session::get_instance(); + + $wp_session->regenerate_id( $delete_old_session ); + + return true; +} + +/** + * Start new or resume existing session. + * + * Resumes an existing session based on a value sent by the _wp_session cookie. + * + * @return bool + */ +function wp_session_start() { + $wp_session = WP_Session::get_instance(); + do_action( 'wp_session_start' ); + + return $wp_session->session_started(); +} +if ( ! defined( 'WP_CLI' ) || false === WP_CLI ) { + add_action( 'plugins_loaded', 'wp_session_start' ); +} + +/** + * Return the current session status. + * + * @return int + */ +function wp_session_status() { + $wp_session = WP_Session::get_instance(); + + if ( $wp_session->session_started() ) { + return PHP_SESSION_ACTIVE; + } + + return PHP_SESSION_NONE; +} + +/** + * Unset all session variables. + */ +function wp_session_unset() { + $wp_session = WP_Session::get_instance(); + + $wp_session->reset(); +} + +/** + * Write session data and end session + */ +function wp_session_write_close() { + $wp_session = WP_Session::get_instance(); + + $wp_session->write_data(); + do_action( 'wp_session_commit' ); +} +if ( ! defined( 'WP_CLI' ) || false === WP_CLI ) { + add_action( 'shutdown', 'wp_session_write_close' ); +} + +/** + * Clean up expired sessions by removing data and their expiration entries from + * the WordPress options table. + * + * This method should never be called directly and should instead be triggered as part + * of a scheduled task or cron job. + */ +function wp_session_cleanup() { + if ( defined( 'WP_SETUP_CONFIG' ) ) { + return; + } + + if ( ! defined( 'WP_INSTALLING' ) ) { + /** + * Determine the size of each batch for deletion. + * + * @param int + */ + $batch_size = apply_filters( 'wp_session_delete_batch_size', 1000 ); + + // Delete a batch of old sessions + WP_Session_Utils::delete_old_sessions( $batch_size ); + } + + // Allow other plugins to hook in to the garbage collection process. + do_action( 'wp_session_cleanup' ); +} +add_action( 'wp_session_garbage_collection', 'wp_session_cleanup' ); + +/** + * Register the garbage collector as a twice daily event. + */ +function wp_session_register_garbage_collection() { + if ( ! wp_next_scheduled( 'wp_session_garbage_collection' ) ) { + wp_schedule_event( time(), 'hourly', 'wp_session_garbage_collection' ); + } +} +add_action( 'wp', 'wp_session_register_garbage_collection' ); diff --git a/vendor/ericmann/wp-session-manager/readme.txt b/vendor/ericmann/wp-session-manager/readme.txt new file mode 100644 index 0000000000..1c50ec8254 --- /dev/null +++ b/vendor/ericmann/wp-session-manager/readme.txt @@ -0,0 +1,95 @@ +=== WP Session Manager === +Contributors: ericmann +Donate link: http://jumping-duck.com/wordpress/plugins +Tags: session +Requires at least: 3.4.2 +Tested up to: 4.7.4 +Stable tag: 1.2.2 +License: GPLv2 or later +License URI: http://www.gnu.org/licenses/gpl-2.0.html + +Prototype session management for WordPress. + +== Description == + +Adds `$_SESSION`-like functionality to WordPress. + +Every visitor, logged in or not, will be issued an instance of `WP_Session`. Their instance will be identified by an ID +stored in the `_wp_session` cookie. Typically, session data will be stored in a WordPress transient, but if your +installation has a caching system in-place (i.e. memcached), the session data might be stored in memory. + +This provides plugin and theme authors the ability to use WordPress-managed session variables without having to use the +standard PHP `$_SESSION` superglobal. + +== Installation == + += Manual Installation = + +1. Upload the entire `/wp-session-manager` folder to the `/wp-content/plugins/` directory. +1. Activate the plugin through the 'Plugins' menu in WordPress. +1. Use `WP_Session::get_instance()` in your code. + +== Frequently Asked Questions == + += How do I add session variables? = + +First, make a reference to the WP_Session instance. Then, use it like an associative array, just like `$_SESSION`: + +`$wp_session = WP_Session::get_instance(); +$wp_session['user_name'] = 'User Name'; // A string +$wp_session['user_contact'] = array( 'email' => 'user@name.com' ); // An array +$wp_session['user_obj'] = new WP_User( 1 ); // An object` + += How long do session variables live? = + +By default, session variables will live for 24 minutes from the last time they were accessed - either read or write. + +This value can be changed by using the `wp_session_expiration` filter: + +`add_filter( 'wp_session_expiration', function() { return 60 * 60; } ); // Set expiration to 1 hour` + +== Screenshots == + +None + +== Changelog == + += 1.2.2 = +* Update: Use regex pattern matching to ensure session IDs are identical going in/out of the DB to account for encoding differences + += 1.2.1 = +* Update: Additional filters for the `setcookie` parameters +* Update: Expose the Session ID publicly +* Fix: Better handling for malformed or broken session names + += 1.2.0 = +* Update: Enhanced plugin organization +* Update: Added WP_CLI support for session management +* Update: Add Composer definitions +* Fix: Break up the deletion of old sessions so queries don't time out under load + += 1.1.2 = +* Fix a race condition where session expiration options could accidentally be set to autoload +* Make the garbage collection routine run hourly to alleviate long-running tasks on larger sites + += 1.1.1 = +* Fix a bug where session expiration was not properly set upon instantiation + += 1.1 = +* Implement Recursive_ArrayAccess to provide multidimensional array support +* Better expiration for session data +* Implement garbage collection to keep the database clean + += 1.0.2 = +* Switch to object persistence rather than transients + += 1.0.1 = +* Changes implementation to avoid the use of a global variable (still registered for convenience) + += 1.0 = +* First version + +== Upgrade Notice == + += 1.0 = +First version \ No newline at end of file diff --git a/vendor/ericmann/wp-session-manager/wp-session-manager.php b/vendor/ericmann/wp-session-manager/wp-session-manager.php new file mode 100644 index 0000000000..913abd1766 --- /dev/null +++ b/vendor/ericmann/wp-session-manager/wp-session-manager.php @@ -0,0 +1,35 @@ +<?php +/** + * Plugin Name: WP Session Manager + * Plugin URI: http://jumping-duck.com/wordpress/plugins + * Description: Prototype session management for WordPress. + * Version: 1.2.2 + * Author: Eric Mann + * Author URI: http://eamann.com + * License: GPLv2+ + */ + +// let users change the session cookie name +if( ! defined( 'WP_SESSION_COOKIE' ) ) { + define( 'WP_SESSION_COOKIE', '_wp_session' ); +} + +if ( ! class_exists( 'Recursive_ArrayAccess' ) ) { + include 'includes/class-recursive-arrayaccess.php'; +} + +// Include utilities class +if ( ! class_exists( 'WP_Session_Utils' ) ) { + include 'includes/class-wp-session-utils.php'; +} + +// Include WP_CLI routines early +if ( defined( 'WP_CLI' ) && WP_CLI ) { + include 'includes/wp-cli.php'; +} + +// Only include the functionality if it's not pre-defined. +if ( ! class_exists( 'WP_Session' ) ) { + include 'includes/class-wp-session.php'; + include 'includes/wp-session.php'; +} diff --git a/vendor/gocodebox/action-scheduler/action-scheduler.php b/vendor/gocodebox/action-scheduler/action-scheduler.php new file mode 100644 index 0000000000..4536553c54 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/action-scheduler.php @@ -0,0 +1,30 @@ +<?php +/* +Plugin Name: Action Scheduler +Plugin URI: https://github.com/prospress/action-scheduler +Description: A robust action scheduler for WordPress +Author: Prospress +Author URI: http://prospress.com/ +Version: 1.5.2 +*/ + +if ( ! function_exists( 'action_scheduler_register_1_dot_5_dot_2' ) ) { + + if ( ! class_exists( 'ActionScheduler_Versions' ) ) { + require_once( 'classes/ActionScheduler_Versions.php' ); + add_action( 'plugins_loaded', array( 'ActionScheduler_Versions', 'initialize_latest_version' ), 1, 0 ); + } + + add_action( 'plugins_loaded', 'action_scheduler_register_1_dot_5_dot_2', 0, 0 ); + + function action_scheduler_register_1_dot_5_dot_2() { + $versions = ActionScheduler_Versions::instance(); + $versions->register( '1.5.2', 'action_scheduler_initialize_1_dot_5_dot_2' ); + } + + function action_scheduler_initialize_1_dot_5_dot_2() { + require_once( 'classes/ActionScheduler.php' ); + ActionScheduler::init( __FILE__ ); + } + +} \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler.php new file mode 100644 index 0000000000..fa08adfdc9 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler.php @@ -0,0 +1,120 @@ +<?php + +/** + * Class ActionScheduler + * @codeCoverageIgnore + */ +abstract class ActionScheduler { + private static $plugin_file = ''; + /** @var ActionScheduler_ActionFactory */ + private static $factory = NULL; + + public static function factory() { + if ( !isset(self::$factory) ) { + self::$factory = new ActionScheduler_ActionFactory(); + } + return self::$factory; + } + + public static function store() { + return ActionScheduler_Store::instance(); + } + + public static function logger() { + return ActionScheduler_Logger::instance(); + } + + public static function runner() { + return ActionScheduler_QueueRunner::instance(); + } + + public static function admin_view() { + return ActionScheduler_AdminView::instance(); + } + + /** + * Get the absolute system path to the plugin directory, or a file therein + * @static + * @param string $path + * @return string + */ + public static function plugin_path( $path ) { + $base = dirname(self::$plugin_file); + if ( $path ) { + return trailingslashit($base).$path; + } else { + return untrailingslashit($base); + } + } + + /** + * Get the absolute URL to the plugin directory, or a file therein + * @static + * @param string $path + * @return string + */ + public static function plugin_url( $path ) { + return plugins_url($path, self::$plugin_file); + } + + public static function autoload( $class ) { + $d = DIRECTORY_SEPARATOR; + if ( strpos( $class, 'ActionScheduler' ) === 0 ) { + $dir = self::plugin_path('classes'.$d); + } elseif ( strpos( $class, 'CronExpression' ) === 0 ) { + $dir = self::plugin_path('lib'.$d.'cron-expression'.$d); + } else { + return; + } + + if ( file_exists( $dir.$class.'.php' ) ) { + include( $dir.$class.'.php' ); + return; + } + } + + /** + * Initialize the plugin + * + * @static + * @param string $plugin_file + * @return void + */ + public static function init( $plugin_file ) { + self::$plugin_file = $plugin_file; + spl_autoload_register( array( __CLASS__, 'autoload' ) ); + + $store = self::store(); + add_action( 'init', array( $store, 'init' ), 1, 0 ); + + $logger = self::logger(); + add_action( 'init', array( $logger, 'init' ), 1, 0 ); + + $runner = self::runner(); + add_action( 'init', array( $runner, 'init' ), 1, 0 ); + + $admin_view = self::admin_view(); + add_action( 'init', array( $admin_view, 'init' ), 0, 0 ); // run before $store::init() + + require_once( self::plugin_path('functions.php') ); + } + + + final public function __clone() { + trigger_error("Singleton. No cloning allowed!", E_USER_ERROR); + } + + final public function __wakeup() { + trigger_error("Singleton. No serialization allowed!", E_USER_ERROR); + } + + final private function __construct() {} + + /** Deprecated **/ + + public static function get_datetime_object( $when = null, $timezone = 'UTC' ) { + _deprecated_function( __METHOD__, '2.0', 'wcs_add_months()' ); + return as_get_datetime_object( $when, $timezone ); + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_Action.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_Action.php new file mode 100644 index 0000000000..18ceb2739f --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_Action.php @@ -0,0 +1,77 @@ +<?php + +/** + * Class ActionScheduler_Action + */ +class ActionScheduler_Action { + protected $hook = ''; + protected $args = array(); + /** @var ActionScheduler_Schedule */ + protected $schedule = NULL; + protected $group = ''; + + public function __construct( $hook, array $args = array(), ActionScheduler_Schedule $schedule = NULL, $group = '' ) { + $schedule = empty( $schedule ) ? new ActionScheduler_NullSchedule() : $schedule; + $this->set_hook($hook); + $this->set_schedule($schedule); + $this->set_args($args); + $this->set_group($group); + } + + public function execute() { + return do_action_ref_array($this->get_hook(), $this->get_args()); + } + + /** + * @param string $hook + * @return void + */ + protected function set_hook( $hook ) { + $this->hook = $hook; + } + + public function get_hook() { + return $this->hook; + } + + protected function set_schedule( ActionScheduler_Schedule $schedule ) { + $this->schedule = $schedule; + } + + /** + * @return ActionScheduler_Schedule + */ + public function get_schedule() { + return $this->schedule; + } + + protected function set_args( array $args ) { + $this->args = $args; + } + + public function get_args() { + return $this->args; + } + + /** + * @param string $group + */ + protected function set_group( $group ) { + $this->group = $group; + } + + /** + * @return string + */ + public function get_group() { + return $this->group; + } + + /** + * @return bool If the action has been finished + */ + public function is_finished() { + return FALSE; + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_ActionClaim.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_ActionClaim.php new file mode 100644 index 0000000000..8b5681620e --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_ActionClaim.php @@ -0,0 +1,23 @@ +<?php + +/** + * Class ActionScheduler_ActionClaim + */ +class ActionScheduler_ActionClaim { + private $id = ''; + private $action_ids = array(); + + public function __construct( $id, array $action_ids ) { + $this->id = $id; + $this->action_ids = $action_ids; + } + + public function get_id() { + return $this->id; + } + + public function get_actions() { + return $this->action_ids; + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_ActionFactory.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_ActionFactory.php new file mode 100644 index 0000000000..f61ba48db3 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_ActionFactory.php @@ -0,0 +1,72 @@ +<?php + +/** + * Class ActionScheduler_ActionFactory + */ +class ActionScheduler_ActionFactory { + /** + * @param string $hook The hook to trigger when this action runs + * @param array $args Args to pass when the hook is triggered + * @param int $when Unix timestamp when the action will run + * @param string $group A group to put the action in + * + * @return string The ID of the stored action + */ + public function single( $hook, $args = array(), $when = NULL, $group = '' ) { + $date = as_get_datetime_object( $when ); + $schedule = new ActionScheduler_SimpleSchedule( $date ); + $action = new ActionScheduler_Action( $hook, $args, $schedule, $group ); + return $this->store( $action ); + } + + /** + * @param string $hook The hook to trigger when this action runs + * @param array $args Args to pass when the hook is triggered + * @param int $first Unix timestamp for the first run + * @param int $interval Seconds between runs + * @param string $group A group to put the action in + * + * @return string The ID of the stored action + */ + public function recurring( $hook, $args = array(), $first = NULL, $interval = NULL, $group = '' ) { + if ( empty($interval) ) { + return $this->single( $hook, $args, $first, $group ); + } + $date = as_get_datetime_object( $first ); + $schedule = new ActionScheduler_IntervalSchedule( $date, $interval ); + $action = new ActionScheduler_Action( $hook, $args, $schedule, $group ); + return $this->store( $action ); + } + + + /** + * @param string $hook The hook to trigger when this action runs + * @param array $args Args to pass when the hook is triggered + * @param int $first Unix timestamp for the first run + * @param int $schedule A cron definition string + * @param string $group A group to put the action in + * + * @return string The ID of the stored action + */ + public function cron( $hook, $args = array(), $first = NULL, $schedule = NULL, $group = '' ) { + if ( empty($schedule) ) { + return $this->single( $hook, $args, $first, $group ); + } + $date = as_get_datetime_object( $first ); + $cron = CronExpression::factory( $schedule ); + $schedule = new ActionScheduler_CronSchedule( $date, $cron ); + $action = new ActionScheduler_Action( $hook, $args, $schedule, $group ); + return $this->store( $action ); + } + + /** + * @param ActionScheduler_Action $action + * + * @return string The ID of the stored action + */ + protected function store( ActionScheduler_Action $action ) { + $store = ActionScheduler_Store::instance(); + return $store->save_action( $action ); + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_AdminView.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_AdminView.php new file mode 100644 index 0000000000..f67f0e631e --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_AdminView.php @@ -0,0 +1,479 @@ +<?php + +/** + * Class ActionScheduler_AdminView + * @codeCoverageIgnore + */ +class ActionScheduler_AdminView { + + private static $admin_view = NULL; + + private static $admin_url; + + /** + * @return ActionScheduler_QueueRunner + * @codeCoverageIgnore + */ + public static function instance() { + + if ( empty( self::$admin_view ) ) { + $class = apply_filters('action_scheduler_admin_view_class', 'ActionScheduler_AdminView'); + self::$admin_view = new $class(); + } + + return self::$admin_view; + } + + /** + * @codeCoverageIgnore + */ + public function init() { + + if ( defined( 'WP_DEBUG' ) && true == WP_DEBUG && is_admin() && ( ! defined( 'DOING_AJAX' ) || false == DOING_AJAX ) ) { + add_filter( 'action_scheduler_post_type_args', array( self::instance(), 'action_scheduler_post_type_args' ) ); + } + + self::$admin_url = admin_url( 'edit.php?post_type=' . ActionScheduler_wpPostStore::POST_TYPE ); + + add_filter( 'views_edit-' . ActionScheduler_wpPostStore::POST_TYPE, array( self::instance(), 'list_table_views' ) ); + + add_filter( 'bulk_actions-edit-' . ActionScheduler_wpPostStore::POST_TYPE, array( self::instance(), 'bulk_actions' ) ); + + add_filter( 'manage_' . ActionScheduler_wpPostStore::POST_TYPE . '_posts_columns', array( self::instance(), 'list_table_columns' ), 1 ); + + add_filter( 'manage_edit-' . ActionScheduler_wpPostStore::POST_TYPE . '_sortable_columns', array( self::instance(), 'list_table_sortable_columns' ) ); + + add_filter( 'manage_' . ActionScheduler_wpPostStore::POST_TYPE . '_posts_custom_column', array( self::instance(), 'list_table_column_content' ), 10, 2 ); + + add_filter( 'post_row_actions', array( self::instance(), 'row_actions' ), 10, 2 ); + + add_action( 'admin_init', array( self::instance(), 'maybe_execute_action' ), 20 ); + + add_action( 'admin_notices', array( self::instance(), 'admin_notices' ) ); + + add_filter( 'post_updated_messages', array( self::instance(), 'post_updated_messages' ) ); + + add_filter( 'posts_orderby', array( self::instance(), 'custom_orderby' ), 10, 2 ); + + add_filter( 'posts_search', array( self::instance(), 'search_post_password' ), 10, 2 ); + } + + public function action_scheduler_post_type_args( $args ) { + return array_merge( $args, array( + 'show_ui' => true, + 'show_in_menu' => 'tools.php', + 'show_in_admin_bar' => false, + )); + } + + /** + * Customise the post status related views displayed on the Scheduled Actions administration screen. + * + * @param array $views An associative array of views and view labels which can be used to filter the 'scheduled-action' posts displayed on the Scheduled Actions administration screen. + * @return array $views An associative array of views and view labels which can be used to filter the 'scheduled-action' posts displayed on the Scheduled Actions administration screen. + */ + public function list_table_views( $views ) { + + foreach ( $views as $view_key => $view ) { + if ( 'publish' == $view_key ) { + $views[ $view_key ] = str_replace( __( 'Published', 'action-scheduler' ), __( 'Complete', 'action-scheduler' ), $view ); + break; + } + } + + return $views; + } + + /** + * Do not include the "Edit" action for the Scheduled Actions administration screen. + * + * Hooked to the 'bulk_actions-edit-action-scheduler' filter. + * + * @param array $actions An associative array of actions which can be performed on the 'scheduled-action' post type. + * @return array $actions An associative array of actions which can be performed on the 'scheduled-action' post type. + */ + public function bulk_actions( $actions ) { + + if ( isset( $actions['edit'] ) ) { + unset( $actions['edit'] ); + } + + return $actions; + } + + /** + * Completely customer the columns displayed on the Scheduled Actions administration screen. + * + * Because we can't filter the content of the default title and date columns, we need to recreate our own + * custom columns for displaying those post fields. For the column content, @see self::list_table_column_content(). + * + * @param array $columns An associative array of columns that are use for the table on the Scheduled Actions administration screen. + * @return array $columns An associative array of columns that are use for the table on the Scheduled Actions administration screen. + */ + public function list_table_columns( $columns ) { + + $custom_columns = array( + 'cb' => $columns['cb'], + 'hook' => __( 'Hook', 'action-scheduler' ), // because we want to customise the inline actions + 'status' => __( 'Status', 'action-scheduler' ), + 'args' => __( 'Arguments', 'action-scheduler' ), + 'taxonomy-action-group' => __( 'Group', 'action-scheduler' ), + 'recurrence' => __( 'Recurrence', 'action-scheduler' ), + 'scheduled' => __( 'Scheduled Date', 'action-scheduler' ), // because we want to customise how the date is displayed + ); + + if ( isset( $_REQUEST['post_status'] ) ) { + if ( in_array( $_REQUEST['post_status'], array( 'failed', 'in-progress' ) ) ) { + $custom_columns['modified'] = __( 'Started', 'action-scheduler' ); + } elseif ( 'publish' == $_REQUEST['post_status'] ) { + $custom_columns['modified'] = __( 'Completed', 'action-scheduler' ); + } + } + + $custom_columns['claim'] = __( 'Claim ID', 'action-scheduler' ); + $custom_columns['comments'] = __( 'Log', 'action-scheduler' ); + + return $custom_columns; + } + + /** + * Make our custom title & date columns use defaulting title & date sorting. + * + * @param array $columns An associative array of columns that can be used to sort the table on the Scheduled Actions administration screen. + * @return array $columns An associative array of columns that can be used to sort the table on the Scheduled Actions administration screen. + */ + public static function list_table_sortable_columns( $columns ) { + + $columns['hook'] = 'title'; + $columns['scheduled'] = array( 'date', true ); + $columns['modified'] = 'modified'; + $columns['claim'] = 'post_password'; + + return $columns; + } + + /** + * Print the content for our custom columns. + * + * @param string $column_name The key for the column for which we should output our content. + * @param int $post_id The ID of the 'scheduled-action' post for which this row relates. + * @return void + */ + public static function list_table_column_content( $column_name, $post_id ) { + global $post; + + $action = ActionScheduler::store()->fetch_action( $post_id ); + + $action_title = ( 'trash' == $post->post_status ) ? $post->post_title : $action->get_hook(); + $recurrence = ( 'trash' == $post->post_status ) ? 0 : $action->get_schedule(); + $next_timestamp = as_get_datetime_object( $post->post_date_gmt )->format( 'U' ); + $status = get_post_status( $post_id ); + + switch ( $column_name ) { + case 'hook': + echo $action_title; + break; + case 'status': + if ( 'publish' == $status ) { + _e( 'Complete', 'action-scheduler' ); + } else { + echo ucfirst( $status ); + } + break; + case 'args': + $action_args = ( 'trash' == $post->post_status ) ? $post->post_content : $action->get_args(); + if ( is_array( $action_args ) ) { + foreach( $action_args as $key => $value ) { + printf( "<code>%s => %s</code><br/>", $key, $value ); + } + } + break; + case 'recurrence': + if ( method_exists( $recurrence, 'interval_in_seconds' ) ) { + echo self::human_interval( $recurrence->interval_in_seconds() ); + } else { + _e( 'Non-repeating', 'action-scheduler' ); + } + break; + case 'scheduled': + echo get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $next_timestamp ), 'Y-m-d H:i:s' ); + if ( gmdate( 'U' ) > $next_timestamp ) { + printf( __( ' (%s ago)', 'action-scheduler' ), human_time_diff( gmdate( 'U' ), $next_timestamp ) ); + } else { + echo ' (' . human_time_diff( gmdate( 'U' ), $next_timestamp ) . ')'; + } + break; + case 'modified': + echo get_post_modified_time( 'Y-m-d H:i:s' ); + $modified_timestamp = get_post_modified_time( 'U', true ); + if ( gmdate( 'U' ) > $modified_timestamp ) { + printf( __( ' (%s ago)', 'action-scheduler' ), human_time_diff( gmdate( 'U' ), $modified_timestamp ) ); + } else { + echo ' (' . human_time_diff( gmdate( 'U' ), $modified_timestamp ) . ')'; + } + break; + case 'claim': + echo $post->post_password; + break; + } + } + + /** + * Hide the inline "Edit" action for all 'scheduled-action' posts. + * + * Hooked to the 'post_row_actions' filter. + * + * @param array $actions An associative array of actions which can be performed on the 'scheduled-action' post type. + * @return array $actions An associative array of actions which can be performed on the 'scheduled-action' post type. + */ + public static function row_actions( $actions, $post ) { + + if ( ActionScheduler_wpPostStore::POST_TYPE == $post->post_type ) { + + if ( isset( $actions['edit'] ) ) { + unset( $actions['edit'] ); + } + + if ( isset( $actions['inline hide-if-no-js'] ) ) { + unset( $actions['inline hide-if-no-js'] ); + } + + if ( current_user_can( 'edit_post', $post->ID ) && ! in_array( $post->post_status, array( 'publish', 'in-progress', 'trash' ) ) ) { + $actions['process'] = "<a title='" . esc_attr( __( 'Process the action now as if it were run as part of a queue' ) ) . "' href='" . self::get_run_action_link( $post->ID, 'process' ) . "'>" . __( 'Run', 'action-scheduler' ) . "</a>"; + } + + ksort( $actions ); + } + + return $actions; + } + + /** + * Retrieve a URI to execute a scheduled action. + * + * @param int $action_id The ID for a 'scheduled-action' post. + * @param string $operation To run the action (including trigger before/after hooks), log the execution and update the action's status, use 'process', to simply trigger the action, use 'execute'. Default 'execute'. + * @return string The URL for running the action. + */ + private static function get_run_action_link( $action_id, $operation = 'process' ) { + + if ( !$post = get_post( $action_id ) ) + return; + + $post_type_object = get_post_type_object( $post->post_type ); + + if ( ! $post_type_object ) + return; + + if ( ! current_user_can( 'edit_post', $post->ID ) ) + return; + + $execute_link = add_query_arg( array( 'action' => $operation, 'post_id' => $post->ID ), self::$admin_url ); + + return wp_nonce_url( $execute_link, "{$operation}-action_{$post->ID}" ); + } + + /** + * Run an action when triggered from the Action Scheduler administration screen. + * + * @codeCoverageIgnore + */ + public static function maybe_execute_action() { + + if ( ! isset( $_GET['action'] ) || 'process' != $_GET['action'] || ! isset( $_GET['post_id'] ) ){ + return; + } + + $action_id = absint( $_GET['post_id'] ); + + check_admin_referer( $_GET['action'] . '-action_' . $action_id ); + + try { + ActionScheduler::runner()->process_action( $action_id ); + $success = 1; + } catch ( Exception $e ) { + $success = 0; + } + + wp_redirect( add_query_arg( array( 'executed' => $success, 'ids' => $action_id ), self::$admin_url ) ); + exit(); + } + + /** + * Convert an interval of seconds into a two part human friendly string. + * + * The WordPress human_time_diff() function only calculates the time difference to one degree, meaning + * even if an action is 1 day and 11 hours away, it will display "1 day". This funciton goes one step + * further to display two degrees of accuracy. + * + * Based on Crontrol::interval() funciton by Edward Dale: https://wordpress.org/plugins/wp-crontrol/ + * + * @param int $interval A interval in seconds. + * @return string A human friendly string representation of the interval. + */ + public static function admin_notices() { + + if ( self::is_admin_page() ) { + + if ( ActionScheduler_Store::instance()->get_claim_count() >= apply_filters( 'action_scheduler_queue_runner_concurrent_batches', 5 ) ) : ?> +<div id="message" class="updated"> + <p><?php printf( __( 'Maximum simulatenous batches already in progress (%s queues). No actions will be processed until the current batches are complete.', 'action-scheduler' ), ActionScheduler_Store::instance()->get_claim_count() ); ?></p> +</div> + <?php endif; + + if ( isset( $_GET['executed'] ) && isset( $_GET['ids'] ) ) { + $action = ActionScheduler::store()->fetch_action( $_GET['ids'] ); + $action_hook_html = '<strong>' . $action->get_hook() . '</strong>'; + if ( 1 == $_GET['executed'] ) : ?> +<div id="message" class="updated"> + <p><?php printf( __( 'Successfully executed the action: %s', 'action-scheduler' ), $action_hook_html ); ?></p> +</div> + <?php else : ?> +<div id="message" class="error"> + <p><?php printf( __( 'Could not execute the action: %s', 'action-scheduler' ), $action_hook_html ); ?></p> +</div> + <?php endif; + } + } + } + + /** + * Convert a interval of seconds into a two part human friendly string. + * + * The WordPress human_time_diff() function only calculates the time difference to one degree, meaning + * even if an action is 1 day and 11 hours away, it will display "1 day". This funciton goes one step + * further to display two degrees of accuracy. + * + * Based on Crontrol::interval() funciton by Edward Dale: https://wordpress.org/plugins/wp-crontrol/ + * + * @param int $interval A interval in seconds. + * @return string A human friendly string representation of the interval. + */ + private static function human_interval( $interval ) { + // array of time period chunks + $chunks = array( + array( 60 * 60 * 24 * 365 , _n_noop( '%s year', '%s years', 'action-scheduler' ) ), + array( 60 * 60 * 24 * 30 , _n_noop( '%s month', '%s months', 'action-scheduler' ) ), + array( 60 * 60 * 24 * 7, _n_noop( '%s week', '%s weeks', 'action-scheduler' ) ), + array( 60 * 60 * 24 , _n_noop( '%s day', '%s days', 'action-scheduler' ) ), + array( 60 * 60 , _n_noop( '%s hour', '%s hours', 'action-scheduler' ) ), + array( 60 , _n_noop( '%s minute', '%s minutes', 'action-scheduler' ) ), + array( 1 , _n_noop( '%s second', '%s seconds', 'action-scheduler' ) ), + ); + + if ( $interval <= 0 ) { + return __( 'Now!', 'action-scheduler' ); + } + + // Step one: the first chunk + for ( $i = 0, $j = count( $chunks ); $i < $j; $i++ ) { + $seconds = $chunks[$i][0]; + $name = $chunks[$i][1]; + + if ( ( $count = floor( $interval / $seconds ) ) != 0 ) { + break; + } + } + + $output = sprintf( _n( $name[0], $name[1], $count, 'action-scheduler' ), $count ); + + if ( $i + 1 < $j ) { + $seconds2 = $chunks[$i + 1][0]; + $name2 = $chunks[$i + 1][1]; + + if ( ( $count2 = floor( ( $interval - ( $seconds * $count ) ) / $seconds2 ) ) != 0 ) { + // add to output var + $output .= ' '.sprintf( _n( $name2[0], $name2[1], $count2, 'action-scheduler' ), $count2 ); + } + } + + return $output; + } + + /** + * Filter search queries to allow searching by Claim ID (i.e. post_password). + * + * @param string $orderby MySQL orderby string. + * @param WP_Query $query Instance of a WP_Query object + * @return string MySQL orderby string. + */ + public function custom_orderby( $orderby, $query ){ + global $wpdb; + + if ( self::is_admin_page() && ! empty( $query->query['orderby'] ) && 'post_password' == $query->query['orderby'] ) { + $orderby = "$wpdb->posts.post_password " . $query->query['order']; + } + + return $orderby; + } + + /** + * Filter search queries to allow searching by Claim ID (i.e. post_password). + * + * @param string $search MySQL search string. + * @param WP_Query $query Instance of a WP_Query object + * @return string MySQL search string. + */ + public function search_post_password( $search, $query ) { + global $wpdb; + + if ( self::is_admin_page() && ! empty( $search ) ) { + + $search = ''; + + $searchand = ''; + $n = ! empty( $query->query_vars['exact'] ) ? '' : '%'; + foreach ( $query->query_vars['search_terms'] as $term ) { + $term = $wpdb->esc_like( esc_sql( $term ) ); + $search .= "{$searchand}(($wpdb->posts.post_title LIKE '{$n}{$term}{$n}') OR ($wpdb->posts.post_content LIKE '{$n}{$term}{$n}') OR ($wpdb->posts.post_password LIKE '{$n}{$term}{$n}'))"; + $searchand = ' AND '; + } + + if ( ! empty( $search ) ) { + $search = " AND ({$search}) "; + } + + } + + return $search; + } + + /** + * Change messages when a scheduled action is updated. + * + * @param array $messages + * @return array + */ + public function post_updated_messages( $messages ) { + global $post, $post_ID; + + $messages[ ActionScheduler_wpPostStore::POST_TYPE ] = array( + 0 => '', // Unused. Messages start at index 1. + 1 => __( 'Action updated.', 'action-scheduler' ), + 2 => __( 'Custom field updated.', 'action-scheduler' ), + 3 => __( 'Custom field deleted.', 'action-scheduler' ), + 4 => __( 'Action updated.', 'action-scheduler' ), + 5 => isset( $_GET['revision'] ) ? sprintf( __( 'Action restored to revision from %s', 'action-scheduler' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false, + 6 => __( 'Action scheduled.', 'action-scheduler' ), + 7 => __( 'Action saved.', 'action-scheduler' ), + 8 => __( 'Action submitted.', 'action-scheduler' ), + 9 => sprintf( __( 'Action scheduled for: <strong>%1$s</strong>', 'action-scheduler' ), date_i18n( __( 'M j, Y @ G:i', 'action-scheduler' ), strtotime( $post->post_date ) ) ), + 10 => __( 'Action draft updated.', 'action-scheduler' ), + ); + + return $messages; + } + + /** + * Check if the current request is for the Schedul Actions administration screen. + * + * @return bool + */ + private static function is_admin_page() { + if ( is_admin() && isset( $_GET['post_type'] ) && $_GET['post_type'] == ActionScheduler_wpPostStore::POST_TYPE ) { + return true; + } else { + return false; + } + } +} \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_CronSchedule.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_CronSchedule.php new file mode 100644 index 0000000000..029c0d53c3 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_CronSchedule.php @@ -0,0 +1,50 @@ +<?php + +/** + * Class ActionScheduler_CronSchedule + */ +class ActionScheduler_CronSchedule implements ActionScheduler_Schedule { + /** @var DateTime */ + private $start = NULL; + private $start_timestamp = 0; + /** @var CronExpression */ + private $cron = NULL; + + public function __construct( DateTime $start, CronExpression $cron ) { + $this->start = $start; + $this->cron = $cron; + } + + /** + * @param DateTime $after + * @return DateTime|null + */ + public function next( DateTime $after = NULL ) { + $after = empty($after) ? clone $this->start : clone $after; + return $this->cron->getNextRunDate($after, 0, false); + } + + /** + * @return bool + */ + public function is_recurring() { + return true; + } + + /** + * For PHP 5.2 compat, since DateTime objects can't be serialized + * @return array + */ + public function __sleep() { + $this->start_timestamp = $this->start->format('U'); + return array( + 'start_timestamp', + 'cron' + ); + } + + public function __wakeup() { + $this->start = as_get_datetime_object($this->start_timestamp); + } +} + diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_FatalErrorMonitor.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_FatalErrorMonitor.php new file mode 100644 index 0000000000..19bac0b14b --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_FatalErrorMonitor.php @@ -0,0 +1,54 @@ +<?php + +/** + * Class ActionScheduler_FatalErrorMonitor + */ +class ActionScheduler_FatalErrorMonitor { + /** @var ActionScheduler_ActionClaim */ + private $claim = NULL; + /** @var ActionScheduler_Store */ + private $store = NULL; + private $action_id = 0; + + public function __construct( ActionScheduler_Store $store ) { + $this->store = $store; + } + + public function attach( ActionScheduler_ActionClaim $claim ) { + $this->claim = $claim; + add_action( 'shutdown', array( $this, 'handle_unexpected_shutdown' ) ); + add_action( 'action_scheduler_before_execute', array( $this, 'track_current_action' ), 0, 1 ); + add_action( 'action_scheduler_after_execute', array( $this, 'untrack_action' ), 0, 0 ); + add_action( 'action_scheduler_failed_execution', array( $this, 'untrack_action' ), 0, 0 ); + } + + public function detach() { + $this->claim = NULL; + $this->untrack_action(); + remove_action( 'shutdown', array( $this, 'handle_unexpected_shutdown' ) ); + remove_action( 'action_scheduler_before_execute', array( $this, 'track_current_action' ), 0, 1 ); + remove_action( 'action_scheduler_after_execute', array( $this, 'untrack_action' ), 0, 0 ); + remove_action( 'action_scheduler_failed_execution', array( $this, 'untrack_action' ), 0, 0 ); + } + + public function track_current_action( $action_id ) { + $this->action_id = $action_id; + } + + public function untrack_action() { + $this->action_id = 0; + } + + public function handle_unexpected_shutdown() { + if ( $error = error_get_last() ) { + if ( in_array( $error['type'], array( E_ERROR, E_PARSE, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR ) ) ) { + if ( !empty($this->action_id) ) { + $this->store->mark_failure( $this->action_id ); + do_action( 'action_scheduler_unexpected_shutdown', $this->action_id, $error ); + } + } + $this->store->release_claim( $this->claim ); + } + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_FinishedAction.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_FinishedAction.php new file mode 100644 index 0000000000..b23a56c66b --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_FinishedAction.php @@ -0,0 +1,16 @@ +<?php + +/** + * Class ActionScheduler_FinishedAction + */ +class ActionScheduler_FinishedAction extends ActionScheduler_Action { + + public function execute() { + // don't execute + } + + public function is_finished() { + return TRUE; + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_IntervalSchedule.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_IntervalSchedule.php new file mode 100644 index 0000000000..eb68a967a4 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_IntervalSchedule.php @@ -0,0 +1,63 @@ +<?php + +/** + * Class ActionScheduler_IntervalSchedule + */ +class ActionScheduler_IntervalSchedule implements ActionScheduler_Schedule { + /** @var DateTime */ + private $start = NULL; + private $start_timestamp = 0; + private $interval_in_seconds = 0; + + public function __construct( DateTime $start, $interval ) { + $this->start = $start; + $this->interval_in_seconds = (int)$interval; + } + + /** + * @param DateTime $after + * + * @return DateTime|null + */ + public function next( DateTime $after = NULL ) { + $after = empty($after) ? as_get_datetime_object('@0') : clone $after; + if ( $after > $this->start ) { + $after->modify('+'.$this->interval_in_seconds.' seconds'); + return $after; + } + return clone $this->start; + } + + /** + * @return bool + */ + public function is_recurring() { + return true; + } + + /** + * @param DateTime $after + * + * @return DateTime|null + */ + public function interval_in_seconds() { + return $this->interval_in_seconds; + } + + /** + * For PHP 5.2 compat, since DateTime objects can't be serialized + * @return array + */ + public function __sleep() { + $this->start_timestamp = $this->start->format('U'); + return array( + 'start_timestamp', + 'interval_in_seconds' + ); + } + + public function __wakeup() { + $this->start = as_get_datetime_object($this->start_timestamp); + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_LogEntry.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_LogEntry.php new file mode 100644 index 0000000000..755cd6ddf9 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_LogEntry.php @@ -0,0 +1,23 @@ +<?php + +/** + * Class ActionScheduler_LogEntry + */ +class ActionScheduler_LogEntry { + protected $action_id = ''; + protected $message = ''; + + public function __construct( $action_id, $message ) { + $this->action_id = $action_id; + $this->message = $message; + } + + public function get_action_id() { + return $this->action_id; + } + + public function get_message() { + return $this->message; + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_Logger.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_Logger.php new file mode 100644 index 0000000000..601e5679c9 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_Logger.php @@ -0,0 +1,47 @@ +<?php + +/** + * Class ActionScheduler_Logger + * @codeCoverageIgnore + */ +abstract class ActionScheduler_Logger { + private static $logger = NULL; + + /** + * @return ActionScheduler_Logger + */ + public static function instance() { + if ( empty(self::$logger) ) { + $class = apply_filters('action_scheduler_logger_class', 'ActionScheduler_wpCommentLogger'); + self::$logger = new $class(); + } + return self::$logger; + } + + /** + * @param string $action_id + * @param string $message + * @param DateTime $date + * + * @return string The log entry ID + */ + abstract public function log( $action_id, $message, DateTime $date = NULL ); + + /** + * @param string $entry_id + * + * @return ActionScheduler_LogEntry + */ + abstract public function get_entry( $entry_id ); + + /** + * @param string $action_id + * + * @return ActionScheduler_LogEntry[] + */ + abstract public function get_logs( $action_id ); + + abstract public function init(); + +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_NullAction.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_NullAction.php new file mode 100644 index 0000000000..cd5dc3b0f9 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_NullAction.php @@ -0,0 +1,16 @@ +<?php + +/** + * Class ActionScheduler_NullAction + */ +class ActionScheduler_NullAction extends ActionScheduler_Action { + + public function __construct( $hook = '', array $args = array(), ActionScheduler_Schedule $schedule = NULL ) { + $this->set_schedule( new ActionScheduler_NullSchedule() ); + } + + public function execute() { + // don't execute + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_NullLogEntry.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_NullLogEntry.php new file mode 100644 index 0000000000..6f8f218aab --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_NullLogEntry.php @@ -0,0 +1,11 @@ +<?php + +/** + * Class ActionScheduler_NullLogEntry + */ +class ActionScheduler_NullLogEntry extends ActionScheduler_LogEntry { + public function __construct( $action_id = '', $message = '' ) { + // nothing to see here + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_NullSchedule.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_NullSchedule.php new file mode 100644 index 0000000000..fab1538d6a --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_NullSchedule.php @@ -0,0 +1,19 @@ +<?php + +/** + * Class ActionScheduler_NullSchedule + */ +class ActionScheduler_NullSchedule implements ActionScheduler_Schedule { + + public function next( DateTime $after = NULL ) { + return NULL; + } + + /** + * @return bool + */ + public function is_recurring() { + return false; + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_QueueCleaner.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_QueueCleaner.php new file mode 100644 index 0000000000..cfcfa4bc6a --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_QueueCleaner.php @@ -0,0 +1,72 @@ +<?php + +/** + * Class ActionScheduler_QueueCleaner + */ +class ActionScheduler_QueueCleaner { + /** @var ActionScheduler_Store */ + private $store = NULL; + + private $month_in_seconds = 2678400; // 31 days + private $five_minutes = 300; + + public function __construct( ActionScheduler_Store $store = NULL ) { + $this->store = $store ? $store : ActionScheduler_Store::instance(); + } + + public function delete_old_actions() { + $lifespan = apply_filters( 'action_scheduler_retention_period', $this->month_in_seconds ); + $cutoff = as_get_datetime_object($lifespan.' seconds ago'); + + $actions_to_delete = $this->store->query_actions( array( + 'status' => ActionScheduler_Store::STATUS_COMPLETE, + 'modified' => $cutoff, + 'modified_compare' => '<=', + 'per_page' => apply_filters( 'action_scheduler_cleanup_batch_size', 20 ), + ) ); + + foreach ( $actions_to_delete as $action_id ) { + $this->store->delete_action( $action_id ); + } + } + + public function reset_timeouts() { + $timeout = apply_filters( 'action_scheduler_timeout_period', $this->five_minutes ); + if ( $timeout < 0 ) { + return; + } + $cutoff = as_get_datetime_object($timeout.' seconds ago'); + $actions_to_reset = $this->store->query_actions( array( + 'status' => ActionScheduler_Store::STATUS_PENDING, + 'modified' => $cutoff, + 'modified_compare' => '<=', + 'claimed' => TRUE, + 'per_page' => apply_filters( 'action_scheduler_cleanup_batch_size', 20 ), + ) ); + + foreach ( $actions_to_reset as $action_id ) { + $this->store->unclaim_action( $action_id ); + do_action( 'action_scheduler_reset_action', $action_id ); + } + } + + public function mark_failures() { + $timeout = apply_filters( 'action_scheduler_failure_period', $this->five_minutes ); + if ( $timeout < 0 ) { + return; + } + $cutoff = as_get_datetime_object($timeout.' seconds ago'); + $actions_to_reset = $this->store->query_actions( array( + 'status' => ActionScheduler_Store::STATUS_RUNNING, + 'modified' => $cutoff, + 'modified_compare' => '<=', + 'per_page' => apply_filters( 'action_scheduler_cleanup_batch_size', 20 ), + ) ); + + foreach ( $actions_to_reset as $action_id ) { + $this->store->mark_failure( $action_id ); + do_action( 'action_scheduler_failed_action', $action_id, $timeout ); + } + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_QueueRunner.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_QueueRunner.php new file mode 100644 index 0000000000..99e8f06790 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_QueueRunner.php @@ -0,0 +1,142 @@ +<?php + +/** + * Class ActionScheduler_QueueRunner + */ +class ActionScheduler_QueueRunner { + const WP_CRON_HOOK = 'action_scheduler_run_queue'; + + const WP_CRON_SCHEDULE = 'every_minute'; + + /** @var ActionScheduler_QueueRunner */ + private static $runner = NULL; + /** @var ActionScheduler_Store */ + private $store = NULL; + + /** @var ActionScheduler_FatalErrorMonitor */ + private $monitor = NULL; + + /** + * @return ActionScheduler_QueueRunner + * @codeCoverageIgnore + */ + public static function instance() { + if ( empty(self::$runner) ) { + $class = apply_filters('action_scheduler_queue_runner_class', 'ActionScheduler_QueueRunner'); + self::$runner = new $class(); + } + return self::$runner; + } + + public function __construct( ActionScheduler_Store $store = NULL ) { + $this->store = $store ? $store : ActionScheduler_Store::instance(); + } + + /** + * @codeCoverageIgnore + */ + public function init() { + + add_filter( 'cron_schedules', array( self::instance(), 'add_wp_cron_schedule' ) ); + + if ( !wp_next_scheduled(self::WP_CRON_HOOK) ) { + $schedule = apply_filters( 'action_scheduler_run_schedule', self::WP_CRON_SCHEDULE ); + wp_schedule_event( time(), $schedule, self::WP_CRON_HOOK ); + } + + add_action( self::WP_CRON_HOOK, array( self::instance(), 'run' ) ); + } + + public function run() { + @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) ); + @set_time_limit( apply_filters( 'action_scheduler_queue_runner_time_limit', 600 ) ); + do_action( 'action_scheduler_before_process_queue' ); + $this->run_cleanup(); + $count = 0; + if ( $this->store->get_claim_count() < apply_filters( 'action_scheduler_queue_runner_concurrent_batches', 5 ) ) { + $batch_size = apply_filters( 'action_scheduler_queue_runner_batch_size', 25 ); + $this->monitor = new ActionScheduler_FatalErrorMonitor( $this->store ); + $count = $this->do_batch( $batch_size ); + unset( $this->monitor ); + } + + do_action( 'action_scheduler_after_process_queue' ); + return $count; + } + + protected function run_cleanup() { + $cleaner = new ActionScheduler_QueueCleaner( $this->store ); + $cleaner->delete_old_actions(); + $cleaner->reset_timeouts(); + $cleaner->mark_failures(); + } + + protected function do_batch( $size = 100 ) { + $claim = $this->store->stake_claim($size); + $this->monitor->attach($claim); + $processed_actions = 0; + foreach ( $claim->get_actions() as $action_id ) { + // bail if we lost the claim + if ( ! in_array( $action_id, $this->store->find_actions_by_claim_id( $claim->get_id() ) ) ) { + break; + } + $this->process_action( $action_id ); + $processed_actions++; + } + $this->store->release_claim($claim); + $this->monitor->detach(); + $this->clear_caches(); + return $processed_actions; + } + + public function process_action( $action_id ) { + try { + do_action( 'action_scheduler_before_execute', $action_id ); + $action = $this->store->fetch_action( $action_id ); + $this->store->log_execution( $action_id ); + $action->execute(); + do_action( 'action_scheduler_after_execute', $action_id ); + $this->store->mark_complete( $action_id ); + } catch ( Exception $e ) { + $this->store->mark_failure( $action_id ); + do_action( 'action_scheduler_failed_execution', $action_id, $e ); + } + $this->schedule_next_instance( $action ); + } + + protected function schedule_next_instance( ActionScheduler_Action $action ) { + + $schedule = $action->get_schedule(); + $next = $schedule->next( as_get_datetime_object() ); + + if ( ! is_null( $next ) && $schedule->is_recurring() ) { + $this->store->save_action( $action, $next ); + } + } + + /** + * Running large batches can eat up memory, as WP adds data to its object cache. + * + * If using a persistent object store, this has the side effect of flushing that + * as well, so this is disabled by default. To enable: + * + * add_filter( 'action_scheduler_queue_runner_flush_cache', '__return_true' ); + * + * @return void + */ + protected function clear_caches() { + if ( ! wp_using_ext_object_cache() || apply_filters( 'action_scheduler_queue_runner_flush_cache', false ) ) { + wp_cache_flush(); + } + } + + public function add_wp_cron_schedule( $schedules ) { + $schedules['every_minute'] = array( + 'interval' => 60, // in seconds + 'display' => __( 'Every minute' ), + ); + + return $schedules; + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_Schedule.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_Schedule.php new file mode 100644 index 0000000000..d61a9f7c92 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_Schedule.php @@ -0,0 +1,18 @@ +<?php + +/** + * Class ActionScheduler_Schedule + */ +interface ActionScheduler_Schedule { + /** + * @param DateTime $after + * @return DateTime|null + */ + public function next( DateTime $after = NULL ); + + /** + * @return bool + */ + public function is_recurring(); +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_SimpleSchedule.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_SimpleSchedule.php new file mode 100644 index 0000000000..8f621e193a --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_SimpleSchedule.php @@ -0,0 +1,45 @@ +<?php + +/** + * Class ActionScheduler_SimpleSchedule + */ +class ActionScheduler_SimpleSchedule implements ActionScheduler_Schedule { + private $date = NULL; + private $timestamp = 0; + public function __construct( DateTime $date ) { + $this->date = clone $date; + } + + /** + * @param DateTime $after + * + * @return DateTime|null + */ + public function next( DateTime $after = NULL ) { + $after = empty($after) ? as_get_datetime_object('@0') : $after; + return ( $after > $this->date ) ? NULL : clone $this->date; + } + + /** + * @return bool + */ + public function is_recurring() { + return false; + } + + /** + * For PHP 5.2 compat, since DateTime objects can't be serialized + * @return array + */ + public function __sleep() { + $this->timestamp = $this->date->format('U'); + return array( + 'timestamp', + ); + } + + public function __wakeup() { + $this->date = as_get_datetime_object($this->timestamp); + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_Store.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_Store.php new file mode 100644 index 0000000000..2d4b973a37 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_Store.php @@ -0,0 +1,128 @@ +<?php + +/** + * Class ActionScheduler_Store + * @codeCoverageIgnore + */ +abstract class ActionScheduler_Store { + const STATUS_COMPLETE = 'complete'; + const STATUS_PENDING = 'pending'; + const STATUS_RUNNING = 'in-progress'; + const STATUS_FAILED = 'failed'; + + /** @var ActionScheduler_Store */ + private static $store = NULL; + + /** + * @param ActionScheduler_Action $action + * @param DateTime $date Optional date of the first instance + * to store. Otherwise uses the first date of the action's + * schedule. + * + * @return string The action ID + */ + abstract public function save_action( ActionScheduler_Action $action, DateTime $date = NULL ); + + /** + * @param string $action_id + * + * @return ActionScheduler_Action + */ + abstract public function fetch_action( $action_id ); + + /** + * @param string $hook + * @param array $params + * @return string ID of the next action matching the criteria + */ + abstract public function find_action( $hook, $params = array() ); + + /** + * @param array $query + * @return array The IDs of actions matching the query + */ + abstract public function query_actions( $query = array() ); + + /** + * @param string $action_id + * + * @return void + */ + abstract public function cancel_action( $action_id ); + + /** + * @param string $action_id + * + * @return void + */ + abstract public function delete_action( $action_id ); + + /** + * @param string $action_id + * + * @return DateTime The date the action is schedule to run, or the date that it ran. + */ + abstract public function get_date( $action_id ); + + + /** + * @param int $max_actions + * @param DateTime $before_date Claim only actions schedule before the given date. Defaults to now. + * + * @return ActionScheduler_ActionClaim + */ + abstract public function stake_claim( $max_actions = 10, DateTime $before_date = NULL ); + + /** + * @return int + */ + abstract public function get_claim_count(); + + /** + * @param ActionScheduler_ActionClaim $claim + * + * @return void + */ + abstract public function release_claim( ActionScheduler_ActionClaim $claim ); + + /** + * @param string $action_id + * + * @return void + */ + abstract public function unclaim_action( $action_id ); + + /** + * @param string $action_id + * + * @return void + */ + abstract public function mark_failure( $action_id ); + + /** + * @param string $action_id + * @return void + */ + abstract public function log_execution( $action_id ); + + /** + * @param string $action_id + * + * @return void + */ + abstract public function mark_complete( $action_id ); + + public function init() {} + + /** + * @return ActionScheduler_Store + */ + public static function instance() { + if ( empty(self::$store) ) { + $class = apply_filters('action_scheduler_store_class', 'ActionScheduler_wpPostStore'); + self::$store = new $class(); + } + return self::$store; + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_TimezoneHelper.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_TimezoneHelper.php new file mode 100644 index 0000000000..0c8d6e4b0c --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_TimezoneHelper.php @@ -0,0 +1,44 @@ +<?php + +/** + * Class ActionScheduler_TimezoneHelper + */ +abstract class ActionScheduler_TimezoneHelper { + private static $local_timezone = NULL; + public static function get_local_timezone( $reset = FALSE ) { + if ( $reset ) { + self::$local_timezone = NULL; + } + if ( !isset(self::$local_timezone) ) { + $tzstring = get_option('timezone_string'); + + if ( empty($tzstring) ) { + $gmt_offset = get_option('gmt_offset'); + if ( $gmt_offset == 0 ) { + $tzstring = 'UTC'; + } else { + $gmt_offset *= HOUR_IN_SECONDS; + $tzstring = timezone_name_from_abbr('', $gmt_offset); + if ( false === $tzstring ) { + $is_dst = date( 'I' ); + foreach ( timezone_abbreviations_list() as $abbr ) { + foreach ( $abbr as $city ) { + if ( $city['dst'] == $is_dst && $city['offset'] == $gmt_offset ) { + $tzstring = $city['timezone_id']; + break 2; + } + } + } + } + if ( false === $tzstring ) { + $tzstring = 'UTC'; + } + } + } + + self::$local_timezone = new DateTimeZone($tzstring); + } + return self::$local_timezone; + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_Versions.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_Versions.php new file mode 100644 index 0000000000..915c2e6329 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_Versions.php @@ -0,0 +1,62 @@ +<?php + +/** + * Class ActionScheduler_Versions + */ +class ActionScheduler_Versions { + /** + * @var ActionScheduler_Versions + */ + private static $instance = NULL; + + private $versions = array(); + + public function register( $version_string, $initialization_callback ) { + if ( isset($this->versions[$version_string]) ) { + return FALSE; + } + $this->versions[$version_string] = $initialization_callback; + return TRUE; + } + + public function get_versions() { + return $this->versions; + } + + public function latest_version() { + $keys = array_keys($this->versions); + if ( empty($keys) ) { + return false; + } + uasort( $keys, 'version_compare' ); + return end($keys); + } + + public function latest_version_callback() { + $latest = $this->latest_version(); + if ( empty($latest) || !isset($this->versions[$latest]) ) { + return '__return_null'; + } + return $this->versions[$latest]; + } + + /** + * @return ActionScheduler_Versions + * @codeCoverageIgnore + */ + public static function instance() { + if ( empty(self::$instance) ) { + self::$instance = new self(); + } + return self::$instance; + } + + /** + * @codeCoverageIgnore + */ + public static function initialize_latest_version() { + $self = self::instance(); + call_user_func($self->latest_version_callback()); + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_wpCommentLogger.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_wpCommentLogger.php new file mode 100644 index 0000000000..58137a0f4b --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_wpCommentLogger.php @@ -0,0 +1,279 @@ +<?php + +/** + * Class ActionScheduler_wpCommentLogger + */ +class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger { + const AGENT = 'ActionScheduler'; + const TYPE = 'action_log'; + + /** + * @param string $action_id + * @param string $message + * @param DateTime $date + * + * @return string The log entry ID + */ + public function log( $action_id, $message, DateTime $date = NULL ) { + if ( empty($date) ) { + $date = as_get_datetime_object(); + } else { + $date = clone $date; + } + $comment_id = $this->create_wp_comment( $action_id, $message, $date ); + return $comment_id; + } + + protected function create_wp_comment( $action_id, $message, DateTime $date ) { + $comment_date_gmt = $date->format('Y-m-d H:i:s'); + $date->setTimezone( ActionScheduler_TimezoneHelper::get_local_timezone() ); + $comment_data = array( + 'comment_post_ID' => $action_id, + 'comment_date' => $date->format('Y-m-d H:i:s'), + 'comment_date_gmt' => $comment_date_gmt, + 'comment_author' => self::AGENT, + 'comment_content' => $message, + 'comment_agent' => self::AGENT, + 'comment_type' => self::TYPE, + ); + return wp_insert_comment($comment_data); + } + + /** + * @param string $entry_id + * + * @return ActionScheduler_LogEntry + */ + public function get_entry( $entry_id ) { + $comment = $this->get_comment( $entry_id ); + if ( empty($comment) || $comment->comment_type != self::TYPE ) { + return new ActionScheduler_NullLogEntry(); + } + return new ActionScheduler_LogEntry( $comment->comment_post_ID, $comment->comment_content, $comment->comment_type ); + } + + /** + * @param string $action_id + * + * @return ActionScheduler_LogEntry[] + */ + public function get_logs( $action_id ) { + $status = 'all'; + if ( get_post_status($action_id) == 'trash' ) { + $status = 'post-trashed'; + } + $comments = get_comments(array( + 'post_id' => $action_id, + 'orderby' => 'comment_date_gmt', + 'order' => 'ASC', + 'type' => self::TYPE, + 'status' => $status, + )); + $logs = array(); + foreach ( $comments as $c ) { + $entry = $this->get_entry( $c ); + if ( !empty($entry) ) { + $logs[] = $entry; + } + } + return $logs; + } + + protected function get_comment( $comment_id ) { + return get_comment( $comment_id ); + } + + + + /** + * @param WP_Comment_Query $query + * + * @return void + */ + public function filter_comment_queries( $query ) { + foreach ( array('ID', 'parent', 'post_author', 'post_name', 'post_parent', 'type', 'post_type', 'post_id', 'post_ID') as $key ) { + if ( !empty($query->query_vars[$key]) ) { + return; // don't slow down queries that wouldn't include action_log comments anyway + } + } + $query->query_vars['action_log_filter'] = TRUE; + add_filter( 'comments_clauses', array( $this, 'filter_comment_query_clauses' ), 10, 2 ); + } + + /** + * @param array $clauses + * @param WP_Comment_Query $query + * + * @return array + */ + public function filter_comment_query_clauses( $clauses, $query ) { + if ( !empty($query->query_vars['action_log_filter']) ) { + $clauses['where'] .= $this->get_where_clause(); + } + return $clauses; + } + + /** + * Make sure Action Scheduler logs are excluded from comment feeds, which use WP_Query, not + * the WP_Comment_Query class handled by @see self::filter_comment_queries(). + * + * @param string $where + * @param WP_Query $query + * + * @return string + */ + public function filter_comment_feed( $where, $query ) { + if ( is_comment_feed() ) { + $where .= $this->get_where_clause(); + } + return $where; + } + + /** + * Return a SQL clause to exclude Action Scheduler comments. + * + * @return string + */ + protected function get_where_clause() { + global $wpdb; + return sprintf( " AND {$wpdb->comments}.comment_type != '%s'", self::TYPE ); + } + + /** + * Remove action log entries from wp_count_comments() + * + * @param array $stats + * @param int $post_id + * + * @return object + */ + public function filter_comment_count( $stats, $post_id ) { + global $wpdb; + + if ( 0 === $post_id ) { + $stats = $this->get_comment_count(); + } + + return $stats; + } + + /** + * Retrieve the comment counts from our cache, or the database if the cached version isn't set. + * + * @return object + */ + protected function get_comment_count() { + global $wpdb; + + $stats = get_transient( 'as_comment_count' ); + + if ( ! $stats ) { + $stats = array(); + + $count = $wpdb->get_results( "SELECT comment_approved, COUNT( * ) AS num_comments FROM {$wpdb->comments} WHERE comment_type NOT IN('order_note','action_log') GROUP BY comment_approved", ARRAY_A ); + + $total = 0; + $stats = array(); + $approved = array( '0' => 'moderated', '1' => 'approved', 'spam' => 'spam', 'trash' => 'trash', 'post-trashed' => 'post-trashed' ); + + foreach ( (array) $count as $row ) { + // Don't count post-trashed toward totals + if ( 'post-trashed' != $row['comment_approved'] && 'trash' != $row['comment_approved'] ) { + $total += $row['num_comments']; + } + if ( isset( $approved[ $row['comment_approved'] ] ) ) { + $stats[ $approved[ $row['comment_approved'] ] ] = $row['num_comments']; + } + } + + $stats['total_comments'] = $total; + $stats['all'] = $total; + + foreach ( $approved as $key ) { + if ( empty( $stats[ $key ] ) ) { + $stats[ $key ] = 0; + } + } + + $stats = (object) $stats; + set_transient( 'as_comment_count', $stats ); + } + + return $stats; + } + + /** + * Delete comment count cache whenever there is new comment or the status of a comment changes. Cache + * will be regenerated next time ActionScheduler_wpCommentLogger::filter_comment_count() is called. + * + * @return void + */ + public function delete_comment_count_cache() { + delete_transient( 'as_comment_count' ); + } + + /** + * @codeCoverageIgnore + */ + public function init() { + add_action( 'action_scheduler_before_process_queue', array( $this, 'disable_comment_counting' ), 10, 0 ); + add_action( 'action_scheduler_after_process_queue', array( $this, 'enable_comment_counting' ), 10, 0 ); + add_action( 'action_scheduler_stored_action', array( $this, 'log_stored_action' ), 10, 1 ); + add_action( 'action_scheduler_canceled_action', array( $this, 'log_canceled_action' ), 10, 1 ); + add_action( 'action_scheduler_before_execute', array( $this, 'log_started_action' ), 10, 1 ); + add_action( 'action_scheduler_after_execute', array( $this, 'log_completed_action' ), 10, 1 ); + add_action( 'action_scheduler_failed_execution', array( $this, 'log_failed_action' ), 10, 2 ); + add_action( 'action_scheduler_failed_action', array( $this, 'log_timed_out_action' ), 10, 2 ); + add_action( 'action_scheduler_unexpected_shutdown', array( $this, 'log_unexpected_shutdown' ), 10, 2 ); + add_action( 'action_scheduler_reset_action', array( $this, 'log_reset_action' ), 10, 1 ); + add_action( 'pre_get_comments', array( $this, 'filter_comment_queries' ), 10, 1 ); + add_action( 'wp_count_comments', array( $this, 'filter_comment_count' ), 20, 2 ); // run after WC_Comments::wp_count_comments() to make sure we exclude order notes and action logs + add_action( 'comment_feed_where', array( $this, 'filter_comment_feed' ), 10, 2 ); + + // Delete comments count cache whenever there is a new comment or a comment status changes + add_action( 'wp_insert_comment', array( $this, 'delete_comment_count_cache' ) ); + add_action( 'wp_set_comment_status', array( $this, 'delete_comment_count_cache' ) ); + } + + public function disable_comment_counting() { + wp_defer_comment_counting(true); + } + public function enable_comment_counting() { + wp_defer_comment_counting(false); + } + + public function log_stored_action( $action_id ) { + $this->log( $action_id, __('action created', 'action-scheduler') ); + } + + public function log_canceled_action( $action_id ) { + $this->log( $action_id, __('action canceled', 'action-scheduler') ); + } + + public function log_started_action( $action_id ) { + $this->log( $action_id, __('action started', 'action-scheduler') ); + } + + public function log_completed_action( $action_id ) { + $this->log( $action_id, __('action complete', 'action-scheduler') ); + } + + public function log_failed_action( $action_id, Exception $exception ) { + $this->log( $action_id, sprintf(__('action failed: %s', 'action-scheduler'), $exception->getMessage() )); + } + + public function log_timed_out_action( $action_id, $timeout) { + $this->log( $action_id, sprintf( __('action timed out after %s seconds', 'action-scheduler'), $timeout ) ); + } + + public function log_unexpected_shutdown( $action_id, $error ) { + if ( !empty($error) ) { + $this->log( $action_id, sprintf(__('unexpected shutdown: PHP Fatal error %s in %s on line %s', 'action-scheduler'), $error['message'], $error['file'], $error['line'] ) ); + } + } + + public function log_reset_action( $action_id ) { + $this->log( $action_id, __('action reset', 'action_scheduler') ); + } + +} diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_wpPostStore.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_wpPostStore.php new file mode 100644 index 0000000000..af54a36ea8 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_wpPostStore.php @@ -0,0 +1,514 @@ +<?php + +/** + * Class ActionScheduler_wpPostStore + */ +class ActionScheduler_wpPostStore extends ActionScheduler_Store { + const POST_TYPE = 'scheduled-action'; + const GROUP_TAXONOMY = 'action-group'; + const SCHEDULE_META_KEY = '_action_manager_schedule'; + + /** @var DateTimeZone */ + protected $local_timezone = NULL; + + public function save_action( ActionScheduler_Action $action, DateTime $date = NULL ){ + try { + $post_array = $this->create_post_array( $action, $date ); + $post_id = $this->save_post_array( $post_array ); + $this->save_post_schedule( $post_id, $action->get_schedule() ); + $this->save_action_group( $post_id, $action->get_group() ); + do_action( 'action_scheduler_stored_action', $post_id ); + return $post_id; + } catch ( Exception $e ) { + throw new RuntimeException( sprintf( __('Error saving action: %s', 'action-scheduler'), $e->getMessage() ), 0 ); + } + } + + protected function create_post_array( ActionScheduler_Action $action, DateTime $date = NULL ) { + $post = array( + 'post_type' => self::POST_TYPE, + 'post_title' => $action->get_hook(), + 'post_content' => json_encode($action->get_args()), + 'post_status' => ( $action->is_finished() ? 'publish' : 'pending' ), + 'post_date_gmt' => $this->get_timestamp($action, $date), + 'post_date' => $this->get_local_timestamp($action, $date), + ); + return $post; + } + + protected function get_timestamp( ActionScheduler_Action $action, DateTime $date = NULL ) { + $next = is_null($date) ? $action->get_schedule()->next() : $date; + if ( !$next ) { + throw new InvalidArgumentException(__('Invalid schedule. Cannot save action.', 'action-scheduler')); + } + $next->setTimezone(new DateTimeZone('UTC')); + return $next->format('Y-m-d H:i:s'); + } + + protected function get_local_timestamp( ActionScheduler_Action $action, DateTime $date = NULL ) { + $next = is_null($date) ? $action->get_schedule()->next() : $date; + if ( !$next ) { + throw new InvalidArgumentException(__('Invalid schedule. Cannot save action.', 'action-scheduler')); + } + $next->setTimezone($this->get_local_timezone()); + return $next->format('Y-m-d H:i:s'); + } + + protected function get_local_timezone() { + return ActionScheduler_TimezoneHelper::get_local_timezone(); + } + + protected function save_post_array( $post_array ) { + add_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10, 1 ); + $post_id = wp_insert_post($post_array); + remove_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10, 1 ); + + if ( is_wp_error($post_id) || empty($post_id) ) { + throw new RuntimeException(__('Unable to save action.', 'action-scheduler')); + } + return $post_id; + } + + public function filter_insert_post_data( $postdata ) { + if ( $postdata['post_type'] == self::POST_TYPE ) { + $postdata['post_author'] = 0; + if ( $postdata['post_status'] == 'future' ) { + $postdata['post_status'] = 'publish'; + } + } + return $postdata; + } + + protected function save_post_schedule( $post_id, $schedule ) { + update_post_meta( $post_id, self::SCHEDULE_META_KEY, $schedule ); + } + + protected function save_action_group( $post_id, $group ) { + if ( empty($group) ) { + wp_set_object_terms( $post_id, array(), self::GROUP_TAXONOMY, FALSE ); + } else { + wp_set_object_terms( $post_id, array($group), self::GROUP_TAXONOMY, FALSE ); + } + } + + public function fetch_action( $action_id ) { + $post = $this->get_post( $action_id ); + if ( empty($post) || $post->post_type != self::POST_TYPE || $post->post_status == 'trash' ) { + return $this->get_null_action(); + } + return $this->make_action_from_post($post); + } + + protected function get_post( $action_id ) { + if ( empty($action_id) ) { + return NULL; + } + return get_post($action_id); + } + + protected function get_null_action() { + return new ActionScheduler_NullAction(); + } + + protected function make_action_from_post( $post ) { + $hook = $post->post_title; + $args = json_decode( $post->post_content, true ); + $schedule = get_post_meta( $post->ID, self::SCHEDULE_META_KEY, true ); + if ( empty($schedule) ) { + $schedule = new ActionScheduler_NullSchedule(); + } + $group = wp_get_object_terms( $post->ID, self::GROUP_TAXONOMY, array('fields' => 'names') ); + $group = empty( $group ) ? '' : reset($group); + if ( $post->post_status == 'pending' ) { + $action = new ActionScheduler_Action( $hook, $args, $schedule, $group ); + } else { + $action = new ActionScheduler_FinishedAction( $hook, $args, $schedule, $group ); + } + return $action; + } + + /** + * @param string $hook + * @param array $params + * + * @return string ID of the next action matching the criteria or NULL if not found + */ + public function find_action( $hook, $params = array() ) { + $params = wp_parse_args( $params, array( + 'args' => NULL, + 'status' => ActionScheduler_Store::STATUS_PENDING, + 'group' => '', + )); + /** @var wpdb $wpdb */ + global $wpdb; + $query = "SELECT p.ID FROM {$wpdb->posts} p"; + $args = array(); + if ( !empty($params['group']) ) { + $query .= " INNER JOIN {$wpdb->term_relationships} tr ON tr.object_id=p.ID"; + $query .= " INNER JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id=tt.term_taxonomy_id"; + $query .= " INNER JOIN {$wpdb->terms} t ON tt.term_id=t.term_id AND t.slug=%s"; + $args[] = $params['group']; + } + $query .= " WHERE p.post_title=%s"; + $args[] = $hook; + $query .= " AND p.post_type=%s"; + $args[] = self::POST_TYPE; + if ( !is_null($params['args']) ) { + $query .= " AND p.post_content=%s"; + $args[] = json_encode($params['args']); + } + switch ( $params['status'] ) { + case self::STATUS_COMPLETE: + $query .= " AND p.post_status='publish'"; + $order = 'DESC'; // Find the most recent action that matches + break; + case self::STATUS_PENDING: + $query .= " AND p.post_status='pending'"; + $order = 'ASC'; // Find the next action that matches + break; + case self::STATUS_RUNNING: + case self::STATUS_FAILED: + $query .= " AND p.post_status=%s"; + $args[] = $params['status']; + $order = 'DESC'; // Find the most recent action that matches + break; + default: + $order = 'ASC'; + break; + } + $query .= " ORDER BY post_date_gmt $order LIMIT 1"; + + $query = $wpdb->prepare( $query, $args ); + + $id = $wpdb->get_var($query); + return $id; + } + + /** + * @param array $query + * @return array The IDs of actions matching the query + */ + public function query_actions( $query = array() ) { + $query = wp_parse_args( $query, array( + 'hook' => '', + 'args' => NULL, + 'date' => NULL, + 'date_compare' => '<=', + 'modified' => NULL, + 'modified_compare' => '<=', + 'group' => '', + 'status' => '', + 'claimed' => NULL, + 'per_page' => 5, + 'offset' => 0, + 'orderby' => 'date', + 'order' => 'ASC', + ) ); + + /** @var wpdb $wpdb */ + global $wpdb; + $sql = "SELECT p.ID FROM {$wpdb->posts} p"; + $sql_params = array(); + if ( !empty($query['group']) ) { + $sql .= " INNER JOIN {$wpdb->term_relationships} tr ON tr.object_id=p.ID"; + $sql .= " INNER JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id=tt.term_taxonomy_id"; + $sql .= " INNER JOIN {$wpdb->terms} t ON tt.term_id=t.term_id AND t.slug=%s"; + $sql_params[] = $query['group']; + } + $sql .= " WHERE post_type=%s"; + $sql_params[] = self::POST_TYPE; + if ( $query['hook'] ) { + $sql .= " AND p.post_title=%s"; + $sql_params[] = $query['hook']; + } + if ( !is_null($query['args']) ) { + $sql .= " AND p.post_content=%s"; + $sql_params[] = json_encode($query['args']); + } + + switch ( $query['status'] ) { + case self::STATUS_COMPLETE: + $sql .= " AND p.post_status='publish'"; + break; + case self::STATUS_PENDING: + case self::STATUS_RUNNING: + case self::STATUS_FAILED: + $sql .= " AND p.post_status=%s"; + $sql_params[] = $query['status']; + break; + } + + if ( $query['date'] instanceof DateTime ) { + $date = clone $query['date']; + $date->setTimezone( new DateTimeZone('UTC') ); + $date_string = $date->format('Y-m-d H:i:s'); + $comparator = $this->validate_sql_comparator($query['date_compare']); + $sql .= " AND p.post_date_gmt $comparator %s"; + $sql_params[] = $date_string; + } + + if ( $query['modified'] instanceof DateTime ) { + $modified = clone $query['modified']; + $modified->setTimezone( new DateTimeZone('UTC') ); + $date_string = $modified->format('Y-m-d H:i:s'); + $comparator = $this->validate_sql_comparator($query['modified_compare']); + $sql .= " AND p.post_modified_gmt $comparator %s"; + $sql_params[] = $date_string; + } + + if ( $query['claimed'] === TRUE ) { + $sql .= " AND p.post_password != ''"; + } elseif ( $query['claimed'] === FALSE ) { + $sql .= " AND p.post_password = ''"; + } elseif ( !is_null($query['claimed']) ) { + $sql .= " AND p.post_password = %s"; + $sql_params[] = $query['claimed']; + } + + switch ( $query['orderby'] ) { + case 'hook': + $orderby = 'p.title'; + break; + case 'group': + $orderby = 't.name'; + break; + case 'modified': + $orderby = 'p.post_modified'; + break; + case 'date': + default: + $orderby = 'p.post_date_gmt'; + break; + } + if ( strtoupper($query['order']) == 'ASC' ) { + $order = 'ASC'; + } else { + $order = 'DESC'; + } + $sql .= " ORDER BY $orderby $order"; + if ( $query['per_page'] > 0 ) { + $sql .= " LIMIT %d, %d"; + $sql_params[] = $query['offset']; + $sql_params[] = $query['per_page']; + } + + $sql = $wpdb->prepare( $sql, $sql_params ); + + $id = $wpdb->get_col($sql); + return $id; + } + + private function validate_sql_comparator( $comp ) { + if ( in_array($comp, array('!=', '>', '>=', '<', '<=', '=')) ) { + return $comp; + } + return '='; + } + + /** + * @param string $action_id + * + * @throws InvalidArgumentException + * @return void + */ + public function cancel_action( $action_id ) { + $post = get_post($action_id); + if ( empty($post) || ($post->post_type != self::POST_TYPE) ) { + throw new InvalidArgumentException(sprintf(__('Unidentified action %s', 'action-scheduler'), $action_id)); + } + do_action( 'action_scheduler_canceled_action', $action_id ); + wp_trash_post($action_id); + } + + public function delete_action( $action_id ) { + $post = get_post($action_id); + if ( empty($post) || ($post->post_type != self::POST_TYPE) ) { + throw new InvalidArgumentException(sprintf(__('Unidentified action %s', 'action-scheduler'), $action_id)); + } + do_action( 'action_scheduler_deleted_action', $action_id ); + wp_delete_post($action_id, TRUE); + } + + /** + * @param string $action_id + * + * @throws InvalidArgumentException + * @return DateTime The date the action is schedule to run, or the date that it ran. + */ + public function get_date( $action_id ) { + $date = $this->get_date_gmt( $action_id ); + return $date->setTimezone( $this->get_local_timezone() ); + } + + /** + * @param string $action_id + * + * @throws InvalidArgumentException + * @return DateTime The date the action is schedule to run, or the date that it ran. + */ + public function get_date_gmt( $action_id ) { + $post = get_post($action_id); + if ( empty($post) || ($post->post_type != self::POST_TYPE) ) { + throw new InvalidArgumentException(sprintf(__('Unidentified action %s', 'action-scheduler'), $action_id)); + } + if ( $post->post_status == 'publish' ) { + return as_get_datetime_object($post->post_modified_gmt); + } else { + return as_get_datetime_object($post->post_date_gmt); + } + } + + /** + * @param int $max_actions + * @param DateTime $before_date Jobs must be schedule before this date. Defaults to now. + * + * @return ActionScheduler_ActionClaim + */ + public function stake_claim( $max_actions = 10, DateTime $before_date = NULL ){ + $claim_id = $this->generate_claim_id(); + $this->claim_actions( $claim_id, $max_actions, $before_date ); + $action_ids = $this->find_actions_by_claim_id( $claim_id ); + return new ActionScheduler_ActionClaim( $claim_id, $action_ids ); + } + + /** + * @return int + */ + public function get_claim_count(){ + global $wpdb; + + $sql = "SELECT COUNT(DISTINCT post_password) FROM {$wpdb->posts} WHERE post_password != '' AND post_type = %s AND post_status IN ('in-progress','pending')"; + $sql = $wpdb->prepare( $sql, array( self::POST_TYPE ) ); + + return $wpdb->get_var( $sql ); + } + + protected function generate_claim_id() { + $claim_id = md5(microtime(true) . rand(0,1000)); + return substr($claim_id, 0, 20); // to fit in db field with 20 char limit + } + + /** + * @param string $claim_id + * @param int $limit + * @param DateTime $before_date Should use UTC timezone. + * @return int The number of actions that were claimed + * @throws RuntimeException + */ + protected function claim_actions( $claim_id, $limit, DateTime $before_date = NULL ) { + /** @var wpdb $wpdb */ + global $wpdb; + + $date = is_null($before_date) ? as_get_datetime_object() : clone $before_date; + // can't use $wpdb->update() because of the <= condition, using post_modified to take advantage of indexes + $sql = "UPDATE {$wpdb->posts} SET post_password = %s, post_modified_gmt = %s, post_modified = %s WHERE post_type = %s AND post_status = %s AND post_password = '' AND post_date_gmt <= %s ORDER BY menu_order ASC, post_date_gmt ASC LIMIT %d"; + $sql = $wpdb->prepare( $sql, array( $claim_id, current_time('mysql', true), current_time('mysql'), self::POST_TYPE, 'pending', $date->format('Y-m-d H:i:s'), $limit ) ); + $rows_affected = $wpdb->query($sql); + if ( $rows_affected === false ) { + throw new RuntimeException(__('Unable to claim actions. Database error.', 'action-scheduler')); + } + return (int)$rows_affected; + } + + /** + * @param string $claim_id + * @return array + */ + public function find_actions_by_claim_id( $claim_id ) { + /** @var wpdb $wpdb */ + global $wpdb; + $sql = "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s AND post_password = %s"; + $sql = $wpdb->prepare( $sql, array( self::POST_TYPE, $claim_id ) ); + $action_ids = $wpdb->get_col( $sql ); + return $action_ids; + } + + public function release_claim( ActionScheduler_ActionClaim $claim ) { + $action_ids = $this->find_actions_by_claim_id( $claim->get_id() ); + if ( empty($action_ids) ) { + return; // nothing to do + } + $action_id_string = implode(',', array_map('intval', $action_ids)); + /** @var wpdb $wpdb */ + global $wpdb; + $sql = "UPDATE {$wpdb->posts} SET post_password = '' WHERE ID IN ($action_id_string) AND post_password = %s"; + $sql = $wpdb->prepare( $sql, array( $claim->get_id() ) ); + $result = $wpdb->query($sql); + if ( $result === false ) { + throw new RuntimeException( sprintf( __('Unable to unlock claim %s. Database error.', 'action-scheduler'), $claim->get_id() ) ); + } + } + + /** + * @param string $action_id + * + * @return void + */ + public function unclaim_action( $action_id ) { + /** @var wpdb $wpdb */ + global $wpdb; + $sql = "UPDATE {$wpdb->posts} SET post_password = '' WHERE ID = %d AND post_type = %s"; + $sql = $wpdb->prepare( $sql, $action_id, self::POST_TYPE ); + $result = $wpdb->query($sql); + if ( $result === false ) { + throw new RuntimeException( sprintf( __('Unable to unlock claim on action %s. Database error.', 'action-scheduler'), $action_id ) ); + } + } + + public function mark_failure( $action_id ) { + /** @var wpdb $wpdb */ + global $wpdb; + $sql = "UPDATE {$wpdb->posts} SET post_status = %s WHERE ID = %d AND post_type = %s"; + $sql = $wpdb->prepare( $sql, self::STATUS_FAILED, $action_id, self::POST_TYPE ); + $result = $wpdb->query($sql); + if ( $result === false ) { + throw new RuntimeException( sprintf( __('Unable to mark failure on action %s. Database error.', 'action-scheduler'), $action_id ) ); + } + } + + /** + * @param string $action_id + * + * @return void + */ + public function log_execution( $action_id ) { + /** @var wpdb $wpdb */ + global $wpdb; + + $sql = "UPDATE {$wpdb->posts} SET menu_order = menu_order+1, post_status=%s, post_modified_gmt = %s, post_modified = %s WHERE ID = %d AND post_type = %s"; + $sql = $wpdb->prepare( $sql, self::STATUS_RUNNING, current_time('mysql', true), current_time('mysql'), $action_id, self::POST_TYPE ); + $wpdb->query($sql); + } + + + public function mark_complete( $action_id ) { + $post = get_post($action_id); + if ( empty($post) || ($post->post_type != self::POST_TYPE) ) { + throw new InvalidArgumentException(sprintf(__('Unidentified action %s', 'action-scheduler'), $action_id)); + } + add_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10, 1 ); + $result = wp_update_post(array( + 'ID' => $action_id, + 'post_status' => 'publish', + ), TRUE); + remove_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10, 1 ); + if ( is_wp_error($result) ) { + throw new RuntimeException($result->get_error_message()); + } + } + + /** + * @codeCoverageIgnore + */ + public function init() { + $post_type_registrar = new ActionScheduler_wpPostStore_PostTypeRegistrar(); + $post_type_registrar->register(); + + $post_status_registrar = new ActionScheduler_wpPostStore_PostStatusRegistrar(); + $post_status_registrar->register(); + + $taxonomy_registrar = new ActionScheduler_wpPostStore_TaxonomyRegistrar(); + $taxonomy_registrar->register(); + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_wpPostStore_PostStatusRegistrar.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_wpPostStore_PostStatusRegistrar.php new file mode 100644 index 0000000000..a85b154f3a --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_wpPostStore_PostStatusRegistrar.php @@ -0,0 +1,57 @@ +<?php + +/** + * Class ActionScheduler_wpPostStore_PostStatusRegistrar + * @codeCoverageIgnore + */ +class ActionScheduler_wpPostStore_PostStatusRegistrar { + public function register() { + register_post_status( ActionScheduler_Store::STATUS_RUNNING, array_merge( $this->post_status_args(), $this->post_status_running_labels() ) ); + register_post_status( ActionScheduler_Store::STATUS_FAILED, array_merge( $this->post_status_args(), $this->post_status_failed_labels() ) ); + } + + /** + * Build the args array for the post type definition + * + * @return array + */ + protected function post_status_args() { + $args = array( + 'public' => false, + 'exclude_from_search' => false, + 'show_in_admin_all_list' => true, + 'show_in_admin_status_list' => true, + ); + + return apply_filters( 'action_scheduler_post_status_args', $args ); + } + + /** + * Build the args array for the post type definition + * + * @return array + */ + protected function post_status_failed_labels() { + $labels = array( + 'label' => _x( 'Failed', 'post' ), + 'label_count' => _n_noop( 'Failed <span class="count">(%s)</span>', 'Failed <span class="count">(%s)</span>' ), + ); + + return apply_filters( 'action_scheduler_post_status_failed_labels', $labels ); + } + + /** + * Build the args array for the post type definition + * + * @return array + */ + protected function post_status_running_labels() { + $labels = array( + 'label' => _x( 'In-Progress', 'post' ), + 'label_count' => _n_noop( 'In-Progress <span class="count">(%s)</span>', 'In-Progress <span class="count">(%s)</span>' ), + ); + + return apply_filters( 'action_scheduler_post_status_running_labels', $labels ); + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_wpPostStore_PostTypeRegistrar.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_wpPostStore_PostTypeRegistrar.php new file mode 100644 index 0000000000..8c63bd0f7a --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_wpPostStore_PostTypeRegistrar.php @@ -0,0 +1,50 @@ +<?php + +/** + * Class ActionScheduler_wpPostStore_PostTypeRegistrar + * @codeCoverageIgnore + */ +class ActionScheduler_wpPostStore_PostTypeRegistrar { + public function register() { + register_post_type( ActionScheduler_wpPostStore::POST_TYPE, $this->post_type_args() ); + } + + /** + * Build the args array for the post type definition + * + * @return array + */ + protected function post_type_args() { + $args = array( + 'label' => __( 'Scheduled Actions', 'action-scheduler' ), + 'description' => __( 'Scheduled actions are hooks triggered on a cetain date and time.', 'action-scheduler' ), + 'public' => false, + 'map_meta_cap' => true, + 'hierarchical' => false, + 'supports' => array('title', 'editor','comments'), + 'rewrite' => false, + 'query_var' => false, + 'can_export' => true, + 'ep_mask' => EP_NONE, + 'labels' => array( + 'name' => __( 'Scheduled Actions', 'action-scheduler' ), + 'singular_name' => __( 'Scheduled Action', 'action-scheduler' ), + 'menu_name' => _x( 'Scheduled Actions', 'Admin menu name', 'action-scheduler' ), + 'add_new' => __( 'Add', 'action-scheduler' ), + 'add_new_item' => __( 'Add New Scheduled Action', 'action-scheduler' ), + 'edit' => __( 'Edit', 'action-scheduler' ), + 'edit_item' => __( 'Edit Scheduled Action', 'action-scheduler' ), + 'new_item' => __( 'New Scheduled Action', 'action-scheduler' ), + 'view' => __( 'View Action', 'action-scheduler' ), + 'view_item' => __( 'View Action', 'action-scheduler' ), + 'search_items' => __( 'Search Scheduled Actions', 'action-scheduler' ), + 'not_found' => __( 'No actions found', 'action-scheduler' ), + 'not_found_in_trash' => __( 'No actions found in trash', 'action-scheduler' ), + ), + ); + + $args = apply_filters('action_scheduler_post_type_args', $args); + return $args; + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/classes/ActionScheduler_wpPostStore_TaxonomyRegistrar.php b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_wpPostStore_TaxonomyRegistrar.php new file mode 100644 index 0000000000..026d6257e8 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/classes/ActionScheduler_wpPostStore_TaxonomyRegistrar.php @@ -0,0 +1,26 @@ +<?php + +/** + * Class ActionScheduler_wpPostStore_TaxonomyRegistrar + * @codeCoverageIgnore + */ +class ActionScheduler_wpPostStore_TaxonomyRegistrar { + public function register() { + register_taxonomy( ActionScheduler_wpPostStore::GROUP_TAXONOMY, ActionScheduler_wpPostStore::POST_TYPE, $this->taxonomy_args() ); + } + + protected function taxonomy_args() { + $args = array( + 'label' => __('Action Group', 'action-scheduler'), + 'public' => false, + 'hierarchical' => false, + 'show_admin_column' => true, + 'query_var' => false, + 'rewrite' => false, + ); + + $args = apply_filters('action_scheduler_taxonomy_args', $args); + return $args; + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/functions.php b/vendor/gocodebox/action-scheduler/functions.php new file mode 100644 index 0000000000..feb8f02b3c --- /dev/null +++ b/vendor/gocodebox/action-scheduler/functions.php @@ -0,0 +1,188 @@ +<?php + +/** + * General API functions for scheduling actions + */ + +/** + * Schedule an action to run one time + * + * @param int $timestamp When the job will run + * @param string $hook The hook to trigger + * @param array $args Arguments to pass when the hook triggers + * @param string $group The group to assign this job to + * + * @return string The job ID + */ +function wc_schedule_single_action( $timestamp, $hook, $args = array(), $group = '' ) { + return ActionScheduler::factory()->single( $hook, $args, $timestamp, $group ); +} + +/** + * Schedule a recurring action + * + * @param int $timestamp When the first instance of the job will run + * @param int $interval_in_seconds How long to wait between runs + * @param string $hook The hook to trigger + * @param array $args Arguments to pass when the hook triggers + * @param string $group The group to assign this job to + * + * @return string The job ID + */ +function wc_schedule_recurring_action( $timestamp, $interval_in_seconds, $hook, $args = array(), $group = '' ) { + return ActionScheduler::factory()->recurring( $hook, $args, $timestamp, $interval_in_seconds, $group ); +} + +/** + * Schedule an action that recurs on a cron-like schedule. + * + * @param int $timestamp The schedule will start on or after this time + * @param string $schedule A cron-link schedule string + * @see http://en.wikipedia.org/wiki/Cron + * * * * * * * + * ┬ ┬ ┬ ┬ ┬ ┬ + * | | | | | | + * | | | | | + year [optional] + * | | | | +----- day of week (0 - 7) (Sunday=0 or 7) + * | | | +---------- month (1 - 12) + * | | +--------------- day of month (1 - 31) + * | +-------------------- hour (0 - 23) + * +------------------------- min (0 - 59) + * @param string $hook The hook to trigger + * @param array $args Arguments to pass when the hook triggers + * @param string $group The group to assign this job to + * + * @return string The job ID + */ +function wc_schedule_cron_action( $timestamp, $schedule, $hook, $args = array(), $group = '' ) { + return ActionScheduler::factory()->cron( $hook, $args, $timestamp, $schedule, $group ); +} + +/** + * Cancel the next occurrence of a job. + * + * @param string $hook The hook that the job will trigger + * @param array $args Args that would have been passed to the job + * @param string $group + * + * @return void + */ +function wc_unschedule_action( $hook, $args = array(), $group = '' ) { + $params = array(); + if ( is_array($args) ) { + $params['args'] = $args; + } + if ( !empty($group) ) { + $params['group'] = $group; + } + $job_id = ActionScheduler::store()->find_action( $hook, $params ); + if ( empty($job_id) ) { + return; + } + + ActionScheduler::store()->cancel_action( $job_id ); +} + +/** + * @param string $hook + * @param array $args + * @param string $group + * + * @return int|bool The timestamp for the next occurrence, or false if nothing was found + */ +function wc_next_scheduled_action( $hook, $args = NULL, $group = '' ) { + $params = array(); + if ( is_array($args) ) { + $params['args'] = $args; + } + if ( !empty($group) ) { + $params['group'] = $group; + } + $job_id = ActionScheduler::store()->find_action( $hook, $params ); + if ( empty($job_id) ) { + return false; + } + $job = ActionScheduler::store()->fetch_action( $job_id ); + $next = $job->get_schedule()->next(); + if ( $next ) { + return (int)($next->format('U')); + } + return false; +} + +/** + * Find scheduled actions + * + * @param array $args Possible arguments, with their default values: + * 'hook' => '' - the name of the action that will be triggered + * 'args' => NULL - the args array that will be passed with the action + * 'date' => NULL - the scheduled date of the action. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). Used in UTC timezone. + * 'date_compare' => '<=' - operator for testing "date". accepted values are '!=', '>', '>=', '<', '<=', '=' + * 'modified' => NULL - the date the action was last updated. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). Used in UTC timezone. + * 'modified_compare' => '<=' - operator for testing "modified". accepted values are '!=', '>', '>=', '<', '<=', '=' + * 'group' => '' - the group the action belongs to + * 'status' => '' - ActionScheduler_Store::STATUS_COMPLETE or ActionScheduler_Store::STATUS_PENDING + * 'claimed' => NULL - TRUE to find claimed actions, FALSE to find unclaimed actions, a string to find a specific claim ID + * 'per_page' => 5 - Number of results to return + * 'offset' => 0 + * 'orderby' => 'date' - accepted values are 'hook', 'group', 'modified', or 'date' + * 'order' => 'ASC' + * + * @param string $return_format OBJECT, ARRAY_A, or ids + * + * @return array + */ +function wc_get_scheduled_actions( $args = array(), $return_format = OBJECT ) { + $store = ActionScheduler::store(); + foreach ( array('date', 'modified') as $key ) { + if ( isset($args[$key]) ) { + $args[$key] = as_get_datetime_object($args[$key]); + } + } + $ids = $store->query_actions( $args ); + + if ( $return_format == 'ids' || $return_format == 'int' ) { + return $ids; + } + + $actions = array(); + foreach ( $ids as $action_id ) { + $actions[$action_id] = $store->fetch_action( $action_id ); + } + + if ( $return_format == ARRAY_A ) { + foreach ( $actions as $action_id => $action_object ) { + $actions[$action_id] = get_object_vars($action_object); + } + } + + return $actions; +} + +/** + * Helper function to create an instance of DateTime based on a given + * string and timezone. By default, will return the current date/time + * in the UTC timezone. + * + * Needed because new DateTime() called without an explicit timezone + * will create a date/time in PHP's timezone, but we need to have + * assurance that a date/time uses the right timezone (which we almost + * always want to be UTC), which means we need to always include the + * timezone when instantiating datetimes rather than leaving it up to + * the PHP default. + * + * @param mixed $date_string A date/time string. Valid formats are explained in http://php.net/manual/en/datetime.formats.php + * @param string $timezone A timezone identifier, like UTC or Europe/Lisbon. The list of valid identifiers is available http://php.net/manual/en/timezones.php + * + * @return DateTime + */ +function as_get_datetime_object( $date_string = null, $timezone = 'UTC' ) { + if ( is_object($date_string) && $date_string instanceof DateTime ) { + $date = $date_string->setTimezone(new DateTimeZone( $timezone ) ); + } elseif ( is_numeric( $date_string ) ) { + $date = new DateTime( '@'.$date_string, new DateTimeZone( $timezone ) ); + } else { + $date = new DateTime( $date_string, new DateTimeZone( $timezone ) ); + } + return $date; +} diff --git a/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression.php b/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression.php new file mode 100755 index 0000000000..43443ff42b --- /dev/null +++ b/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression.php @@ -0,0 +1,318 @@ +<?php + +/** + * CRON expression parser that can determine whether or not a CRON expression is + * due to run, the next run date and previous run date of a CRON expression. + * The determinations made by this class are accurate if checked run once per + * minute (seconds are dropped from date time comparisons). + * + * Schedule parts must map to: + * minute [0-59], hour [0-23], day of month, month [1-12|JAN-DEC], day of week + * [1-7|MON-SUN], and an optional year. + * + * @author Michael Dowling <mtdowling@gmail.com> + * @link http://en.wikipedia.org/wiki/Cron + */ +class CronExpression +{ + const MINUTE = 0; + const HOUR = 1; + const DAY = 2; + const MONTH = 3; + const WEEKDAY = 4; + const YEAR = 5; + + /** + * @var array CRON expression parts + */ + private $cronParts; + + /** + * @var CronExpression_FieldFactory CRON field factory + */ + private $fieldFactory; + + /** + * @var array Order in which to test of cron parts + */ + private static $order = array(self::YEAR, self::MONTH, self::DAY, self::WEEKDAY, self::HOUR, self::MINUTE); + + /** + * Factory method to create a new CronExpression. + * + * @param string $expression The CRON expression to create. There are + * several special predefined values which can be used to substitute the + * CRON expression: + * + * @yearly, @annually) - Run once a year, midnight, Jan. 1 - 0 0 1 1 * + * @monthly - Run once a month, midnight, first of month - 0 0 1 * * + * @weekly - Run once a week, midnight on Sun - 0 0 * * 0 + * @daily - Run once a day, midnight - 0 0 * * * + * @hourly - Run once an hour, first minute - 0 * * * * + * +*@param CronExpression_FieldFactory $fieldFactory (optional) Field factory to use + * + * @return CronExpression + */ + public static function factory($expression, CronExpression_FieldFactory $fieldFactory = null) + { + $mappings = array( + '@yearly' => '0 0 1 1 *', + '@annually' => '0 0 1 1 *', + '@monthly' => '0 0 1 * *', + '@weekly' => '0 0 * * 0', + '@daily' => '0 0 * * *', + '@hourly' => '0 * * * *' + ); + + if (isset($mappings[$expression])) { + $expression = $mappings[$expression]; + } + + return new self($expression, $fieldFactory ? $fieldFactory : new CronExpression_FieldFactory()); + } + + /** + * Parse a CRON expression + * + * @param string $expression CRON expression (e.g. '8 * * * *') + * @param CronExpression_FieldFactory $fieldFactory Factory to create cron fields + */ + public function __construct($expression, CronExpression_FieldFactory $fieldFactory) + { + $this->fieldFactory = $fieldFactory; + $this->setExpression($expression); + } + + /** + * Set or change the CRON expression + * + * @param string $value CRON expression (e.g. 8 * * * *) + * + * @return CronExpression + * @throws InvalidArgumentException if not a valid CRON expression + */ + public function setExpression($value) + { + $this->cronParts = preg_split('/\s/', $value, -1, PREG_SPLIT_NO_EMPTY); + if (count($this->cronParts) < 5) { + throw new InvalidArgumentException( + $value . ' is not a valid CRON expression' + ); + } + + foreach ($this->cronParts as $position => $part) { + $this->setPart($position, $part); + } + + return $this; + } + + /** + * Set part of the CRON expression + * + * @param int $position The position of the CRON expression to set + * @param string $value The value to set + * + * @return CronExpression + * @throws InvalidArgumentException if the value is not valid for the part + */ + public function setPart($position, $value) + { + if (!$this->fieldFactory->getField($position)->validate($value)) { + throw new InvalidArgumentException( + 'Invalid CRON field value ' . $value . ' as position ' . $position + ); + } + + $this->cronParts[$position] = $value; + + return $this; + } + + /** + * Get a next run date relative to the current date or a specific date + * + * @param string|DateTime $currentTime (optional) Relative calculation date + * @param int $nth (optional) Number of matches to skip before returning a + * matching next run date. 0, the default, will return the current + * date and time if the next run date falls on the current date and + * time. Setting this value to 1 will skip the first match and go to + * the second match. Setting this value to 2 will skip the first 2 + * matches and so on. + * @param bool $allowCurrentDate (optional) Set to TRUE to return the + * current date if it matches the cron expression + * + * @return DateTime + * @throws RuntimeException on too many iterations + */ + public function getNextRunDate($currentTime = 'now', $nth = 0, $allowCurrentDate = false) + { + return $this->getRunDate($currentTime, $nth, false, $allowCurrentDate); + } + + /** + * Get a previous run date relative to the current date or a specific date + * + * @param string|DateTime $currentTime (optional) Relative calculation date + * @param int $nth (optional) Number of matches to skip before returning + * @param bool $allowCurrentDate (optional) Set to TRUE to return the + * current date if it matches the cron expression + * + * @return DateTime + * @throws RuntimeException on too many iterations + * @see CronExpression::getNextRunDate + */ + public function getPreviousRunDate($currentTime = 'now', $nth = 0, $allowCurrentDate = false) + { + return $this->getRunDate($currentTime, $nth, true, $allowCurrentDate); + } + + /** + * Get multiple run dates starting at the current date or a specific date + * + * @param int $total Set the total number of dates to calculate + * @param string|DateTime $currentTime (optional) Relative calculation date + * @param bool $invert (optional) Set to TRUE to retrieve previous dates + * @param bool $allowCurrentDate (optional) Set to TRUE to return the + * current date if it matches the cron expression + * + * @return array Returns an array of run dates + */ + public function getMultipleRunDates($total, $currentTime = 'now', $invert = false, $allowCurrentDate = false) + { + $matches = array(); + for ($i = 0; $i < max(0, $total); $i++) { + $matches[] = $this->getRunDate($currentTime, $i, $invert, $allowCurrentDate); + } + + return $matches; + } + + /** + * Get all or part of the CRON expression + * + * @param string $part (optional) Specify the part to retrieve or NULL to + * get the full cron schedule string. + * + * @return string|null Returns the CRON expression, a part of the + * CRON expression, or NULL if the part was specified but not found + */ + public function getExpression($part = null) + { + if (null === $part) { + return implode(' ', $this->cronParts); + } elseif (array_key_exists($part, $this->cronParts)) { + return $this->cronParts[$part]; + } + + return null; + } + + /** + * Helper method to output the full expression. + * + * @return string Full CRON expression + */ + public function __toString() + { + return $this->getExpression(); + } + + /** + * Determine if the cron is due to run based on the current date or a + * specific date. This method assumes that the current number of + * seconds are irrelevant, and should be called once per minute. + * + * @param string|DateTime $currentTime (optional) Relative calculation date + * + * @return bool Returns TRUE if the cron is due to run or FALSE if not + */ + public function isDue($currentTime = 'now') + { + if ('now' === $currentTime) { + $currentDate = date('Y-m-d H:i'); + $currentTime = strtotime($currentDate); + } elseif ($currentTime instanceof DateTime) { + $currentDate = $currentTime->format('Y-m-d H:i'); + $currentTime = strtotime($currentDate); + } else { + $currentTime = new DateTime($currentTime); + $currentTime->setTime($currentTime->format('H'), $currentTime->format('i'), 0); + $currentDate = $currentTime->format('Y-m-d H:i'); + $currentTime = (int)($currentTime->format('U')); + } + + return $this->getNextRunDate($currentDate, 0, true)->format('U') == $currentTime; + } + + /** + * Get the next or previous run date of the expression relative to a date + * + * @param string|DateTime $currentTime (optional) Relative calculation date + * @param int $nth (optional) Number of matches to skip before returning + * @param bool $invert (optional) Set to TRUE to go backwards in time + * @param bool $allowCurrentDate (optional) Set to TRUE to return the + * current date if it matches the cron expression + * + * @return DateTime + * @throws RuntimeException on too many iterations + */ + protected function getRunDate($currentTime = null, $nth = 0, $invert = false, $allowCurrentDate = false) + { + if ($currentTime instanceof DateTime) { + $currentDate = $currentTime; + } else { + $currentDate = new DateTime($currentTime ? $currentTime : 'now'); + $currentDate->setTimezone(new DateTimeZone(date_default_timezone_get())); + } + + $currentDate->setTime($currentDate->format('H'), $currentDate->format('i'), 0); + $nextRun = clone $currentDate; + $nth = (int) $nth; + + // Set a hard limit to bail on an impossible date + for ($i = 0; $i < 1000; $i++) { + + foreach (self::$order as $position) { + $part = $this->getExpression($position); + if (null === $part) { + continue; + } + + $satisfied = false; + // Get the field object used to validate this part + $field = $this->fieldFactory->getField($position); + // Check if this is singular or a list + if (strpos($part, ',') === false) { + $satisfied = $field->isSatisfiedBy($nextRun, $part); + } else { + foreach (array_map('trim', explode(',', $part)) as $listPart) { + if ($field->isSatisfiedBy($nextRun, $listPart)) { + $satisfied = true; + break; + } + } + } + + // If the field is not satisfied, then start over + if (!$satisfied) { + $field->increment($nextRun, $invert); + continue 2; + } + } + + // Skip this match if needed + if ((!$allowCurrentDate && $nextRun == $currentDate) || --$nth > -1) { + $this->fieldFactory->getField(0)->increment($nextRun, $invert); + continue; + } + + return $nextRun; + } + + // @codeCoverageIgnoreStart + throw new RuntimeException('Impossible CRON expression'); + // @codeCoverageIgnoreEnd + } +} diff --git a/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_AbstractField.php b/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_AbstractField.php new file mode 100755 index 0000000000..f8d5c00ae7 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_AbstractField.php @@ -0,0 +1,100 @@ +<?php + +/** + * Abstract CRON expression field + * + * @author Michael Dowling <mtdowling@gmail.com> + */ +abstract class CronExpression_AbstractField implements CronExpression_FieldInterface +{ + /** + * Check to see if a field is satisfied by a value + * + * @param string $dateValue Date value to check + * @param string $value Value to test + * + * @return bool + */ + public function isSatisfied($dateValue, $value) + { + if ($this->isIncrementsOfRanges($value)) { + return $this->isInIncrementsOfRanges($dateValue, $value); + } elseif ($this->isRange($value)) { + return $this->isInRange($dateValue, $value); + } + + return $value == '*' || $dateValue == $value; + } + + /** + * Check if a value is a range + * + * @param string $value Value to test + * + * @return bool + */ + public function isRange($value) + { + return strpos($value, '-') !== false; + } + + /** + * Check if a value is an increments of ranges + * + * @param string $value Value to test + * + * @return bool + */ + public function isIncrementsOfRanges($value) + { + return strpos($value, '/') !== false; + } + + /** + * Test if a value is within a range + * + * @param string $dateValue Set date value + * @param string $value Value to test + * + * @return bool + */ + public function isInRange($dateValue, $value) + { + $parts = array_map('trim', explode('-', $value, 2)); + + return $dateValue >= $parts[0] && $dateValue <= $parts[1]; + } + + /** + * Test if a value is within an increments of ranges (offset[-to]/step size) + * + * @param string $dateValue Set date value + * @param string $value Value to test + * + * @return bool + */ + public function isInIncrementsOfRanges($dateValue, $value) + { + $parts = array_map('trim', explode('/', $value, 2)); + $stepSize = isset($parts[1]) ? $parts[1] : 0; + if ($parts[0] == '*' || $parts[0] === '0') { + return (int) $dateValue % $stepSize == 0; + } + + $range = explode('-', $parts[0], 2); + $offset = $range[0]; + $to = isset($range[1]) ? $range[1] : $dateValue; + // Ensure that the date value is within the range + if ($dateValue < $offset || $dateValue > $to) { + return false; + } + + for ($i = $offset; $i <= $to; $i+= $stepSize) { + if ($i == $dateValue) { + return true; + } + } + + return false; + } +} diff --git a/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_DayOfMonthField.php b/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_DayOfMonthField.php new file mode 100755 index 0000000000..40c1d6c6e7 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_DayOfMonthField.php @@ -0,0 +1,110 @@ +<?php + +/** + * Day of month field. Allows: * , / - ? L W + * + * 'L' stands for "last" and specifies the last day of the month. + * + * The 'W' character is used to specify the weekday (Monday-Friday) nearest the + * given day. As an example, if you were to specify "15W" as the value for the + * day-of-month field, the meaning is: "the nearest weekday to the 15th of the + * month". So if the 15th is a Saturday, the trigger will fire on Friday the + * 14th. If the 15th is a Sunday, the trigger will fire on Monday the 16th. If + * the 15th is a Tuesday, then it will fire on Tuesday the 15th. However if you + * specify "1W" as the value for day-of-month, and the 1st is a Saturday, the + * trigger will fire on Monday the 3rd, as it will not 'jump' over the boundary + * of a month's days. The 'W' character can only be specified when the + * day-of-month is a single day, not a range or list of days. + * + * @author Michael Dowling <mtdowling@gmail.com> + */ +class CronExpression_DayOfMonthField extends CronExpression_AbstractField +{ + /** + * Get the nearest day of the week for a given day in a month + * + * @param int $currentYear Current year + * @param int $currentMonth Current month + * @param int $targetDay Target day of the month + * + * @return DateTime Returns the nearest date + */ + private static function getNearestWeekday($currentYear, $currentMonth, $targetDay) + { + $tday = str_pad($targetDay, 2, '0', STR_PAD_LEFT); + $target = new DateTime("$currentYear-$currentMonth-$tday"); + $currentWeekday = (int) $target->format('N'); + + if ($currentWeekday < 6) { + return $target; + } + + $lastDayOfMonth = $target->format('t'); + + foreach (array(-1, 1, -2, 2) as $i) { + $adjusted = $targetDay + $i; + if ($adjusted > 0 && $adjusted <= $lastDayOfMonth) { + $target->setDate($currentYear, $currentMonth, $adjusted); + if ($target->format('N') < 6 && $target->format('m') == $currentMonth) { + return $target; + } + } + } + } + + /** + * {@inheritdoc} + */ + public function isSatisfiedBy(DateTime $date, $value) + { + // ? states that the field value is to be skipped + if ($value == '?') { + return true; + } + + $fieldValue = $date->format('d'); + + // Check to see if this is the last day of the month + if ($value == 'L') { + return $fieldValue == $date->format('t'); + } + + // Check to see if this is the nearest weekday to a particular value + if (strpos($value, 'W')) { + // Parse the target day + $targetDay = substr($value, 0, strpos($value, 'W')); + // Find out if the current day is the nearest day of the week + return $date->format('j') == self::getNearestWeekday( + $date->format('Y'), + $date->format('m'), + $targetDay + )->format('j'); + } + + return $this->isSatisfied($date->format('d'), $value); + } + + /** + * {@inheritdoc} + */ + public function increment(DateTime $date, $invert = false) + { + if ($invert) { + $date->modify('previous day'); + $date->setTime(23, 59); + } else { + $date->modify('next day'); + $date->setTime(0, 0); + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function validate($value) + { + return (bool) preg_match('/[\*,\/\-\?LW0-9A-Za-z]+/', $value); + } +} diff --git a/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_DayOfWeekField.php b/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_DayOfWeekField.php new file mode 100755 index 0000000000..e9f68a7cd6 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_DayOfWeekField.php @@ -0,0 +1,124 @@ +<?php + +/** + * Day of week field. Allows: * / , - ? L # + * + * Days of the week can be represented as a number 0-7 (0|7 = Sunday) + * or as a three letter string: SUN, MON, TUE, WED, THU, FRI, SAT. + * + * 'L' stands for "last". It allows you to specify constructs such as + * "the last Friday" of a given month. + * + * '#' is allowed for the day-of-week field, and must be followed by a + * number between one and five. It allows you to specify constructs such as + * "the second Friday" of a given month. + * + * @author Michael Dowling <mtdowling@gmail.com> + */ +class CronExpression_DayOfWeekField extends CronExpression_AbstractField +{ + /** + * {@inheritdoc} + */ + public function isSatisfiedBy(DateTime $date, $value) + { + if ($value == '?') { + return true; + } + + // Convert text day of the week values to integers + $value = str_ireplace( + array('SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT'), + range(0, 6), + $value + ); + + $currentYear = $date->format('Y'); + $currentMonth = $date->format('m'); + $lastDayOfMonth = $date->format('t'); + + // Find out if this is the last specific weekday of the month + if (strpos($value, 'L')) { + $weekday = str_replace('7', '0', substr($value, 0, strpos($value, 'L'))); + $tdate = clone $date; + $tdate->setDate($currentYear, $currentMonth, $lastDayOfMonth); + while ($tdate->format('w') != $weekday) { + $tdate->setDate($currentYear, $currentMonth, --$lastDayOfMonth); + } + + return $date->format('j') == $lastDayOfMonth; + } + + // Handle # hash tokens + if (strpos($value, '#')) { + list($weekday, $nth) = explode('#', $value); + // Validate the hash fields + if ($weekday < 1 || $weekday > 5) { + throw new InvalidArgumentException("Weekday must be a value between 1 and 5. {$weekday} given"); + } + if ($nth > 5) { + throw new InvalidArgumentException('There are never more than 5 of a given weekday in a month'); + } + // The current weekday must match the targeted weekday to proceed + if ($date->format('N') != $weekday) { + return false; + } + + $tdate = clone $date; + $tdate->setDate($currentYear, $currentMonth, 1); + $dayCount = 0; + $currentDay = 1; + while ($currentDay < $lastDayOfMonth + 1) { + if ($tdate->format('N') == $weekday) { + if (++$dayCount >= $nth) { + break; + } + } + $tdate->setDate($currentYear, $currentMonth, ++$currentDay); + } + + return $date->format('j') == $currentDay; + } + + // Handle day of the week values + if (strpos($value, '-')) { + $parts = explode('-', $value); + if ($parts[0] == '7') { + $parts[0] = '0'; + } elseif ($parts[1] == '0') { + $parts[1] = '7'; + } + $value = implode('-', $parts); + } + + // Test to see which Sunday to use -- 0 == 7 == Sunday + $format = in_array(7, str_split($value)) ? 'N' : 'w'; + $fieldValue = $date->format($format); + + return $this->isSatisfied($fieldValue, $value); + } + + /** + * {@inheritdoc} + */ + public function increment(DateTime $date, $invert = false) + { + if ($invert) { + $date->modify('-1 day'); + $date->setTime(23, 59, 0); + } else { + $date->modify('+1 day'); + $date->setTime(0, 0, 0); + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function validate($value) + { + return (bool) preg_match('/[\*,\/\-0-9A-Z]+/', $value); + } +} diff --git a/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_FieldFactory.php b/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_FieldFactory.php new file mode 100755 index 0000000000..556ba1a3e3 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_FieldFactory.php @@ -0,0 +1,55 @@ +<?php + +/** + * CRON field factory implementing a flyweight factory + * + * @author Michael Dowling <mtdowling@gmail.com> + * @link http://en.wikipedia.org/wiki/Cron + */ +class CronExpression_FieldFactory +{ + /** + * @var array Cache of instantiated fields + */ + private $fields = array(); + + /** + * Get an instance of a field object for a cron expression position + * + * @param int $position CRON expression position value to retrieve + * + * @return CronExpression_FieldInterface + * @throws InvalidArgumentException if a position is not valid + */ + public function getField($position) + { + if (!isset($this->fields[$position])) { + switch ($position) { + case 0: + $this->fields[$position] = new CronExpression_MinutesField(); + break; + case 1: + $this->fields[$position] = new CronExpression_HoursField(); + break; + case 2: + $this->fields[$position] = new CronExpression_DayOfMonthField(); + break; + case 3: + $this->fields[$position] = new CronExpression_MonthField(); + break; + case 4: + $this->fields[$position] = new CronExpression_DayOfWeekField(); + break; + case 5: + $this->fields[$position] = new CronExpression_YearField(); + break; + default: + throw new InvalidArgumentException( + $position . ' is not a valid position' + ); + } + } + + return $this->fields[$position]; + } +} diff --git a/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_FieldInterface.php b/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_FieldInterface.php new file mode 100755 index 0000000000..5d5109b70d --- /dev/null +++ b/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_FieldInterface.php @@ -0,0 +1,39 @@ +<?php + +/** + * CRON field interface + * + * @author Michael Dowling <mtdowling@gmail.com> + */ +interface CronExpression_FieldInterface +{ + /** + * Check if the respective value of a DateTime field satisfies a CRON exp + * + * @param DateTime $date DateTime object to check + * @param string $value CRON expression to test against + * + * @return bool Returns TRUE if satisfied, FALSE otherwise + */ + public function isSatisfiedBy(DateTime $date, $value); + + /** + * When a CRON expression is not satisfied, this method is used to increment + * or decrement a DateTime object by the unit of the cron field + * + * @param DateTime $date DateTime object to change + * @param bool $invert (optional) Set to TRUE to decrement + * + * @return CronExpression_FieldInterface + */ + public function increment(DateTime $date, $invert = false); + + /** + * Validates a CRON expression for a given field + * + * @param string $value CRON expression value to validate + * + * @return bool Returns TRUE if valid, FALSE otherwise + */ + public function validate($value); +} diff --git a/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_HoursField.php b/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_HoursField.php new file mode 100755 index 0000000000..088ca73c71 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_HoursField.php @@ -0,0 +1,47 @@ +<?php + +/** + * Hours field. Allows: * , / - + * + * @author Michael Dowling <mtdowling@gmail.com> + */ +class CronExpression_HoursField extends CronExpression_AbstractField +{ + /** + * {@inheritdoc} + */ + public function isSatisfiedBy(DateTime $date, $value) + { + return $this->isSatisfied($date->format('H'), $value); + } + + /** + * {@inheritdoc} + */ + public function increment(DateTime $date, $invert = false) + { + // Change timezone to UTC temporarily. This will + // allow us to go back or forwards and hour even + // if DST will be changed between the hours. + $timezone = $date->getTimezone(); + $date->setTimezone(new DateTimeZone('UTC')); + if ($invert) { + $date->modify('-1 hour'); + $date->setTime($date->format('H'), 59); + } else { + $date->modify('+1 hour'); + $date->setTime($date->format('H'), 0); + } + $date->setTimezone($timezone); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function validate($value) + { + return (bool) preg_match('/[\*,\/\-0-9]+/', $value); + } +} diff --git a/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_MinutesField.php b/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_MinutesField.php new file mode 100755 index 0000000000..436acf2f56 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_MinutesField.php @@ -0,0 +1,39 @@ +<?php + +/** + * Minutes field. Allows: * , / - + * + * @author Michael Dowling <mtdowling@gmail.com> + */ +class CronExpression_MinutesField extends CronExpression_AbstractField +{ + /** + * {@inheritdoc} + */ + public function isSatisfiedBy(DateTime $date, $value) + { + return $this->isSatisfied($date->format('i'), $value); + } + + /** + * {@inheritdoc} + */ + public function increment(DateTime $date, $invert = false) + { + if ($invert) { + $date->modify('-1 minute'); + } else { + $date->modify('+1 minute'); + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function validate($value) + { + return (bool) preg_match('/[\*,\/\-0-9]+/', $value); + } +} diff --git a/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_MonthField.php b/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_MonthField.php new file mode 100755 index 0000000000..d3deb129f4 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_MonthField.php @@ -0,0 +1,55 @@ +<?php + +/** + * Month field. Allows: * , / - + * + * @author Michael Dowling <mtdowling@gmail.com> + */ +class CronExpression_MonthField extends CronExpression_AbstractField +{ + /** + * {@inheritdoc} + */ + public function isSatisfiedBy(DateTime $date, $value) + { + // Convert text month values to integers + $value = str_ireplace( + array( + 'JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', + 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC' + ), + range(1, 12), + $value + ); + + return $this->isSatisfied($date->format('m'), $value); + } + + /** + * {@inheritdoc} + */ + public function increment(DateTime $date, $invert = false) + { + if ($invert) { + // $date->modify('last day of previous month'); // remove for php 5.2 compat + $date->modify('previous month'); + $date->modify($date->format('Y-m-t')); + $date->setTime(23, 59); + } else { + //$date->modify('first day of next month'); // remove for php 5.2 compat + $date->modify('next month'); + $date->modify($date->format('Y-m-01')); + $date->setTime(0, 0); + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function validate($value) + { + return (bool) preg_match('/[\*,\/\-0-9A-Z]+/', $value); + } +} diff --git a/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_YearField.php b/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_YearField.php new file mode 100755 index 0000000000..f11562e451 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/lib/cron-expression/CronExpression_YearField.php @@ -0,0 +1,43 @@ +<?php + +/** + * Year field. Allows: * , / - + * + * @author Michael Dowling <mtdowling@gmail.com> + */ +class CronExpression_YearField extends CronExpression_AbstractField +{ + /** + * {@inheritdoc} + */ + public function isSatisfiedBy(DateTime $date, $value) + { + return $this->isSatisfied($date->format('Y'), $value); + } + + /** + * {@inheritdoc} + */ + public function increment(DateTime $date, $invert = false) + { + if ($invert) { + $date->modify('-1 year'); + $date->setDate($date->format('Y'), 12, 31); + $date->setTime(23, 59, 0); + } else { + $date->modify('+1 year'); + $date->setDate($date->format('Y'), 1, 1); + $date->setTime(0, 0, 0); + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function validate($value) + { + return (bool) preg_match('/[\*,\/\-0-9]+/', $value); + } +} diff --git a/vendor/gocodebox/action-scheduler/tests/ActionScheduler_UnitTestCase.php b/vendor/gocodebox/action-scheduler/tests/ActionScheduler_UnitTestCase.php new file mode 100644 index 0000000000..94e7fc5734 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/tests/ActionScheduler_UnitTestCase.php @@ -0,0 +1,36 @@ +<?php + +/** + * Class ActionScheduler_UnitTestCase + */ +class ActionScheduler_UnitTestCase extends WP_UnitTestCase { + + protected $existing_timezone; + + /** + * We want to run every test multiple times using a different timezone to make sure + * that they are unaffected by changes to PHP's timezone. + */ + public function run( PHPUnit_Framework_TestResult $result = NULL ){ + + if ($result === NULL) { + $result = $this->createResult(); + } + + if ( 'UTC' != ( $this->existing_timezone = date_default_timezone_get() ) ) { + date_default_timezone_set( 'UTC' ); + $result->run( $this ); + } + + date_default_timezone_set( 'Pacific/Fiji' ); // UTC+12 + $result->run( $this ); + + date_default_timezone_set( 'Pacific/Tahiti' ); // UTC-10: it's a magical place + $result->run( $this ); + + date_default_timezone_set( $this->existing_timezone ); + + return $result; + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/tests/bootstrap.php b/vendor/gocodebox/action-scheduler/tests/bootstrap.php new file mode 100644 index 0000000000..e897161f55 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/tests/bootstrap.php @@ -0,0 +1,31 @@ +<?php + +$GLOBALS['wp_tests_options'] = array( + 'active_plugins' => array( + basename(dirname(dirname(__FILE__))).'/action-scheduler.php', + ), + 'template' => 'twentythirteen', + 'stylesheet' => 'twentythirteen', +); + +// Check for select constants defined as environment variables +foreach ( array('WP_CONTENT_DIR', 'WP_CONTENT_URL', 'WP_PLUGIN_DIR', 'WP_PLUGIN_URL', 'WPMU_PLUGIN_DIR') as $env_constant ) { + if ( false !== getenv( $env_constant ) && !defined( $env_constant ) ) { + define( $env_constant, getenv( $env_constant )); + } +} + +// If the wordpress-tests repo location has been customized (and specified +// with WP_TESTS_DIR), use that location. This will most commonly be the case +// when configured for use with Travis CI. + +// Otherwise, we'll just assume that this plugin is installed in the WordPress +// SVN external checkout configured in the wordpress-tests repo. + +if( false !== getenv( 'WP_TESTS_DIR' ) ) { + require getenv( 'WP_TESTS_DIR' ) . '/includes/bootstrap.php'; +} else { + require dirname( dirname( dirname( dirname( dirname( dirname( __FILE__ ) ) ) ) ) ) . '/tests/phpunit/includes/bootstrap.php'; +} + +include_once('ActionScheduler_UnitTestCase.php'); \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/tests/phpunit.xml.dist b/vendor/gocodebox/action-scheduler/tests/phpunit.xml.dist new file mode 100644 index 0000000000..74a3efe8d6 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/tests/phpunit.xml.dist @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<phpunit backupGlobals="false" + backupStaticAttributes="false" + colors="true" + convertErrorsToExceptions="true" + convertNoticesToExceptions="true" + convertWarningsToExceptions="true" + processIsolation="false" + stopOnFailure="false" + syntaxCheck="false" + bootstrap="bootstrap.php" + > + <testsuites> + <testsuite name="Action Scheduler"> + <directory>./phpunit</directory> + </testsuite> + </testsuites> + <groups> + <exclude> + <group>ignore</group> + </exclude> + </groups> + <filter> + <whitelist processsUncoveredFilesFromWhitelist="true"> + <directory suffix=".php">..</directory> + <exclude> + <directory>.</directory> + </exclude> + </whitelist> + </filter> +</phpunit> \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/tests/phpunit/jobs/ActionScheduler_Action_Test.php b/vendor/gocodebox/action-scheduler/tests/phpunit/jobs/ActionScheduler_Action_Test.php new file mode 100644 index 0000000000..629f97f7c1 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/tests/phpunit/jobs/ActionScheduler_Action_Test.php @@ -0,0 +1,55 @@ +<?php + +/** + * Class ActionScheduler_Action_Test + * @group actions + */ +class ActionScheduler_Action_Test extends ActionScheduler_UnitTestCase { + public function test_set_schedule() { + $time = as_get_datetime_object(); + $schedule = new ActionScheduler_SimpleSchedule($time); + $action = new ActionScheduler_Action('my_hook', array(), $schedule); + $this->assertEquals( $schedule, $action->get_schedule() ); + } + + public function test_null_schedule() { + $action = new ActionScheduler_Action('my_hook'); + $this->assertInstanceOf( 'ActionScheduler_NullSchedule', $action->get_schedule() ); + } + + public function test_set_hook() { + $action = new ActionScheduler_Action('my_hook'); + $this->assertEquals( 'my_hook', $action->get_hook() ); + } + + public function test_args() { + $action = new ActionScheduler_Action('my_hook'); + $this->assertEmpty($action->get_args()); + + $action = new ActionScheduler_Action('my_hook', array(5,10,15)); + $this->assertEqualSets(array(5,10,15), $action->get_args()); + } + + public function test_set_group() { + $action = new ActionScheduler_Action('my_hook', array(), NULL, 'my_group'); + $this->assertEquals('my_group', $action->get_group()); + } + + public function test_execute() { + $mock = new MockAction(); + + $random = md5(rand()); + add_action( $random, array( $mock, 'action' ) ); + + $action = new ActionScheduler_Action( $random, array($random) ); + $action->execute(); + + remove_action( $random, array( $mock, 'action' ) ); + + $this->assertEquals( 1, $mock->get_call_count() ); + $events = $mock->get_events(); + $event = reset($events); + $this->assertEquals( $random, reset($event['args']) ); + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/tests/phpunit/jobs/ActionScheduler_NullAction_Test.php b/vendor/gocodebox/action-scheduler/tests/phpunit/jobs/ActionScheduler_NullAction_Test.php new file mode 100644 index 0000000000..d144e88e21 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/tests/phpunit/jobs/ActionScheduler_NullAction_Test.php @@ -0,0 +1,16 @@ +<?php + +/** + * Class ActionScheduler_NullAction_Test + * @group actions + */ +class ActionScheduler_NullAction_Test extends ActionScheduler_UnitTestCase { + public function test_null_action() { + $action = new ActionScheduler_NullAction(); + + $this->assertEmpty($action->get_hook()); + $this->assertEmpty($action->get_args()); + $this->assertNull($action->get_schedule()->next()); + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/tests/phpunit/jobstore/ActionScheduler_wpPostStore_Test.php b/vendor/gocodebox/action-scheduler/tests/phpunit/jobstore/ActionScheduler_wpPostStore_Test.php new file mode 100644 index 0000000000..100a378a54 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/tests/phpunit/jobstore/ActionScheduler_wpPostStore_Test.php @@ -0,0 +1,199 @@ +<?php + +/** + * Class ActionScheduler_wpPostStore_Test + * @group stores + */ +class ActionScheduler_wpPostStore_Test extends ActionScheduler_UnitTestCase { + + public function test_create_action() { + $time = as_get_datetime_object(); + $schedule = new ActionScheduler_SimpleSchedule($time); + $action = new ActionScheduler_Action('my_hook', array(), $schedule); + $store = new ActionScheduler_wpPostStore(); + $action_id = $store->save_action($action); + + $this->assertNotEmpty($action_id); + } + + public function test_retrieve_action() { + $time = as_get_datetime_object(); + $schedule = new ActionScheduler_SimpleSchedule($time); + $action = new ActionScheduler_Action('my_hook', array(), $schedule, 'my_group'); + $store = new ActionScheduler_wpPostStore(); + $action_id = $store->save_action($action); + + $retrieved = $store->fetch_action($action_id); + $this->assertEquals($action->get_hook(), $retrieved->get_hook()); + $this->assertEqualSets($action->get_args(), $retrieved->get_args()); + $this->assertEquals($action->get_schedule()->next()->format('U'), $retrieved->get_schedule()->next()->format('U')); + $this->assertEquals($action->get_group(), $retrieved->get_group()); + } + + public function test_cancel_action() { + $time = as_get_datetime_object(); + $schedule = new ActionScheduler_SimpleSchedule($time); + $action = new ActionScheduler_Action('my_hook', array(), $schedule, 'my_group'); + $store = new ActionScheduler_wpPostStore(); + $action_id = $store->save_action($action); + $store->cancel_action( $action_id ); + + $fetched = $store->fetch_action( $action_id ); + $this->assertInstanceOf( 'ActionScheduler_NullAction', $fetched ); + } + + public function test_claim_actions() { + $created_actions = array(); + $store = new ActionScheduler_wpPostStore(); + for ( $i = 3 ; $i > -3 ; $i-- ) { + $time = as_get_datetime_object($i.' hours'); + $schedule = new ActionScheduler_SimpleSchedule($time); + $action = new ActionScheduler_Action('my_hook', array($i), $schedule, 'my_group'); + $created_actions[] = $store->save_action($action); + } + + $claim = $store->stake_claim(); + $this->assertInstanceof( 'ActionScheduler_ActionClaim', $claim ); + + $this->assertCount( 3, $claim->get_actions() ); + $this->assertEqualSets( array_slice( $created_actions, 3, 3 ), $claim->get_actions() ); + } + + public function test_duplicate_claim() { + $created_actions = array(); + $store = new ActionScheduler_wpPostStore(); + for ( $i = 0 ; $i > -3 ; $i-- ) { + $time = as_get_datetime_object($i.' hours'); + $schedule = new ActionScheduler_SimpleSchedule($time); + $action = new ActionScheduler_Action('my_hook', array($i), $schedule, 'my_group'); + $created_actions[] = $store->save_action($action); + } + + $claim1 = $store->stake_claim(); + $claim2 = $store->stake_claim(); + $this->assertCount( 3, $claim1->get_actions() ); + $this->assertCount( 0, $claim2->get_actions() ); + } + + public function test_release_claim() { + $created_actions = array(); + $store = new ActionScheduler_wpPostStore(); + for ( $i = 0 ; $i > -3 ; $i-- ) { + $time = as_get_datetime_object($i.' hours'); + $schedule = new ActionScheduler_SimpleSchedule($time); + $action = new ActionScheduler_Action('my_hook', array($i), $schedule, 'my_group'); + $created_actions[] = $store->save_action($action); + } + + $claim1 = $store->stake_claim(); + + $store->release_claim( $claim1 ); + + $claim2 = $store->stake_claim(); + $this->assertCount( 3, $claim2->get_actions() ); + } + + public function test_search() { + $created_actions = array(); + $store = new ActionScheduler_wpPostStore(); + for ( $i = -3 ; $i <= 3 ; $i++ ) { + $time = as_get_datetime_object($i.' hours'); + $schedule = new ActionScheduler_SimpleSchedule($time); + $action = new ActionScheduler_Action('my_hook', array($i), $schedule, 'my_group'); + $created_actions[] = $store->save_action($action); + } + + $next_no_args = $store->find_action( 'my_hook' ); + $this->assertEquals( $created_actions[0], $next_no_args ); + + $next_with_args = $store->find_action( 'my_hook', array( 'args' => array( 1 ) ) ); + $this->assertEquals( $created_actions[4], $next_with_args ); + + $non_existent = $store->find_action( 'my_hook', array( 'args' => array( 17 ) ) ); + $this->assertNull( $non_existent ); + } + + public function test_search_by_group() { + $store = new ActionScheduler_wpPostStore(); + $schedule = new ActionScheduler_SimpleSchedule(as_get_datetime_object('tomorrow')); + $abc = $store->save_action(new ActionScheduler_Action('my_hook', array(1), $schedule, 'abc')); + $def = $store->save_action(new ActionScheduler_Action('my_hook', array(1), $schedule, 'def')); + $ghi = $store->save_action(new ActionScheduler_Action('my_hook', array(1), $schedule, 'ghi')); + + $this->assertEquals( $abc, $store->find_action('my_hook', array('group' => 'abc'))); + $this->assertEquals( $def, $store->find_action('my_hook', array('group' => 'def'))); + $this->assertEquals( $ghi, $store->find_action('my_hook', array('group' => 'ghi'))); + } + + public function test_post_author() { + $current_user = get_current_user_id(); + + $time = as_get_datetime_object(); + $schedule = new ActionScheduler_SimpleSchedule($time); + $action = new ActionScheduler_Action('my_hook', array(), $schedule); + $store = new ActionScheduler_wpPostStore(); + $action_id = $store->save_action($action); + + $post = get_post($action_id); + $this->assertEquals(0, $post->post_author); + + $new_user = $this->factory->user->create_object(array( + 'user_login' => __FUNCTION__, + 'user_pass' => md5(rand()), + )); + wp_set_current_user( $new_user ); + + + $schedule = new ActionScheduler_SimpleSchedule($time); + $action = new ActionScheduler_Action('my_hook', array(), $schedule); + $action_id = $store->save_action($action); + $post = get_post($action_id); + $this->assertEquals(0, $post->post_author); + + wp_set_current_user($current_user); + } + + /** + * @issue 13 + */ + public function test_post_status_for_recurring_action() { + $time = as_get_datetime_object('10 minutes'); + $schedule = new ActionScheduler_IntervalSchedule($time, HOUR_IN_SECONDS); + $action = new ActionScheduler_Action('my_hook', array(), $schedule); + $store = new ActionScheduler_wpPostStore(); + $action_id = $store->save_action($action); + + $action = $store->fetch_action($action_id); + $action->execute(); + $store->mark_complete( $action_id ); + + $next = $action->get_schedule()->next( as_get_datetime_object() ); + $new_action_id = $store->save_action( $action, $next ); + + $this->assertEquals('publish', get_post_status($action_id)); + $this->assertEquals('pending', get_post_status($new_action_id)); + } + + public function test_get_run_date() { + $time = as_get_datetime_object('-10 minutes'); + $schedule = new ActionScheduler_IntervalSchedule($time, HOUR_IN_SECONDS); + $action = new ActionScheduler_Action('my_hook', array(), $schedule); + $store = new ActionScheduler_wpPostStore(); + $action_id = $store->save_action($action); + + $this->assertEquals( $store->get_date($action_id)->format('U'), $time->format('U') ); + + $action = $store->fetch_action($action_id); + $action->execute(); + $now = as_get_datetime_object(); + $store->mark_complete( $action_id ); + + $this->assertEquals( $store->get_date($action_id)->format('U'), $now->format('U') ); + + $next = $action->get_schedule()->next( $now ); + $new_action_id = $store->save_action( $action, $next ); + + $this->assertEquals( (int)($now->format('U')) + HOUR_IN_SECONDS, $store->get_date($new_action_id)->format('U') ); + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/tests/phpunit/logging/ActionScheduler_wpCommentLogger_Test.php b/vendor/gocodebox/action-scheduler/tests/phpunit/logging/ActionScheduler_wpCommentLogger_Test.php new file mode 100644 index 0000000000..0769ba2789 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/tests/phpunit/logging/ActionScheduler_wpCommentLogger_Test.php @@ -0,0 +1,154 @@ +<?php + +/** + * Class ActionScheduler_wpCommentLogger_Test + * @package test_cases\logging + */ +class ActionScheduler_wpCommentLogger_Test extends ActionScheduler_UnitTestCase { + public function test_default_logger() { + $logger = ActionScheduler::logger(); + $this->assertInstanceOf( 'ActionScheduler_Logger', $logger ); + $this->assertInstanceOf( 'ActionScheduler_wpCommentLogger', $logger ); + } + + public function test_add_log_entry() { + $action_id = wc_schedule_single_action( time(), 'a hook' ); + $logger = ActionScheduler::logger(); + $message = 'Logging that something happened'; + $log_id = $logger->log( $action_id, $message ); + $entry = $logger->get_entry( $log_id ); + + $this->assertEquals( $action_id, $entry->get_action_id() ); + $this->assertEquals( $message, $entry->get_message() ); + } + + public function test_null_log_entry() { + $logger = ActionScheduler::logger(); + $entry = $logger->get_entry( 1 ); + $this->assertEquals( '', $entry->get_action_id() ); + $this->assertEquals( '', $entry->get_message() ); + } + + public function test_erroneous_entry_id() { + $comment = wp_insert_comment(array( + 'comment_post_ID' => 1, + 'comment_author' => 'test', + 'comment_content' => 'this is not a log entry', + )); + $logger = ActionScheduler::logger(); + $entry = $logger->get_entry( $comment ); + $this->assertEquals( '', $entry->get_action_id() ); + $this->assertEquals( '', $entry->get_message() ); + } + + public function test_storage_comments() { + $action_id = wc_schedule_single_action( time(), 'a hook' ); + $logger = ActionScheduler::logger(); + $logs = $logger->get_logs( $action_id ); + $expected = new ActionScheduler_LogEntry( $action_id, 'action created' ); + $this->assertTrue( in_array( $expected, $logs ) ); + } + + public function test_execution_comments() { + $action_id = wc_schedule_single_action( time(), 'a hook' ); + $logger = ActionScheduler::logger(); + $started = new ActionScheduler_LogEntry( $action_id, 'action started' ); + $finished = new ActionScheduler_LogEntry( $action_id, 'action complete' ); + + $runner = new ActionScheduler_QueueRunner(); + $runner->run(); + + $logs = $logger->get_logs( $action_id ); + $this->assertTrue( in_array( $started, $logs ) ); + $this->assertTrue( in_array( $finished, $logs ) ); + } + + public function test_failed_execution_comments() { + $hook = md5(rand()); + add_action( $hook, array( $this, '_a_hook_callback_that_throws_an_exception' ) ); + $action_id = wc_schedule_single_action( time(), $hook ); + $logger = ActionScheduler::logger(); + $started = new ActionScheduler_LogEntry( $action_id, 'action started' ); + $finished = new ActionScheduler_LogEntry( $action_id, 'action complete' ); + $failed = new ActionScheduler_LogEntry( $action_id, 'action failed: Execution failed' ); + + $runner = new ActionScheduler_QueueRunner(); + $runner->run(); + + $logs = $logger->get_logs( $action_id ); + $this->assertTrue( in_array( $started, $logs ) ); + $this->assertFalse( in_array( $finished, $logs ) ); + $this->assertTrue( in_array( $failed, $logs ) ); + } + + public function test_fatal_error_comments() { + $hook = md5(rand()); + $action_id = wc_schedule_single_action( time(), $hook ); + $logger = ActionScheduler::logger(); + do_action( 'action_scheduler_unexpected_shutdown', $action_id, array( + 'type' => E_ERROR, + 'message' => 'Test error', + 'file' => __FILE__, + 'line' => __LINE__, + )); + + $logs = $logger->get_logs( $action_id ); + $found_log = FALSE; + foreach ( $logs as $l ) { + if ( strpos( $l->get_message(), 'unexpected shutdown' ) === 0 ) { + $found_log = TRUE; + } + } + $this->assertTrue( $found_log, 'Unexpected shutdown log not found' ); + } + + public function test_canceled_action_comments() { + $action_id = wc_schedule_single_action( time(), 'a hook' ); + wc_unschedule_action( 'a hook' ); + $logger = ActionScheduler::logger(); + $logs = $logger->get_logs( $action_id ); + $expected = new ActionScheduler_LogEntry( $action_id, 'action canceled' ); + $this->assertTrue( in_array( $expected, $logs ) ); + } + + public function _a_hook_callback_that_throws_an_exception() { + throw new RuntimeException('Execution failed'); + } + + public function test_filtering_of_get_comments() { + $post_id = $this->factory->post->create_object(array( + 'post_title' => __FUNCTION__, + )); + $comment_id = $this->factory->comment->create_object(array( + 'comment_post_ID' => $post_id, + 'comment_author' => __CLASS__, + 'comment_content' => __FUNCTION__, + )); + + // Verify that we're getting the expected comment before we add logging comments + $comments = get_comments(); + $this->assertCount( 1, $comments ); + $this->assertEquals( $comment_id, $comments[0]->comment_ID ); + + + $action_id = wc_schedule_single_action( time(), 'a hook' ); + $logger = ActionScheduler::logger(); + $message = 'Logging that something happened'; + $log_id = $logger->log( $action_id, $message ); + + + // Verify that logging comments are excluded from general comment queries + $comments = get_comments(); + $this->assertCount( 1, $comments ); + $this->assertEquals( $comment_id, $comments[0]->comment_ID ); + + // Verify that logging comments are returned when asking for them specifically + $comments = get_comments(array( + 'type' => ActionScheduler_wpCommentLogger::TYPE, + )); + // Expecting two: one when the action is created, another when we added our custom log + $this->assertCount( 2, $comments ); + $this->assertContains( $log_id, wp_list_pluck($comments, 'comment_ID')); + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/tests/phpunit/procedural_api/procedural_api_Test.php b/vendor/gocodebox/action-scheduler/tests/phpunit/procedural_api/procedural_api_Test.php new file mode 100644 index 0000000000..13904ff99e --- /dev/null +++ b/vendor/gocodebox/action-scheduler/tests/phpunit/procedural_api/procedural_api_Test.php @@ -0,0 +1,133 @@ +<?php + +/** + * Class procedural_api_Test + */ +class procedural_api_Test extends ActionScheduler_UnitTestCase { + + public function test_schedule_action() { + $time = time(); + $hook = md5(rand()); + $action_id = wc_schedule_single_action( $time, $hook ); + + $store = ActionScheduler::store(); + $action = $store->fetch_action($action_id); + $this->assertEquals( $time, $action->get_schedule()->next()->format('U') ); + $this->assertEquals( $hook, $action->get_hook() ); + } + + public function test_recurring_action() { + $time = time(); + $hook = md5(rand()); + $action_id = wc_schedule_recurring_action( $time, HOUR_IN_SECONDS, $hook ); + + $store = ActionScheduler::store(); + $action = $store->fetch_action($action_id); + $this->assertEquals( $time, $action->get_schedule()->next()->format('U') ); + $this->assertEquals( $time + HOUR_IN_SECONDS + 2, $action->get_schedule()->next(as_get_datetime_object($time + 2))->format('U')); + $this->assertEquals( $hook, $action->get_hook() ); + } + + public function test_cron_schedule() { + $time = as_get_datetime_object('2014-01-01'); + $hook = md5(rand()); + $action_id = wc_schedule_cron_action( $time->format('U'), '0 0 10 10 *', $hook ); + + $store = ActionScheduler::store(); + $action = $store->fetch_action($action_id); + $expected_date = as_get_datetime_object('2014-10-10'); + $this->assertEquals( $expected_date->format('U'), $action->get_schedule()->next()->format('U') ); + $this->assertEquals( $hook, $action->get_hook() ); + } + + public function test_get_next() { + $time = as_get_datetime_object('tomorrow'); + $hook = md5(rand()); + wc_schedule_recurring_action( $time->format('U'), HOUR_IN_SECONDS, $hook ); + + $next = wc_next_scheduled_action( $hook ); + + $this->assertEquals( $time->format('U'), $next ); + } + + public function test_unschedule() { + $time = time(); + $hook = md5(rand()); + $action_id = wc_schedule_single_action( $time, $hook ); + + wc_unschedule_action( $hook ); + + $next = wc_next_scheduled_action( $hook ); + $this->assertFalse($next); + + $store = ActionScheduler::store(); + $action = $store->fetch_action($action_id); + + $this->assertNull($action->get_schedule()->next()); + $this->assertEmpty($action->get_hook()); + } + + public function test_as_get_datetime_object_default() { + + $utc_now = new DateTime(null, new DateTimeZone('UTC')); + $as_now = as_get_datetime_object(); + + // Don't want to use 'U' as timestamps will always be in UTC + $this->assertEquals($utc_now->format('Y-m-d H:i:s'),$as_now->format('Y-m-d H:i:s')); + } + + public function test_as_get_datetime_object_relative() { + + $utc_tomorrow = new DateTime('tomorrow', new DateTimeZone('UTC')); + $as_tomorrow = as_get_datetime_object('tomorrow'); + + $this->assertEquals($utc_tomorrow->format('Y-m-d H:i:s'),$as_tomorrow->format('Y-m-d H:i:s')); + + $utc_tomorrow = new DateTime('yesterday', new DateTimeZone('UTC')); + $as_tomorrow = as_get_datetime_object('yesterday'); + + $this->assertEquals($utc_tomorrow->format('Y-m-d H:i:s'),$as_tomorrow->format('Y-m-d H:i:s')); + } + + public function test_as_get_datetime_object_fixed() { + + $utc_tomorrow = new DateTime('29 February 2016', new DateTimeZone('UTC')); + $as_tomorrow = as_get_datetime_object('29 February 2016'); + + $this->assertEquals($utc_tomorrow->format('Y-m-d H:i:s'),$as_tomorrow->format('Y-m-d H:i:s')); + + $utc_tomorrow = new DateTime('1st January 2024', new DateTimeZone('UTC')); + $as_tomorrow = as_get_datetime_object('1st January 2024'); + + $this->assertEquals($utc_tomorrow->format('Y-m-d H:i:s'),$as_tomorrow->format('Y-m-d H:i:s')); + } + + public function test_as_get_datetime_object_timezone() { + + $timezone_au = 'Australia/Brisbane'; + $timezone_default = date_default_timezone_get(); + + date_default_timezone_set( $timezone_au ); + + $au_now = new DateTime(null); + $as_now = as_get_datetime_object(); + + // Make sure they're for the same time + $this->assertEquals($au_now->format('U'),$as_now->format('U')); + + // But not in the same timezone, as $as_now should be using UTC + $this->assertNotEquals($au_now->format('Y-m-d H:i:s'),$as_now->format('Y-m-d H:i:s')); + + $au_now = new DateTime(null); + $as_au_now = as_get_datetime_object(); + + $this->assertEquals($au_now->format('U'),$as_now->format('U')); + + // But not in the same timezone, as $as_now should be using UTC + $this->assertNotEquals($au_now->format('Y-m-d H:i:s'),$as_now->format('Y-m-d H:i:s')); + + // Just in cases + date_default_timezone_set( $timezone_default ); + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/tests/phpunit/procedural_api/wc_get_scheduled_actions_Test.php b/vendor/gocodebox/action-scheduler/tests/phpunit/procedural_api/wc_get_scheduled_actions_Test.php new file mode 100644 index 0000000000..ee2bbfba15 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/tests/phpunit/procedural_api/wc_get_scheduled_actions_Test.php @@ -0,0 +1,100 @@ +<?php + +/** + * Class wc_get_scheduled_actions_Test + */ +class wc_get_scheduled_actions_Test extends ActionScheduler_UnitTestCase { + private $hooks = array(); + private $args = array(); + private $groups = array(); + + public function setUp() { + parent::setUp(); + + $store = ActionScheduler::store(); + + for ( $i = 0 ; $i < 10 ; $i++ ) { + $this->hooks[$i] = md5(rand()); + $this->args[$i] = md5(rand()); + $this->groups[$i] = md5(rand()); + } + + for ( $i = 0 ; $i < 10 ; $i++ ) { + for ( $j = 0 ; $j < 10 ; $j++ ) { + $schedule = new ActionScheduler_SimpleSchedule( as_get_datetime_object( $j - 3 . 'days') ); + $group = $this->groups[ ( $i + $j ) % 10 ]; + $action = new ActionScheduler_Action( $this->hooks[$i], array($this->args[$j]), $schedule, $group ); + $store->save_action( $action ); + } + } + } + + public function test_date_queries() { + $actions = wc_get_scheduled_actions(array( + 'date' => as_get_datetime_object(gmdate('Y-m-d 00:00:00')), + 'per_page' => -1, + ), 'ids'); + $this->assertCount(30, $actions); + + $actions = wc_get_scheduled_actions(array( + 'date' => as_get_datetime_object(gmdate('Y-m-d 00:00:00')), + 'date_compare' => '>=', + 'per_page' => -1, + ), 'ids'); + $this->assertCount(70, $actions); + } + + public function test_hook_queries() { + $actions = wc_get_scheduled_actions(array( + 'hook' => $this->hooks[2], + 'per_page' => -1, + ), 'ids'); + $this->assertCount(10, $actions); + + $actions = wc_get_scheduled_actions(array( + 'hook' => $this->hooks[2], + 'date' => as_get_datetime_object(gmdate('Y-m-d 00:00:00')), + 'per_page' => -1, + ), 'ids'); + $this->assertCount(3, $actions); + } + + public function test_args_queries() { + $actions = wc_get_scheduled_actions(array( + 'args' => array($this->args[5]), + 'per_page' => -1, + ), 'ids'); + $this->assertCount(10, $actions); + + $actions = wc_get_scheduled_actions(array( + 'args' => array($this->args[5]), + 'hook' => $this->hooks[3], + 'per_page' => -1, + ), 'ids'); + $this->assertCount(1, $actions); + + $actions = wc_get_scheduled_actions(array( + 'args' => array($this->args[5]), + 'hook' => $this->hooks[3], + 'date' => as_get_datetime_object(gmdate('Y-m-d 00:00:00')), + 'per_page' => -1, + ), 'ids'); + $this->assertCount(0, $actions); + } + + public function test_group_queries() { + $actions = wc_get_scheduled_actions(array( + 'group' => $this->groups[1], + 'per_page' => -1, + ), 'ids'); + $this->assertCount(10, $actions); + + $actions = wc_get_scheduled_actions(array( + 'group' => $this->groups[1], + 'hook' => $this->hooks[9], + 'per_page' => -1, + ), 'ids'); + $this->assertCount(1, $actions); + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/tests/phpunit/runner/ActionScheduler_QueueCleaner_Test.php b/vendor/gocodebox/action-scheduler/tests/phpunit/runner/ActionScheduler_QueueCleaner_Test.php new file mode 100644 index 0000000000..88584110cd --- /dev/null +++ b/vendor/gocodebox/action-scheduler/tests/phpunit/runner/ActionScheduler_QueueCleaner_Test.php @@ -0,0 +1,122 @@ +<?php + +/** + * Class ActionScheduler_QueueCleaner_Test + */ +class ActionScheduler_QueueCleaner_Test extends ActionScheduler_UnitTestCase { + + public function test_delete_old_actions() { + $store = new ActionScheduler_wpPostStore(); + $runner = new ActionScheduler_QueueRunner( $store ); + + $random = md5(rand()); + $schedule = new ActionScheduler_SimpleSchedule(as_get_datetime_object('1 day ago')); + + $created_actions = array(); + for ( $i = 0 ; $i < 5 ; $i++ ) { + $action = new ActionScheduler_Action( $random, array($random), $schedule ); + $created_actions[] = $store->save_action( $action ); + } + + $runner->run(); + + add_filter( 'action_scheduler_retention_period', '__return_zero' ); // delete any finished job + $cleaner = new ActionScheduler_QueueCleaner( $store ); + $cleaner->delete_old_actions(); + remove_filter( 'action_scheduler_retention_period', '__return_zero' ); + + foreach ( $created_actions as $action_id ) { + $action = $store->fetch_action($action_id); + $this->assertFalse($action->is_finished()); // it's a NullAction + } + } + + public function test_do_not_delete_recent_actions() { + $store = new ActionScheduler_wpPostStore(); + $runner = new ActionScheduler_QueueRunner( $store ); + + $random = md5(rand()); + $schedule = new ActionScheduler_SimpleSchedule(as_get_datetime_object('1 day ago')); + + $created_actions = array(); + for ( $i = 0 ; $i < 5 ; $i++ ) { + $action = new ActionScheduler_Action( $random, array($random), $schedule ); + $created_actions[] = $store->save_action( $action ); + } + + $runner->run(); + + $cleaner = new ActionScheduler_QueueCleaner( $store ); + $cleaner->delete_old_actions(); + + foreach ( $created_actions as $action_id ) { + $action = $store->fetch_action($action_id); + $this->assertTrue($action->is_finished()); // It's a FinishedAction + } + } + + public function test_reset_unrun_actions() { + $store = new ActionScheduler_wpPostStore(); + + $random = md5(rand()); + $schedule = new ActionScheduler_SimpleSchedule(as_get_datetime_object('1 day ago')); + + $created_actions = array(); + for ( $i = 0 ; $i < 5 ; $i++ ) { + $action = new ActionScheduler_Action( $random, array($random), $schedule ); + $created_actions[] = $store->save_action( $action ); + } + + $store->stake_claim(10); + + // don't actually process the jobs, to simulate a request that timed out + + add_filter( 'action_scheduler_timeout_period', '__return_zero' ); // delete any finished job + $cleaner = new ActionScheduler_QueueCleaner( $store ); + $cleaner->reset_timeouts(); + + remove_filter( 'action_scheduler_timeout_period', '__return_zero' ); + + $claim = $store->stake_claim(10); + $this->assertEqualSets($created_actions, $claim->get_actions()); + } + + public function test_do_not_reset_failed_action() { + $store = new ActionScheduler_wpPostStore(); + + $random = md5(rand()); + $schedule = new ActionScheduler_SimpleSchedule(as_get_datetime_object('1 day ago')); + + $created_actions = array(); + for ( $i = 0 ; $i < 5 ; $i++ ) { + $action = new ActionScheduler_Action( $random, array($random), $schedule ); + $created_actions[] = $store->save_action( $action ); + } + + $claim = $store->stake_claim(10); + foreach ( $claim->get_actions() as $action_id ) { + // simulate the first action interrupted by an uncatchable fatal error + $store->log_execution( $action_id ); + break; + } + + add_filter( 'action_scheduler_timeout_period', '__return_zero' ); // delete any finished job + $cleaner = new ActionScheduler_QueueCleaner( $store ); + $cleaner->reset_timeouts(); + remove_filter( 'action_scheduler_timeout_period', '__return_zero' ); + + $new_claim = $store->stake_claim(10); + $this->assertCount( 4, $new_claim->get_actions() ); + + add_filter( 'action_scheduler_failure_period', '__return_zero' ); + $cleaner->mark_failures(); + remove_filter( 'action_scheduler_failure_period', '__return_zero' ); + + $failed = $store->query_actions(array('status' => ActionScheduler_Store::STATUS_FAILED)); + $this->assertEquals( $created_actions[0], $failed[0] ); + $this->assertCount( 1, $failed ); + + + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/tests/phpunit/runner/ActionScheduler_QueueRunner_Test.php b/vendor/gocodebox/action-scheduler/tests/phpunit/runner/ActionScheduler_QueueRunner_Test.php new file mode 100644 index 0000000000..9a9a1b0e67 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/tests/phpunit/runner/ActionScheduler_QueueRunner_Test.php @@ -0,0 +1,210 @@ +<?php + +/** + * Class ActionScheduler_QueueRunner_Test + * @group runners + */ +class ActionScheduler_QueueRunner_Test extends ActionScheduler_UnitTestCase { + public function test_create_runner() { + $store = new ActionScheduler_wpPostStore(); + $runner = new ActionScheduler_QueueRunner( $store ); + $actions_run = $runner->run(); + + $this->assertEquals( 0, $actions_run ); + } + + public function test_run() { + $store = new ActionScheduler_wpPostStore(); + $runner = new ActionScheduler_QueueRunner( $store ); + + $mock = new MockAction(); + $random = md5(rand()); + add_action( $random, array( $mock, 'action' ) ); + $schedule = new ActionScheduler_SimpleSchedule(as_get_datetime_object('1 day ago')); + + for ( $i = 0 ; $i < 5 ; $i++ ) { + $action = new ActionScheduler_Action( $random, array($random), $schedule ); + $store->save_action( $action ); + } + + $actions_run = $runner->run(); + + remove_action( $random, array( $mock, 'action' ) ); + + $this->assertEquals( 5, $mock->get_call_count() ); + $this->assertEquals( 5, $actions_run ); + } + + public function test_run_with_future_actions() { + $store = new ActionScheduler_wpPostStore(); + $runner = new ActionScheduler_QueueRunner( $store ); + + $mock = new MockAction(); + $random = md5(rand()); + add_action( $random, array( $mock, 'action' ) ); + $schedule = new ActionScheduler_SimpleSchedule(as_get_datetime_object('1 day ago')); + + for ( $i = 0 ; $i < 3 ; $i++ ) { + $action = new ActionScheduler_Action( $random, array($random), $schedule ); + $store->save_action( $action ); + } + + $schedule = new ActionScheduler_SimpleSchedule(as_get_datetime_object('tomorrow')); + for ( $i = 0 ; $i < 3 ; $i++ ) { + $action = new ActionScheduler_Action( $random, array($random), $schedule ); + $store->save_action( $action ); + } + + $actions_run = $runner->run(); + + remove_action( $random, array( $mock, 'action' ) ); + + $this->assertEquals( 3, $mock->get_call_count() ); + $this->assertEquals( 3, $actions_run ); + } + + public function test_completed_action_status() { + $store = new ActionScheduler_wpPostStore(); + $runner = new ActionScheduler_QueueRunner( $store ); + + $random = md5(rand()); + $schedule = new ActionScheduler_SimpleSchedule(as_get_datetime_object('12 hours ago')); + + $action = new ActionScheduler_Action( $random, array(), $schedule ); + $action_id = $store->save_action( $action ); + + $runner->run(); + + $finished_action = $store->fetch_action( $action_id ); + + $this->assertTrue( $finished_action->is_finished() ); + } + + public function test_next_instance_of_action() { + $store = new ActionScheduler_wpPostStore(); + $runner = new ActionScheduler_QueueRunner( $store ); + + $random = md5(rand()); + $schedule = new ActionScheduler_IntervalSchedule(as_get_datetime_object('12 hours ago'), DAY_IN_SECONDS); + + $action = new ActionScheduler_Action( $random, array(), $schedule ); + $store->save_action( $action ); + + $runner->run(); + + $claim = $store->stake_claim(10, as_get_datetime_object((DAY_IN_SECONDS - 60).' seconds')); + $this->assertCount(0, $claim->get_actions()); + + $claim = $store->stake_claim(10, as_get_datetime_object(DAY_IN_SECONDS.' seconds')); + $actions = $claim->get_actions(); + $this->assertCount(1, $actions); + + $action_id = reset($actions); + $new_action = $store->fetch_action($action_id); + + + $this->assertEquals( $random, $new_action->get_hook() ); + $this->assertEquals( $schedule->next(as_get_datetime_object()), $new_action->get_schedule()->next(as_get_datetime_object()) ); + } + + public function test_hooked_into_wp_cron() { + $next = wp_next_scheduled( ActionScheduler_QueueRunner::WP_CRON_HOOK ); + $this->assertNotEmpty($next); + } + + public function test_batch_count_limit() { + $store = new ActionScheduler_wpPostStore(); + $runner = new ActionScheduler_QueueRunner( $store ); + + $mock = new MockAction(); + $random = md5(rand()); + add_action( $random, array( $mock, 'action' ) ); + $schedule = new ActionScheduler_SimpleSchedule(new DateTime('1 day ago')); + + for ( $i = 0 ; $i < 30 ; $i++ ) { + $action = new ActionScheduler_Action( $random, array($random), $schedule ); + $store->save_action( $action ); + } + + $claims = array(); + + for ( $i = 0 ; $i < 5 ; $i++ ) { + $claims[] = $store->stake_claim( 5 ); + } + + $actions_run = $runner->run(); + + + $this->assertEquals( 0, $mock->get_call_count() ); + $this->assertEquals( 0, $actions_run ); + + $first = reset($claims); + $store->release_claim( $first ); + + $actions_run = $runner->run(); + $this->assertEquals( 10, $mock->get_call_count() ); + $this->assertEquals( 10, $actions_run ); + + remove_action( $random, array( $mock, 'action' ) ); + } + + public function test_changing_batch_count_limit() { + $store = new ActionScheduler_wpPostStore(); + $runner = new ActionScheduler_QueueRunner( $store ); + + $random = md5(rand()); + $schedule = new ActionScheduler_SimpleSchedule(new DateTime('1 day ago')); + + for ( $i = 0 ; $i < 30 ; $i++ ) { + $action = new ActionScheduler_Action( $random, array($random), $schedule ); + $store->save_action( $action ); + } + + $claims = array(); + + for ( $i = 0 ; $i < 5 ; $i++ ) { + $claims[] = $store->stake_claim( 5 ); + } + + $mock1 = new MockAction(); + add_action( $random, array( $mock1, 'action' ) ); + $actions_run = $runner->run(); + remove_action( $random, array( $mock1, 'action' ) ); + + $this->assertEquals( 0, $mock1->get_call_count() ); + $this->assertEquals( 0, $actions_run ); + + + add_filter( 'action_scheduler_queue_runner_concurrent_batches', array( $this, 'return_6' ) ); + + $mock2 = new MockAction(); + add_action( $random, array( $mock2, 'action' ) ); + $actions_run = $runner->run(); + remove_action( $random, array( $mock2, 'action' ) ); + + $this->assertEquals( 5, $mock2->get_call_count() ); + $this->assertEquals( 5, $actions_run ); + + remove_filter( 'action_scheduler_queue_runner_concurrent_batches', array( $this, 'return_6' ) ); + + for ( $i = 0 ; $i < 5 ; $i++ ) { // to make up for the actions we just processed + $action = new ActionScheduler_Action( $random, array($random), $schedule ); + $store->save_action( $action ); + } + + $mock3 = new MockAction(); + add_action( $random, array( $mock3, 'action' ) ); + $actions_run = $runner->run(); + remove_action( $random, array( $mock3, 'action' ) ); + + $this->assertEquals( 0, $mock3->get_call_count() ); + $this->assertEquals( 0, $actions_run ); + + remove_filter( 'action_scheduler_queue_runner_concurrent_batches', array( $this, 'return_6' ) ); + } + + public function return_6() { + return 6; + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/tests/phpunit/schedules/ActionScheduler_CronSchedule_Test.php b/vendor/gocodebox/action-scheduler/tests/phpunit/schedules/ActionScheduler_CronSchedule_Test.php new file mode 100644 index 0000000000..4d1ee9a799 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/tests/phpunit/schedules/ActionScheduler_CronSchedule_Test.php @@ -0,0 +1,45 @@ +<?php + +/** + * Class ActionScheduler_CronSchedule_Test + * @group schedules + */ +class ActionScheduler_CronSchedule_Test extends ActionScheduler_UnitTestCase { + public function test_creation() { + $time = as_get_datetime_object('tomorrow'); + $cron = CronExpression::factory('@daily'); + $schedule = new ActionScheduler_CronSchedule(as_get_datetime_object(), $cron); + $this->assertEquals( $time, $schedule->next() ); + } + + public function test_next() { + $time = as_get_datetime_object('2013-06-14'); + $cron = CronExpression::factory('@daily'); + $schedule = new ActionScheduler_CronSchedule($time, $cron); + $this->assertEquals( as_get_datetime_object('tomorrow'), $schedule->next( as_get_datetime_object() ) ); + } + + public function test_is_recurring() { + $schedule = new ActionScheduler_CronSchedule(as_get_datetime_object('2013-06-14'), CronExpression::factory('@daily')); + $this->assertTrue( $schedule->is_recurring() ); + } + + public function test_cron_format() { + $time = as_get_datetime_object('2014-01-01'); + $cron = CronExpression::factory('0 0 10 10 *'); + $schedule = new ActionScheduler_CronSchedule($time, $cron); + $this->assertEquals( as_get_datetime_object('2014-10-10'), $schedule->next() ); + + $cron = CronExpression::factory('0 0 L 1/2 *'); + $schedule = new ActionScheduler_CronSchedule($time, $cron); + $this->assertEquals( as_get_datetime_object('2014-01-31'), $schedule->next() ); + $this->assertEquals( as_get_datetime_object('2014-07-31'), $schedule->next( as_get_datetime_object('2014-06-01') ) ); + $this->assertEquals( as_get_datetime_object('2028-11-30'), $schedule->next( as_get_datetime_object('2028-11-01') ) ); + + $cron = CronExpression::factory('30 14 * * MON#3 *'); + $schedule = new ActionScheduler_CronSchedule($time, $cron); + $this->assertEquals( as_get_datetime_object('2014-01-20 14:30:00'), $schedule->next() ); + $this->assertEquals( as_get_datetime_object('2014-05-19 14:30:00'), $schedule->next( as_get_datetime_object('2014-05-01') ) ); + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/tests/phpunit/schedules/ActionScheduler_IntervalSchedule_Test.php b/vendor/gocodebox/action-scheduler/tests/phpunit/schedules/ActionScheduler_IntervalSchedule_Test.php new file mode 100644 index 0000000000..54cf9cc3cd --- /dev/null +++ b/vendor/gocodebox/action-scheduler/tests/phpunit/schedules/ActionScheduler_IntervalSchedule_Test.php @@ -0,0 +1,29 @@ +<?php + +/** + * Class ActionScheduler_IntervalSchedule_Test + * @group schedules + */ +class ActionScheduler_IntervalSchedule_Test extends ActionScheduler_UnitTestCase { + public function test_creation() { + $time = as_get_datetime_object(); + $schedule = new ActionScheduler_IntervalSchedule($time, HOUR_IN_SECONDS); + $this->assertEquals( $time, $schedule->next() ); + } + + public function test_next() { + $now = time(); + $start = $now - 30; + $schedule = new ActionScheduler_IntervalSchedule( as_get_datetime_object("@$start"), MINUTE_IN_SECONDS ); + $this->assertEquals( $start, $schedule->next()->format('U') ); + $this->assertEquals( $now + MINUTE_IN_SECONDS, $schedule->next(as_get_datetime_object())->format('U') ); + $this->assertEquals( $start, $schedule->next(as_get_datetime_object("@$start"))->format('U') ); + } + + public function test_is_recurring() { + $start = time() - 30; + $schedule = new ActionScheduler_IntervalSchedule( as_get_datetime_object("@$start"), MINUTE_IN_SECONDS ); + $this->assertTrue( $schedule->is_recurring() ); + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/tests/phpunit/schedules/ActionScheduler_NullSchedule_Test.php b/vendor/gocodebox/action-scheduler/tests/phpunit/schedules/ActionScheduler_NullSchedule_Test.php new file mode 100644 index 0000000000..cd2c601061 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/tests/phpunit/schedules/ActionScheduler_NullSchedule_Test.php @@ -0,0 +1,18 @@ +<?php + +/** + * Class ActionScheduler_NullSchedule_Test + * @group schedules + */ +class ActionScheduler_NullSchedule_Test extends ActionScheduler_UnitTestCase { + public function test_null_schedule() { + $schedule = new ActionScheduler_NullSchedule(); + $this->assertNull( $schedule->next() ); + } + + public function test_is_recurring() { + $schedule = new ActionScheduler_NullSchedule(); + $this->assertFalse( $schedule->is_recurring() ); + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/tests/phpunit/schedules/ActionScheduler_SimpleSchedule_Test.php b/vendor/gocodebox/action-scheduler/tests/phpunit/schedules/ActionScheduler_SimpleSchedule_Test.php new file mode 100644 index 0000000000..022dd66aad --- /dev/null +++ b/vendor/gocodebox/action-scheduler/tests/phpunit/schedules/ActionScheduler_SimpleSchedule_Test.php @@ -0,0 +1,37 @@ +<?php + +/** + * Class ActionScheduler_SimpleSchedule_Test + * @group schedules + */ +class ActionScheduler_SimpleSchedule_Test extends ActionScheduler_UnitTestCase { + public function test_creation() { + $time = as_get_datetime_object(); + $schedule = new ActionScheduler_SimpleSchedule($time); + $this->assertEquals( $time, $schedule->next() ); + } + + public function test_past_date() { + $time = as_get_datetime_object('-1 day'); + $schedule = new ActionScheduler_SimpleSchedule($time); + $this->assertEquals( $time, $schedule->next() ); + } + + public function test_future_date() { + $time = as_get_datetime_object('+1 day'); + $schedule = new ActionScheduler_SimpleSchedule($time); + $this->assertEquals( $time, $schedule->next() ); + } + + public function test_grace_period_for_next() { + $time = as_get_datetime_object('3 seconds ago'); + $schedule = new ActionScheduler_SimpleSchedule($time); + $this->assertEquals( $time, $schedule->next() ); + } + + public function test_is_recurring() { + $schedule = new ActionScheduler_SimpleSchedule(as_get_datetime_object('+1 day')); + $this->assertFalse( $schedule->is_recurring() ); + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/tests/phpunit/versioning/ActionScheduler_Versions_Test.php b/vendor/gocodebox/action-scheduler/tests/phpunit/versioning/ActionScheduler_Versions_Test.php new file mode 100644 index 0000000000..9e79e02459 --- /dev/null +++ b/vendor/gocodebox/action-scheduler/tests/phpunit/versioning/ActionScheduler_Versions_Test.php @@ -0,0 +1,43 @@ +<?php + +/** + * Class ActionScheduler_Versions_Test + */ +class ActionScheduler_Versions_Test extends ActionScheduler_UnitTestCase { + public function test_register_version() { + $versions = new ActionScheduler_Versions(); + $versions->register('1.0-dev', 'callback_1_dot_0_dev'); + $versions->register('1.0', 'callback_1_dot_0'); + + $registered = $versions->get_versions(); + + $this->assertArrayHasKey( '1.0-dev', $registered ); + $this->assertArrayHasKey( '1.0', $registered ); + $this->assertCount( 2, $registered ); + + $this->assertEquals( 'callback_1_dot_0_dev', $registered['1.0-dev'] ); + } + + public function test_duplicate_version() { + $versions = new ActionScheduler_Versions(); + $versions->register('1.0', 'callback_1_dot_0_a'); + $versions->register('1.0', 'callback_1_dot_0_b'); + + $registered = $versions->get_versions(); + + $this->assertArrayHasKey( '1.0', $registered ); + $this->assertCount( 1, $registered ); + } + + public function test_latest_version() { + $versions = new ActionScheduler_Versions(); + $this->assertEquals('__return_null', $versions->latest_version_callback() ); + $versions->register('1.2', 'callback_1_dot_2'); + $versions->register('1.3', 'callback_1_dot_3'); + $versions->register('1.0', 'callback_1_dot_0'); + + $this->assertEquals( '1.3', $versions->latest_version() ); + $this->assertEquals( 'callback_1_dot_3', $versions->latest_version_callback() ); + } +} + \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/tests/travis/setup.sh b/vendor/gocodebox/action-scheduler/tests/travis/setup.sh new file mode 100755 index 0000000000..82fc09d95c --- /dev/null +++ b/vendor/gocodebox/action-scheduler/tests/travis/setup.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +# WordPress test setup script for Travis CI +# +# Author: Benjamin J. Balter ( ben@balter.com | ben.balter.com ) +# License: GPL3 + +export WP_CORE_DIR=/tmp/wordpress +export WP_TESTS_DIR=/tmp/wordpress-tests/tests/phpunit + +plugin_slug=$(basename $(pwd)) +plugin_dir=$WP_CORE_DIR/wp-content/plugins/$plugin_slug + +# Init database +mysql -e 'CREATE DATABASE wordpress_test;' -uroot + +# Grab specified version of WordPress from github +wget -nv -O /tmp/wordpress.tar.gz https://github.com/WordPress/WordPress/tarball/$WP_VERSION +mkdir -p $WP_CORE_DIR +tar --strip-components=1 -zxmf /tmp/wordpress.tar.gz -C $WP_CORE_DIR + +# Grab testing framework +svn co --quiet https://develop.svn.wordpress.org/tags/$WP_VERSION/ /tmp/wordpress-tests + +# Put various components in proper folders +cp tests/travis/wp-tests-config.php $WP_TESTS_DIR/wp-tests-config.php + +cd .. +mv $plugin_slug $plugin_dir + +cd $plugin_dir \ No newline at end of file diff --git a/vendor/gocodebox/action-scheduler/tests/travis/wp-tests-config.php b/vendor/gocodebox/action-scheduler/tests/travis/wp-tests-config.php new file mode 100644 index 0000000000..f626da090a --- /dev/null +++ b/vendor/gocodebox/action-scheduler/tests/travis/wp-tests-config.php @@ -0,0 +1,38 @@ +<?php + +/* Path to the WordPress codebase you'd like to test. Add a backslash in the end. */ +define( 'ABSPATH', getenv( 'WP_CORE_DIR' ) . '/' ); + +// Test with multisite enabled +define( 'WP_TESTS_MULTISITE', (bool) getenv( 'WP_MULTISITE' ) ); + +// Force known bugs +// define( 'WP_TESTS_FORCE_KNOWN_BUGS', true ); + +// Test with WordPress debug mode on +define( 'WP_DEBUG', true ); + +// ** MySQL settings ** // + +// This configuration file will be used by the copy of WordPress being tested. +// wordpress/wp-config.php will be ignored. + +// WARNING WARNING WARNING! +// These tests will DROP ALL TABLES in the database with the prefix named below. +// DO NOT use a production database or one that is shared with something else. + +define( 'DB_NAME', 'wordpress_test' ); +define( 'DB_USER', 'root' ); +define( 'DB_PASSWORD', '' ); +define( 'DB_HOST', 'localhost' ); +define( 'DB_CHARSET', 'utf8' ); +define( 'DB_COLLATE', '' ); + +define( 'WP_TESTS_DOMAIN', 'example.org' ); +define( 'WP_TESTS_EMAIL', 'admin@example.org' ); +define( 'WP_TESTS_TITLE', 'Test Blog' ); + +define( 'WP_PHP_BINARY', 'php' ); + +define( 'WPLANG', '' ); +$table_prefix = 'wptests_'; \ No newline at end of file