├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── README.md ├── TESTING.md ├── TROUBLESHOOTING.md ├── ajax.php ├── amd ├── build │ ├── migration_tool_launch.min.js │ ├── migration_tool_migrate.min.js │ └── modal_migration_tool.min.js └── src │ ├── migration_tool_launch.js │ ├── migration_tool_migrate.js │ └── modal_migration_tool.js ├── backup └── moodle2 │ ├── backup_turnitintooltwo_activity_task.class.php │ ├── backup_turnitintooltwo_stepslib.php │ ├── restore_turnitintooltwo_activity_task.class.php │ └── restore_turnitintooltwo_stepslib.php ├── classes ├── digitalreceipt │ ├── instructor_message.php │ └── receipt_message.php ├── event │ ├── add_submission.php │ ├── delete_submission.php │ ├── list_submissions.php │ ├── migrate_assignment.php │ └── view_submission.php ├── nonsubmitters │ └── nonsubmitters_message.php ├── privacy │ └── provider.php ├── task │ └── turnitintooltwo_task.php ├── v1migration │ └── v1migration.php └── view │ └── members.php ├── css ├── bootstrap.min.css ├── colorbox.css ├── fontawesome.min.css ├── hide_bg.css ├── jquery-ui-1.8.4.custom.css ├── jqueryui-editable.css ├── student_noscript.css ├── styles_block.css ├── tii-icon-webfont.css └── tooltipster.css ├── db ├── access.php ├── install.php ├── install.xml ├── log.php ├── messages.php ├── tasks.php └── upgrade.php ├── extras.php ├── fonts ├── tii-icon-webfont.eot ├── tii-icon-webfont.svg ├── tii-icon-webfont.ttf └── tii-icon-webfont.woff ├── gulpfile.js ├── index.php ├── jquery ├── colorbox.css ├── jquery.colorbox.js ├── jquery.cookie.js ├── jquery.dataTables.columnFilter.js ├── jquery.dataTables.css ├── jquery.dataTables.js ├── jquery.dataTables.plugins.js ├── jquery.tooltipster.js ├── jqueryui-editable.css ├── jqueryui-editable.js ├── moment.js ├── plugins.php ├── tooltipster.css ├── turnitintooltwo-2025070302.js ├── turnitintooltwo-2025070302.min.js ├── turnitintooltwo-2025070302.min.js.map ├── turnitintooltwo_extra-2024120301.js ├── turnitintooltwo_extra-2024120301.min.js ├── turnitintooltwo_extra-2024120301.min.js.map ├── turnitintooltwo_settings-2025070302.js ├── turnitintooltwo_settings-2025070302.min.js └── turnitintooltwo_settings-2025070302.min.js.map ├── lang ├── ar │ └── turnitintooltwo.php ├── ca │ └── turnitintooltwo.php ├── cs │ └── turnitintooltwo.php ├── de │ └── turnitintooltwo.php ├── en │ └── turnitintooltwo.php ├── es │ └── turnitintooltwo.php ├── fi │ └── turnitintooltwo.php ├── fr │ └── turnitintooltwo.php ├── it │ └── turnitintooltwo.php ├── ja │ └── turnitintooltwo.php ├── ko │ └── turnitintooltwo.php ├── nl │ └── turnitintooltwo.php ├── pl │ └── turnitintooltwo.php ├── pt_br │ └── turnitintooltwo.php ├── ro │ └── turnitintooltwo.php ├── ru │ └── turnitintooltwo.php ├── sv │ └── turnitintooltwo.php ├── tr │ └── turnitintooltwo.php ├── vi │ └── turnitintooltwo.php ├── zh_cn │ └── turnitintooltwo.php └── zh_tw │ └── turnitintooltwo.php ├── lib.php ├── mod_form.php ├── package-lock.json ├── package.json ├── pix ├── back_disabled.png ├── back_enabled.png ├── back_enabled_hover.png ├── bootstrap │ ├── glyphicons-halflings-white.png │ └── glyphicons-halflings.png ├── changelog │ └── resetcourse.png ├── clear.png ├── clearpixel.gif ├── colorbox │ ├── controls.png │ └── loading.gif ├── doc-x-grey.png ├── enrolicon.gif ├── fileicon.gif ├── forward_disabled.png ├── forward_enabled.png ├── forward_enabled_hover.png ├── globe.png ├── icon-dot.png ├── icon-student-read.png ├── icon.gif ├── icon.png ├── jqueryui │ ├── ui-bg_flat_0_aaaaaa_40x100.png │ ├── ui-bg_flat_75_ffffff_40x100.png │ ├── ui-bg_glass_55_fbf9ee_1x400.png │ ├── ui-bg_glass_65_ffffff_1x400.png │ ├── ui-bg_glass_75_dadada_1x400.png │ ├── ui-bg_glass_75_e6e6e6_1x400.png │ ├── ui-bg_glass_95_fef1ec_1x400.png │ ├── ui-bg_highlight-soft_75_cccccc_1x100.png │ ├── ui-icons_222222_256x240.png │ ├── ui-icons_2e83ff_256x240.png │ ├── ui-icons_454545_256x240.png │ ├── ui-icons_888888_256x240.png │ └── ui-icons_cd0a0a_256x240.png ├── loader-lrg.gif ├── loader.gif ├── loading.gif ├── minus.gif ├── nextdisabled.png ├── nextenabled.png ├── order_down.gif ├── order_up.gif ├── peermark-reviews.png ├── peermark-settings.png ├── plus.gif ├── prevdisabled.png ├── prevenabled.png ├── printer.png ├── quickmark.png ├── receipt.png ├── refresh.gif ├── refreshfade.gif ├── rubric.png ├── sort_asc.png ├── sort_asc_disabled.png ├── sort_both.png ├── sort_desc.png ├── sort_desc_disabled.png ├── sortdown.png ├── sortnone.png ├── sortup.png ├── tick.png ├── tii-icon.png └── tii-logo.png ├── sass ├── _other.scss ├── _utilities.scss ├── _variables.scss ├── partials │ ├── _digital_receipt.scss │ ├── _eula.scss │ ├── _inbox.scss │ ├── _listbar.scss │ ├── _members.scss │ ├── _modal.scss │ ├── _part_details.scss │ └── _table.scss ├── settings_partials │ ├── _class_migration_tab.scss │ └── _settings_tab.scss └── styles.scss ├── sdk ├── api.class.php ├── assignmentsoap.class.php ├── classsoap.class.php ├── log.class.php ├── logger.php ├── lti.class.php ├── membershipsoap.class.php ├── oauthsimple.class.php ├── perflog.class.php ├── response.class.php ├── sdkexception.class.php ├── soap.class.php ├── submissionsoap.class.php ├── tiiassignment.class.php ├── tiiclass.class.php ├── tiiform.class.php ├── tiilti.class.php ├── tiimembership.class.php ├── tiipeermarkassignment.class.php ├── tiipseudouser.class.php ├── tiirubric.class.php ├── tiisubmission.class.php ├── tiiuser.class.php ├── usersoap.class.php └── wsdl │ ├── lis-coursesection.wsdl │ ├── lis-lineitem.wsdl │ ├── lis-membership.wsdl │ ├── lis-person.wsdl │ └── lis-result.wsdl ├── settings.php ├── settings_extras.php ├── settingslib.php ├── styles.css ├── styles.css.map ├── templates └── modal_migration_tool.mustache ├── tests └── unit │ ├── classes │ ├── digitalreceipt │ │ ├── instructor_message_test.php │ │ └── receipt_message_test.php │ ├── nonsubmitters │ │ └── nonsubmitters_message_test.php │ ├── privacy │ │ └── provider_test.php │ ├── v1migration │ │ └── v1migration_test.php │ └── view │ │ ├── members_test.php │ │ └── turnitintooltwo_view_test.php │ ├── generator │ └── lib.php │ ├── lib_test.php │ ├── mod_form_test.php │ ├── turnitintooltwo_assignment_test.php │ ├── turnitintooltwo_comms_test.php │ └── turnitintooltwo_submission_test.php ├── turnitintooltwo_assignment.class.php ├── turnitintooltwo_class.class.php ├── turnitintooltwo_comms.class.php ├── turnitintooltwo_form.class.php ├── turnitintooltwo_perflog.class.php ├── turnitintooltwo_submission.class.php ├── turnitintooltwo_user.class.php ├── turnitintooltwo_view.class.php ├── version.php └── view.php /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .git 3 | .vscode/ 4 | 5 | # Ignore Node.js modules 6 | node_modules/ 7 | /.settings/ 8 | /.buildpath 9 | /.project 10 | /.idea 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | sudo: false 4 | 5 | cache: 6 | directories: 7 | - $HOME/.composer/cache 8 | 9 | php: 10 | - 7.1 11 | - 7.2 12 | 13 | services: 14 | - mysql 15 | - postgresql 16 | 17 | env: 18 | global: 19 | - IGNORE_PATHS=sdk/,fonts/,pix/ 20 | - IGNORE_NAMES=jquery*,moment.js,colorbox.css,tooltipster.css,*.min.css,*.min.js,tii-icon-webfont.css,styles.css,styles.css.map,gulpfile.js 21 | matrix: 22 | - DB=pgsql MOODLE_BRANCH=MOODLE_36_STABLE 23 | - DB=mysqli MOODLE_BRANCH=MOODLE_36_STABLE 24 | - DB=pgsql MOODLE_BRANCH=MOODLE_37_STABLE 25 | - DB=mysqli MOODLE_BRANCH=MOODLE_37_STABLE 26 | - DB=pgsql MOODLE_BRANCH=MOODLE_38_STABLE 27 | - DB=mysqli MOODLE_BRANCH=MOODLE_38_STABLE 28 | 29 | before_install: 30 | - phpenv config-rm xdebug.ini 31 | - cd ../.. 32 | - composer selfupdate 33 | - composer create-project -n --no-dev --prefer-dist blackboard-open-source/moodle-plugin-ci ci ^1 34 | - export PATH="$(cd ci/bin; pwd):$(cd ci/vendor/bin; pwd):$PATH" 35 | 36 | install: 37 | - moodle-plugin-ci install 38 | 39 | script: 40 | - moodle-plugin-ci phplint 41 | - moodle-plugin-ci phpmd 42 | - moodle-plugin-ci csslint 43 | - moodle-plugin-ci shifter 44 | - moodle-plugin-ci validate 45 | - moodle-plugin-ci phpunit -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Announcement - Issues page merged with Turnitin's support page 2 | ================ 3 | 4 | In order to be able to better monitor incoming issues, we are consolidating the 3 issues pages for the 2 plagiarism plugins and Direct v2 with our existing support area. 5 | 6 | The support area is how our team currently monitors issues for every other area of Turnitin. Therefore, we will be closing the Issues pages. If you have issues with Turnitin Direct v2, please raise them here: https://helpcenter.turnitin.com/hc/en-us/requests/new 7 | 8 | The team appreciates your ongoing support and contributions. Thank you! 9 | 10 | Moodle Direct v2 11 | ================ 12 | 13 | Please be aware that the **Develop** branch should not be considered production ready, although it contains the latest fixes and features it may contain bugs. It should be avoided in favour of the **Master** branch which is the latest available branch that has been through the QA process. Please make any pull requests you would like to make to the develop branch. 14 | 15 | To see what has changed in recent versions of Moodle Direct V2, see the [CHANGELOG](https://github.com/turnitin/moodle-mod_turnitintooltwo/blob/master/CHANGELOG.md). 16 | 17 | If you are having issues, please consult our [TROUBLE SHOOTING](https://github.com/turnitin/moodle-mod_turnitintooltwo/blob/master/TROUBLESHOOTING.md) page. 18 | 19 | Installation 20 | ------------ 21 | 22 | Before installing these plugins firstly make sure you are logged in as an Administrator and that you are using Moodle 3.5 or higher. 23 | 24 | To install, all you need to do is copy all the files into the mod/turnitintooltwo directory on your moodle installation. You should then go to `"Site Administration" > "Notifications"` and follow the on screen instructions. 25 | 26 | To configure the plugin go to `"Site Administration" > "Plugins" > "Activity Modules" > "Turnitin Assignment 2"` and enter your Turnitin account Id, shared key and API URL. 27 | 28 | **Note:** *The API connection URL is different for this package to previous Turnitin plugins. It should be https://api.turnitin.com, https://api.turnitinuk.com. or https://sandbox.turnitin.com.* 29 | 30 | Testing 31 | ------- 32 | 33 | Please see the [testing instructions](./TESTING.md) for detail instructions on running the unit tests. 34 | 35 | Contributions 36 | ------------------------------ 37 | 38 | We welcome contributions to all elements of the plugin. Since launch we've had a number of users provide us with fixes and enhancements through either pull request or commits linked to from the issues page. If you are interested in contributing enhancements, or would like to solve an issue raised by another user, please feel free to make a pull request against the develop branch. 39 | 40 | ------------------------------ -------------------------------------------------------------------------------- /TESTING.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | To run the unit tests you will require PHP, Composer, a working Moodle installation and an installed copy of the plugin. The following guide explains how to do this. 3 | 4 | ## Set up a local Moodle environment 5 | You may well have a local Moodle setup already. If so, skip this step. 6 | 7 | If not, the easiet way to get Moodle set up on a Mac is with the MAMP Moodle installers. 8 | 9 | Grab an installer for the latest stable version from here: 10 | 11 | [https://download.moodle.org/macosx/](https://download.moodle.org/macosx/) 12 | 13 | ## Set up PHP 14 | 15 | You will need PHP and [Composer](https://getcomposer.org/) installed. 16 | 17 | ## Install the plugin 18 | Grab a copy of the plugin. 19 | 20 | [https://github.com/turnitin/moodle-mod_turnitintooltwo](https://github.com/turnitin/moodle-mod_turnitintooltwo) 21 | 22 | Put the plugin in the `mod` folder inside your Moodle installation. 23 | 24 | Go to the admin notifications screen in Moodle to install the plugin. 25 | 26 | ## Prepare Moodle for running unit tests 27 | 28 | * `cd` into the root folder of your Moodle installation. From here run `composer install` to install the required dependencies. 29 | 30 | * Edit `config.php` in the root of the Moodle folder and add the `phpunit` config. The following works for the MAMP Moodle install mentioned above: 31 | 32 | ``` 33 | $CFG->phpunit_prefix = 'phpu_'; 34 | $CFG->phpunit_dataroot = '/Applications/MAMP/data/phpu_moodledata'; 35 | $CFG->phpunit_dbtype = 'mysqli'; // 'pgsql', 'mariadb', 'mysqli', 'mssql', 'sqlsrv' or 'oci' 36 | $CFG->phpunit_dbhost = '127.0.0.1:8889'; // eg 'localhost' or 'db.isp.com' or IP 37 | $CFG->phpunit_dbname = 'moodle31'; // database name, eg moodle 38 | $CFG->phpunit_dbuser = 'moodle'; // your database username 39 | $CFG->phpunit_dbpass = 'moodle'; // your database password 40 | ``` 41 | 42 | * Run `php admin/tool/phpunit/cli/init.php` 43 | 44 | ## Run the tests 45 | 46 | To run the test commands, make sure you are in the root directory of Moodle. 47 | 48 | Run the whole test suite: 49 | 50 | `vendor/bin/phpunit --testsuite mod_turnitintooltwo_testsuite` 51 | 52 | Run only a specific test file: 53 | 54 | `vendor/bin/phpunit -v mod/turnitintooltwo/tests/unit/classes/digitalreceipt/receipt_message_test.php` 55 | 56 | -------------------------------------------------------------------------------- /TROUBLESHOOTING.md: -------------------------------------------------------------------------------- 1 | #Moodle Direct V2 Troubleshooting 2 | 3 | 1) You may need to ensure that within your designated moodledata directory; the turnitintooltwo subdirectory and the subsequent logs subdirectory have the correct permissions to be able to create directories and files. 4 | 5 | 2) You may need to ensure that the turnitintooltwo directory within your designated data directory and it's logs subdirectory have the correct permissions to be able to create directories and files. 6 | 7 | 3) Pop-ups will need to be enabled on the browser being used if access to the Turnitin Document Viewer is required. 8 | 9 | 4) There have been very isolated reports of the settings not showing for the Plagiarism plugin despite it being enabled, this is due to it not showing in Moodle cache. The solution is for an administrator to purge all caches and it should then appear. 10 | 11 | ##Required PHP Extensions 12 | 13 | In order for the module to work correctly you must enable the following PHP extensions: 14 | 15 | **cURL** 16 | 17 | >You must enable support for cURL in your php.ini file. To do this locate the following line in your php.ini file: 18 | 19 | >;extension=php_curl.dll 20 | >OR 21 | >;extension=php_curl.so 22 | 23 | >Remove the semi-colon at the start of the line to activate the php cURL extension. Once you have done this you will need to restart your web server service. 24 | 25 | >More information on cURL and more detailed instructions for installing it can be found here: http://uk3.php.net/curl 26 | 27 | 28 | **XMLWriter** 29 | 30 | >This is normally enabled by default but if PHP was compiled with --disable-xmlreader set then you will need to recompile PHP without --disable-xmlreader set. 31 | 32 | 33 | **MBstring** 34 | 35 | >You may be able to enable this setting by uncommenting the extension listing in your php.ini file: 36 | 37 | >;extension=php_mbstring.dll 38 | 39 | >Remove the semi-colon at the start of the line to activate the MBstring extension. Once you have done this you will need to restart your web server service. 40 | 41 | >If you can't find this line in your php.ini file then you may need to install the php-mbstring first. For further information see: http://php.net/manual/en/mbstring.installation.php 42 | 43 | **fileinfo** 44 | 45 | >This extension is enabled by default as of PHP 5.3.0. Windows users must include the bundled php_fileinfo.dll DLL file in php.ini to enable this extension. 46 | 47 | >For further information see http://php.net/manual/en/fileinfo.installation.php. 48 | 49 | **SOAP** 50 | 51 | >To enable SOAP support, configure PHP with --enable-soap. 52 | 53 | >For futher information see http://php.net/manual/en/intro.soap.php. 54 | 55 | ##cURL Connectivity 56 | 57 | If you encounter connectivity issues (error: Turnitin API Base URL incorrect or unavailable) this could be related to a CA certificate being unavailable to cURL. 58 | 59 | If cURL has an out of date (or no) CA certificates, the interaction with Turnitin will fail due to cURL performing peer SSL certificate verification and not being able to verify the Turnitin SSL certificate. 60 | Until cURL 7.18.0 some CA certificates were provided, but after 7.18.0 no cs certificates have been provided at all. Because of this, the Moodle server administrator would need to ensure that an up to date CA certificate bundle is used. To be clear, Moodle doesn't need an SSL certificate, however, it needs to have the certificate bundle in place so cURL can recognize the SSL certificates of Turnitin. 61 | 62 | Information on how to install a certificate bundle is available via the URLs below. Note that the URLs are third party sites and not affiliated with Turnitin or iParadigms in any way: 63 | 64 | Information for Linux environments: http://docs.moodle.org/26/en/SSL_certificate_for_moodle.org 65 | 66 | Information for Windows environments: http://curl.haxx.se/docs/sslcerts.html 67 | 68 | ##WSDL 69 | 70 | We have had reported issues with users not being able to parse the WSDL files that the API requires. The relevant error message starts “PHP Fatal error: SOAP-ERROR: Parsing WSDL: ….” 71 | 72 | From version 2014012405 onwards we have bundled the WSDL files with the plugin download, however the issue does still occur for some users. This is due to a PHP bug with libxml_disable_entity_loader() being set to true and preventing external entities from being loaded. If this is set by a PHP script then PHP uses this value for all processes on the server. For further information see: https://bugs.php.net/bug.php?id=64938. 73 | 74 | To fix this, you need to add the following line to your to your moodle config.php: 75 | 76 | libxml_disable_entity_loader(false); 77 | 78 | Thanks to Dan Marsden for the information and solution. 79 | -------------------------------------------------------------------------------- /amd/build/migration_tool_launch.min.js: -------------------------------------------------------------------------------- 1 | define(["jquery","core/templates","core/modal_factory","core/modal_events","mod_turnitintooltwo/modal_migration_tool","mod_turnitintooltwo/migration_tool_migrate"],function(a,b,c,d,e,f){return{migration_tool_launch:function(){a.ajax({dataType:"json",type:"POST",url:M.cfg.wwwroot+"/mod/turnitintooltwo/ajax.php",data:{action:"check_migrated",turnitintoolid:a("#migrate_type").data("turnitintoolid"),sesskey:M.cfg.sesskey},success:function(b){b.migrated===!0?window.location.href=M.cfg.wwwroot+"/mod/turnitintooltwo/view.php?id="+b.v2id:c.create({type:e.TYPE}).then(function(b){b.show(),2===a("#migrate_type").data("migratetype")&&(a(".asktomigrate").hide(),a(".migrating").show(),f.migration_tool_migrate(a("#migrate_type").data("courseid"),a("#migrate_type").data("turnitintoolid")))})}})}}}); -------------------------------------------------------------------------------- /amd/build/migration_tool_migrate.min.js: -------------------------------------------------------------------------------- 1 | define(["jquery"],function(a){return{migration_tool_migrate:function(b,c){a.ajax({dataType:"json",type:"POST",url:M.cfg.wwwroot+"/mod/turnitintooltwo/ajax.php",data:{action:"begin_migration",courseid:b,turnitintoolid:c,sesskey:M.cfg.sesskey},success:function(a){window.location.href=M.cfg.wwwroot+"/mod/turnitintooltwo/view.php?id="+a.id},error:function(b){var c=b.responseJSON;a("#turnitintool_style").prepend('
'+c.error+" "+c.message+"
")}})}}}); -------------------------------------------------------------------------------- /amd/build/modal_migration_tool.min.js: -------------------------------------------------------------------------------- 1 | define(["jquery","core/notification","core/custom_interaction_events","core/modal","core/modal_registry","core/modal_events","core/config","mod_turnitintooltwo/migration_tool_migrate"],function(a,b,c,d,e,f,g,h){var i=!1,j={MIGRATE_BUTTON:'[data-action="migrate-assignment"]',CANCEL_BUTTON:'[data-action="cancel"]'},k=function(a){d.call(this,a)};return k.TYPE="mod_turnitintooltwo-migration_tool",k.prototype=Object.create(d.prototype),k.prototype.constructor=k,k.prototype.registerEventListeners=function(){d.prototype.registerEventListeners.call(this),this.getModal().on(c.events.activate,j.MIGRATE_BUTTON,function(){a(".asktomigrate").hide(),a(".migrating").show(),h.migration_tool_migrate(a("#migrate_type").data("courseid"),a("#migrate_type").data("turnitintoolid"))}.bind(this)),this.getModal().on(c.events.activate,j.CANCEL_BUTTON,function(b,c){var d=a.Event(f.cancel);this.getRoot().trigger(d,this),d.isDefaultPrevented()||(this.hide(),c.originalEvent.preventDefault())}.bind(this))},i||(e.register(k.TYPE,k,"mod_turnitintooltwo/modal_migration_tool"),i=!0),k}); -------------------------------------------------------------------------------- /amd/src/migration_tool_launch.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Javascript controller for launching the migration tool modal. 3 | * 4 | * @package turnitintooltwo 5 | * @copyright Turnitin 6 | * @author 2019 David Winn 7 | * @module mod_turnitintooltwo/migration_tool_launch 8 | */ 9 | 10 | define(['jquery', 11 | 'core/templates', 12 | 'core/modal_factory', 13 | 'core/modal_events', 14 | 'mod_turnitintooltwo/modal_migration_tool', 15 | 'mod_turnitintooltwo/migration_tool_migrate' 16 | ], 17 | function($, Templates, ModalFactory, ModalEvents, ModalMigrationTool, MigrationToolMigrate) { 18 | return { 19 | migration_tool_launch: function() { 20 | // Check whether this assignment has been migrated in this session and redirect if so. 21 | $.ajax({ 22 | "dataType": 'json', 23 | "type": "POST", 24 | "url": M.cfg.wwwroot + "/mod/turnitintooltwo/ajax.php", 25 | "data": { 26 | action: "check_migrated", 27 | turnitintoolid: $("#migrate_type").data("turnitintoolid"), 28 | sesskey: M.cfg.sesskey 29 | }, 30 | "success": function(data) { 31 | if (data.migrated === true) { 32 | window.location.href = M.cfg.wwwroot + "/mod/turnitintooltwo/view.php?id="+data.v2id; 33 | } else { 34 | ModalFactory.create({ 35 | type: ModalMigrationTool.TYPE 36 | }) 37 | .then(function(modal) { 38 | modal.show(); 39 | 40 | // During automatic migration, we don't need to ask to migrate. 41 | if ($('#migrate_type').data("migratetype") === 2) { 42 | $('.asktomigrate').hide(); 43 | $('.migrating').show(); 44 | 45 | MigrationToolMigrate.migration_tool_migrate( 46 | $("#migrate_type").data("courseid"), 47 | $("#migrate_type").data("turnitintoolid") 48 | ); 49 | } 50 | }); 51 | } 52 | } 53 | }); 54 | } 55 | }; 56 | } 57 | ); -------------------------------------------------------------------------------- /amd/src/migration_tool_migrate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Javascript module for handling the migration of an assignment. 3 | * 4 | * @package turnitintooltwo 5 | * @copyright Turnitin 6 | * @author 2019 David Winn 7 | * @module mod_turnitintooltwo/migration_tool_migrate 8 | */ 9 | 10 | define(['jquery'], 11 | function($) { 12 | return { 13 | migration_tool_migrate: function(courseid, turnitintoolid) { 14 | $.ajax({ 15 | "dataType": 'json', 16 | "type": "POST", 17 | url: M.cfg.wwwroot + "/mod/turnitintooltwo/ajax.php", 18 | "data": {action: "begin_migration", courseid: courseid, turnitintoolid: turnitintoolid, sesskey: M.cfg.sesskey}, 19 | success: function(data) { 20 | window.location.href = M.cfg.wwwroot + "/mod/turnitintooltwo/view.php?id="+data.id; 21 | }, 22 | error: function(error) { 23 | var data = error.responseJSON; 24 | $('#turnitintool_style') 25 | .prepend('
' + 26 | data.error + ' ' + data.message + '
'); 27 | } 28 | }); 29 | } 30 | }; 31 | } 32 | ); -------------------------------------------------------------------------------- /amd/src/modal_migration_tool.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Javascript controller for the migration tool modal. 3 | * 4 | * @package turnitintooltwo 5 | * @copyright Turnitin 6 | * @author 2019 David Winn 7 | * @module mod_turnitintooltwo/migration_tool 8 | */ 9 | 10 | define([ 11 | 'jquery', 12 | 'core/notification', 13 | 'core/custom_interaction_events', 14 | 'core/modal', 15 | 'core/modal_registry', 16 | 'core/modal_events', 17 | 'core/config', 18 | 'mod_turnitintooltwo/migration_tool_migrate' 19 | ], 20 | function($, Notification, CustomEvents, Modal, ModalRegistry, ModalEvents, Config, MigrationToolMigrate) { 21 | 22 | var registered = false; 23 | var SELECTORS = { 24 | MIGRATE_BUTTON: '[data-action="migrate-assignment"]', 25 | CANCEL_BUTTON: '[data-action="cancel"]' 26 | }; 27 | 28 | /** 29 | * Constructor for the Modal. 30 | * 31 | * @param {object} root The root jQuery element for the modal 32 | */ 33 | var ModalMigrationTool = function(root) { 34 | Modal.call(this, root); 35 | }; 36 | 37 | ModalMigrationTool.TYPE = 'mod_turnitintooltwo-migration_tool'; 38 | ModalMigrationTool.prototype = Object.create(Modal.prototype); 39 | ModalMigrationTool.prototype.constructor = ModalMigrationTool; 40 | 41 | /** 42 | * Set up all of the event handling for the modal. 43 | * 44 | * @method registerEventListeners 45 | */ 46 | ModalMigrationTool.prototype.registerEventListeners = function() { 47 | // Apply parent event listeners. 48 | Modal.prototype.registerEventListeners.call(this); 49 | 50 | // Fired during a manual migration when clicking to migrate the assignment. Initiate the migration process. 51 | this.getModal().on(CustomEvents.events.activate, SELECTORS.MIGRATE_BUTTON, function() { 52 | $('.asktomigrate').hide(); 53 | $('.migrating').show(); 54 | 55 | MigrationToolMigrate.migration_tool_migrate( 56 | $("#migrate_type").data("courseid"), 57 | $("#migrate_type").data("turnitintoolid") 58 | ); 59 | }.bind(this)); 60 | 61 | // On cancel, then hide the modal. 62 | this.getModal().on(CustomEvents.events.activate, SELECTORS.CANCEL_BUTTON, function(e, data) { 63 | 64 | var cancelEvent = $.Event(ModalEvents.cancel); 65 | this.getRoot().trigger(cancelEvent, this); 66 | 67 | if (!cancelEvent.isDefaultPrevented()) { 68 | this.hide(); 69 | data.originalEvent.preventDefault(); 70 | } 71 | }.bind(this)); 72 | }; 73 | 74 | // Automatically register with the modal registry the first time this module is imported so that 75 | // you can create modals of this type using the modal factory. 76 | if (!registered) { 77 | ModalRegistry.register(ModalMigrationTool.TYPE, ModalMigrationTool, 'mod_turnitintooltwo/modal_migration_tool'); 78 | registered = true; 79 | } 80 | 81 | return ModalMigrationTool; 82 | } 83 | ); -------------------------------------------------------------------------------- /backup/moodle2/backup_turnitintooltwo_activity_task.class.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * @package moodlecore 19 | * @subpackage backup-moodle2 20 | * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} 21 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 22 | */ 23 | 24 | defined('MOODLE_INTERNAL') || die(); 25 | 26 | require_once($CFG->dirroot . '/mod/turnitintooltwo/backup/moodle2/backup_turnitintooltwo_stepslib.php'); 27 | 28 | /** 29 | * turnitintooltwo backup task that provides all the settings and steps to perform one 30 | * complete backup of the activity 31 | */ 32 | class backup_turnitintooltwo_activity_task extends backup_activity_task { 33 | 34 | // Define (add) particular settings this activity can have. 35 | protected function define_my_settings() { 36 | // No particular settings for this activity. 37 | } 38 | 39 | // Define (add) particular steps this activity can have. 40 | protected function define_my_steps() { 41 | // Choice only has one structure step. 42 | $this->add_step(new backup_turnitintooltwo_activity_structure_step('turnitintooltwo_structure', 'turnitintooltwo.xml')); 43 | } 44 | 45 | // Code the transformations to perform in the activity in order to get transportable (encoded) links. 46 | static public function encode_content_links($content) { 47 | global $CFG; 48 | 49 | $base = preg_quote($CFG->wwwroot, "/"); 50 | 51 | // Link to the list of turnitintooltwos. 52 | $search = "/(".$base."\/mod\/turnitintooltwo\/index.php\?id\=)([0-9]+)/"; 53 | $content = preg_replace($search, '$@TURNITINTOOLTWOINDEX*$2@$', $content); 54 | 55 | // Link to turnitintooltwo view by moduleid. 56 | $search = "/(".$base."\/mod\/turnitintooltwo\/view.php\?id\=)([0-9]+)/"; 57 | $content = preg_replace($search, '$@TURNITINTOOLTWOVIEWBYID*$2@$', $content); 58 | 59 | return $content; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /backup/moodle2/backup_turnitintooltwo_stepslib.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * @package moodlecore 19 | * @subpackage backup-moodle2 20 | * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} 21 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 22 | */ 23 | 24 | defined('MOODLE_INTERNAL') || die(); 25 | 26 | // Define all the backup steps that will be used by the backup_assignment_activity_task. 27 | // This is the Complete assignment structure for backup, with file and id annotations. 28 | 29 | require_once($CFG->dirroot."/mod/turnitintooltwo/lib.php"); 30 | 31 | class backup_turnitintooltwo_activity_structure_step extends backup_activity_structure_step { 32 | 33 | protected function define_structure() { 34 | // Required otherwise Moodle unit test core_calendar_container_testcase calendar/tests/container_test.php will fail. 35 | if (defined('PHPUNIT_TEST') && PHPUNIT_TEST) { 36 | set_config('accountid', 'NULL', 'turnitintooltwo'); 37 | } 38 | 39 | $config = turnitintooltwo_admin_config(); 40 | 41 | // To know if we are including userinfo. 42 | $userinfo = $this->get_setting_value('userinfo'); 43 | 44 | // Define each element separated. 45 | $turnitintooltwo = new backup_nested_element('turnitintooltwo', array('id'), array( 46 | 'type', 'name', 'grade', 'numparts', 'tiiaccount', 'defaultdtstart', 'defaultdtdue', 'defaultdtpost', 47 | 'anon', 'portfolio', 'allowlate', 'reportgenspeed', 'submitpapersto', 'spapercheck', 'internetcheck', 48 | 'journalcheck', 'institution_check', 'maxfilesize', 'intro', 'introformat', 'timecreated', 'timemodified', 49 | 'studentreports', 'dateformat', 'usegrademark', 'gradedisplay', 'autoupdates', 'commentedittime', 'commentmaxsize', 50 | 'autosubmission', 'shownonsubmission', 'excludebiblio', 'excludequoted', 'excludevalue', 'excludetype', 51 | 'transmatch', 'rubric', 'allownonor' 52 | )); 53 | 54 | $parts = new backup_nested_element('parts'); 55 | 56 | $part = new backup_nested_element('part', array('id'), array( 57 | 'turnitintooltwoid', 'partname', 'tiiassignid', 'dtstart', 'dtdue', 58 | 'dtpost', 'maxmarks', 'deleted', 'migrated')); 59 | 60 | $courses = new backup_nested_element('courses'); 61 | 62 | $course = new backup_nested_element('course', array('id'), array( 63 | 'courseid', 'ownerid', 'ownertiiuid', 'owneremail', 'ownerfn', 64 | 'ownerln', 'ownerun', 'turnitin_ctl', 'turnitin_cid', 'course_type')); 65 | 66 | $submissions = new backup_nested_element('submissions'); 67 | 68 | $submission = new backup_nested_element('submission', array('id'), array( 69 | 'userid', 'submission_part', 'submission_title', 'submission_type', 'submission_filename', 70 | 'submission_objectid', 'submission_score', 'submission_grade', 'submission_gmimaged', 'submission_attempts', 71 | 'submission_modified', 'submission_parent', 'submission_nmuserid', 'submission_nmfirstname', 72 | 'submission_nmlastname', 'submission_unanon', 'submission_anonreason', 'submission_transmatch', 73 | 'submission_orcapable', 'submission_acceptnothing', 'tiiuserid')); 74 | 75 | // Build the tree. 76 | $submissions->add_child($submission); 77 | $parts->add_child($part); 78 | $turnitintooltwo->add_child($parts); 79 | $turnitintooltwo->add_child($course); 80 | $turnitintooltwo->add_child($submissions); 81 | 82 | // Define sources. 83 | $turnitintooltwo->set_source_table('turnitintooltwo', array('id' => backup::VAR_ACTIVITYID)); 84 | $values['tiiaccount'] = $config->accountid; 85 | $turnitintooltwo->fill_values($values); 86 | 87 | $part->set_source_table('turnitintooltwo_parts', array('turnitintooltwoid' => backup::VAR_ACTIVITYID), 'id'); 88 | 89 | $course->set_source_sql(" 90 | SELECT t.id, t.courseid, t.ownerid, tu.turnitin_uid AS ownertiiuid, 91 | u.email AS owneremail, u.firstname AS ownerfn, u.lastname AS ownerln, 92 | u.username AS ownerun, t.turnitin_ctl, t.turnitin_cid 93 | FROM {turnitintooltwo_courses} t, {user} u, {turnitintooltwo_users} tu 94 | WHERE t.ownerid=u.id AND tu.userid=t.ownerid AND t.courseid = ? AND t.course_type = 'TT'", 95 | array(backup::VAR_COURSEID)); 96 | 97 | // All the rest of elements only happen if we are including user info. 98 | if ($userinfo) { 99 | $submission->set_source_sql(' 100 | SELECT s.*, tu.turnitin_uid AS tiiuserid 101 | FROM {turnitintooltwo_submissions} s, {turnitintooltwo_users} tu 102 | WHERE s.userid=tu.userid AND s.turnitintooltwoid = ?', 103 | array(backup::VAR_ACTIVITYID)); 104 | } 105 | 106 | // Define id annotations. 107 | $submission->annotate_ids('user', 'userid'); 108 | 109 | // Define file annotations. 110 | $turnitintooltwo->annotate_files('mod_turnitintooltwo', 'intro', null); // This file area hasn't itemid. 111 | $submission->annotate_files('mod_turnitintooltwo', 'submissions', 'id'); 112 | 113 | // Return the root element (turnitintooltwo), wrapped into standard activity structure. 114 | return $this->prepare_activity_structure($turnitintooltwo); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /backup/moodle2/restore_turnitintooltwo_activity_task.class.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * @package moodlecore 19 | * @subpackage backup-moodle2 20 | * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} 21 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 22 | */ 23 | 24 | defined('MOODLE_INTERNAL') || die(); 25 | 26 | require_once($CFG->dirroot . '/mod/turnitintooltwo/backup/moodle2/restore_turnitintooltwo_stepslib.php'); 27 | 28 | /** 29 | * Choice restore task that provides all the settings and steps to perform one 30 | * complete restore of the activity. 31 | */ 32 | class restore_turnitintooltwo_activity_task extends restore_activity_task { 33 | 34 | /** 35 | * Define (add) particular settings this activity can have. 36 | */ 37 | protected function define_my_settings() { 38 | // No particular settings for this activity. 39 | } 40 | 41 | /** 42 | * Define (add) particular steps this activity can have. 43 | */ 44 | protected function define_my_steps() { 45 | // Choice only has one structure step. 46 | $this->add_step(new restore_turnitintooltwo_activity_structure_step('turnitintooltwo_structure', 'turnitintooltwo.xml')); 47 | } 48 | 49 | /** 50 | * Define the contents in the activity that must be 51 | * processed by the link decoder 52 | */ 53 | static public function define_decode_contents() { 54 | $contents = array(); 55 | 56 | $contents[] = new restore_decode_content('turnitintooltwo', array('intro'), 'turnitintooltwo'); 57 | 58 | return $contents; 59 | } 60 | 61 | /** 62 | * Define the decoding rules for links belonging 63 | * to the activity to be executed by the link decoder 64 | */ 65 | static public function define_decode_rules() { 66 | $rules = array(); 67 | 68 | $rules[] = new restore_decode_rule('TURNITINTOOLTWOVIEWBYID', '/mod/turnitintooltwo/view.php?id=$1', 'course_module'); 69 | $rules[] = new restore_decode_rule('TURNITINTOOLTWOINDEX', '/mod/turnitintooltwo/index.php?id=$1', 'course'); 70 | 71 | return $rules; 72 | } 73 | 74 | /** 75 | * If no user data was restored after everything has been restored then 76 | * create a new course in Turnitin. 77 | */ 78 | public function after_restore() { 79 | global $DB, $CFG; 80 | 81 | if (!empty($_SESSION['tii_course_reset'])) { 82 | 83 | $course = turnitintooltwo_assignment::get_course_data($_SESSION['course_id']); 84 | 85 | // Get the main site admin. 86 | $admins = explode(",", $CFG->siteadmins); 87 | $ownerid = $admins[0]; 88 | 89 | // Get the number of assignments that already exist on this course that aren't part of recreation. 90 | $assignments = 0; 91 | if (!empty($_SESSION['assignments_to_create'])) { 92 | $modules = $_SESSION['assignments_to_create']; 93 | list($notinsql, $notinparams) = $DB->get_in_or_equal($modules, SQL_PARAMS_QM, 'param', false); 94 | $assignments = $DB->count_records_select('turnitintooltwo', " course = ? AND id ". 95 | $notinsql, array_merge(array($_SESSION['course_id']), $notinparams)); 96 | } 97 | 98 | // Only recreate course on Turnitin if Turnitin Assignments don't exist on destination course. 99 | if ($assignments == 0) { 100 | // Remove Turnitin link from course. 101 | $turnitincourse = new stdClass(); 102 | $turnitincourse->id = $course->tii_rel_id; 103 | $turnitincourse->turnitin_cid = 0; 104 | $DB->update_record('turnitintooltwo_courses', $turnitincourse); 105 | 106 | // Recreate course in Turnitin. 107 | $course->turnitin_cid = 0; 108 | $tmpassignment = new turnitintooltwo_assignment(0, '', ''); 109 | $turnitincourse = $tmpassignment->create_tii_course($course, $ownerid); 110 | 111 | // Join the course as Instructor. 112 | $owner = new turnitintooltwo_user($ownerid, 'Instructor'); 113 | $owner->join_user_to_class($turnitincourse->turnitin_cid); 114 | } 115 | 116 | unset($_SESSION['tii_course_reset']); 117 | unset($_SESSION['course_id']); 118 | } 119 | 120 | if (!empty($_SESSION['assignments_to_create'])) { 121 | foreach ($_SESSION["assignments_to_create"] as $newassignmentid) { 122 | $assignment = new turnitintooltwo_assignment($newassignmentid); 123 | $assignment->unlink_assignment(); 124 | $assignment->edit_moodle_assignment(true, true); 125 | } 126 | unset($_SESSION['tii_assignment_reset']); 127 | unset($_SESSION['assignments_to_create']); 128 | } 129 | 130 | } 131 | 132 | /** 133 | * Define the restore log rules that will be applied by the {@link restore_logs_processor} 134 | * when restoring {@link restore_log_rule} objects. 135 | */ 136 | static public function define_restore_log_rules() { 137 | $rules = array(); 138 | 139 | $rules[] = new restore_log_rule('turnitintooltwo', 'view', 'view.php?id={course_module}', '{turnitintooltwo}'); 140 | $rules[] = new restore_log_rule('turnitintooltwo', 'add', 'view.php?id={course_module}', '{turnitintooltwo}'); 141 | $rules[] = new restore_log_rule('turnitintooltwo', 'update', 'view.php?id={course_module}', '{turnitintooltwo}'); 142 | $rules[] = new restore_log_rule('turnitintooltwo', 'delete', 'view.php?id={course_module}', '{turnitintooltwo}'); 143 | $rules[] = new restore_log_rule('turnitintooltwo', 'submit', 'view.php?id={course_module}', '{turnitintooltwo}'); 144 | 145 | return $rules; 146 | } 147 | 148 | /** 149 | * Define the restore log rules that will be applied by the {@link restore_logs_processor} 150 | * when restoring {@link restore_log_rule} objects. 151 | */ 152 | static public function define_restore_log_rules_for_course() { 153 | $rules = array(); 154 | return $rules; 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /classes/digitalreceipt/instructor_message.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | defined('MOODLE_INTERNAL') || die(); 18 | 19 | class instructor_message { 20 | 21 | /** 22 | * Build a modified receipt to send to instructors upon a submission being made. 23 | * This message must preserve the anonymity of a submission. 24 | * 25 | * @param array $input - used to build message 26 | * @return string 27 | */ 28 | public function build_instructor_message($input) { 29 | $message = new stdClass(); 30 | $message->submission_title = $input['submission_title']; 31 | $message->assignment_name = $input['assignment_name']; 32 | if ( isset($input['assignment_part']) ) { 33 | $message->assignment_part = ": " . $input['assignment_part']; 34 | } else { 35 | $message->assignment_part = ""; 36 | } 37 | $message->course_fullname = $input['course_fullname']; 38 | $message->submission_date = $input['submission_date']; 39 | $message->submission_id = $input['submission_id']; 40 | 41 | return format_string(get_string('receipt_instructor_copy', 'turnitintooltwo', $message)); 42 | } 43 | 44 | /** 45 | * Send instructor message to instructors on course. 46 | * 47 | * @param array $instructors 48 | * @param string $message 49 | * @return void 50 | */ 51 | public function send_instructor_message($instructors, $message, $courseid) { 52 | global $CFG; 53 | 54 | $subject = get_string('receipt_instructor_copy_subject', 'turnitintooltwo'); 55 | 56 | $eventdata = new \core\message\message(); 57 | 58 | $eventdata->component = 'mod_turnitintooltwo'; 59 | $eventdata->name = 'notify_instructor_of_submission'; // This is the message name from messages.php. 60 | $eventdata->userfrom = \core_user::get_noreply_user(); 61 | $eventdata->subject = $subject; 62 | $eventdata->fullmessage = $message; 63 | $eventdata->fullmessageformat = FORMAT_HTML; 64 | $eventdata->fullmessagehtml = $message; 65 | $eventdata->smallmessage = ''; 66 | $eventdata->notification = 1; // This is only set to 0 for personal messages between users. 67 | 68 | if ($CFG->branch >= 32) { 69 | $eventdata->courseid = $courseid; 70 | } 71 | 72 | foreach ($instructors as $instructor) { 73 | 74 | $eventdata->userto = $instructor->id; 75 | message_send($eventdata); 76 | } 77 | unset($instructor); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /classes/digitalreceipt/receipt_message.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | defined('MOODLE_INTERNAL') || die(); 18 | 19 | class receipt_message { 20 | 21 | /** 22 | * Send digital receipt to submitter 23 | * 24 | * @param string $message 25 | * @return void 26 | */ 27 | public function send_message($userid, $message, $courseid) { 28 | global $CFG; 29 | 30 | $subject = get_string('digital_receipt_subject', 'turnitintooltwo'); 31 | 32 | $eventdata = new \core\message\message(); 33 | 34 | $eventdata->component = 'mod_turnitintooltwo'; 35 | $eventdata->name = 'submission'; // This is the message name from messages.php. 36 | $eventdata->userfrom = \core_user::get_noreply_user(); 37 | $eventdata->userto = $userid; 38 | $eventdata->subject = $subject; 39 | $eventdata->fullmessage = $message; 40 | $eventdata->fullmessageformat = FORMAT_HTML; 41 | $eventdata->fullmessagehtml = $message; 42 | $eventdata->smallmessage = ''; 43 | $eventdata->notification = 1; // This is only set to 0 for personal messages between users. 44 | 45 | if ($CFG->branch >= 32) { 46 | $eventdata->courseid = $courseid; 47 | } 48 | 49 | message_send($eventdata); 50 | } 51 | 52 | /** 53 | * Build message to send to user 54 | * 55 | * @param array $input - used to build message 56 | * @return string 57 | */ 58 | public function build_message($input) { 59 | $message = new stdClass(); 60 | $message->firstname = $input['firstname']; 61 | $message->lastname = $input['lastname']; 62 | $message->submission_title = $input['submission_title']; 63 | $message->assignment_name = $input['assignment_name']; 64 | if ( isset($input['assignment_part']) ) { 65 | $message->assignment_part = ": " . $input['assignment_part']; 66 | } else { 67 | $message->assignment_part = ""; 68 | } 69 | $message->course_fullname = $input['course_fullname']; 70 | $message->submission_date = $input['submission_date']; 71 | $message->submission_id = $input['submission_id']; 72 | 73 | return format_string(get_string('digital_receipt_message', 'turnitintooltwo', $message)); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /classes/event/add_submission.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * @package turnitintooltwo 19 | * @copyright 2012 iParadigms LLC * 20 | */ 21 | namespace mod_turnitintooltwo\event; 22 | 23 | /* 24 | * Log event when paper is submitted either by student or instructor on behalf of student. 25 | */ 26 | 27 | defined('MOODLE_INTERNAL') || die(); 28 | 29 | class add_submission extends \core\event\base { 30 | protected function init() { 31 | $this->data['crud'] = 'c'; 32 | $this->data['level'] = self::LEVEL_PARTICIPATING; // For 2.6, this appears to have been renamed to 'edulevel' in 2.7. 33 | $this->data['edulevel'] = self::LEVEL_PARTICIPATING; 34 | $this->data['objecttable'] = 'turnitintooltwo'; 35 | } 36 | 37 | public static function get_name() { 38 | return get_string('addsubmission', 'mod_turnitintooltwo'); 39 | } 40 | 41 | public function get_description() { 42 | return $this->other['desc']; 43 | } 44 | 45 | public function get_url() { 46 | return new \moodle_url('/mod/turnitintooltwo/view.php', array( 'id' => $this->objectid)); 47 | } 48 | 49 | /** 50 | * Custom validation. 51 | * 52 | * @throws \coding_exception 53 | * @return void 54 | */ 55 | protected function validate_data() { 56 | parent::validate_data(); 57 | if (!isset($this->other['desc'])) { 58 | throw new \coding_exception('The \'desc\' value must be set in other.'); 59 | } 60 | 61 | if ($this->contextlevel != CONTEXT_MODULE) { 62 | throw new \coding_exception('Context level must be CONTEXT_MODULE.'); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /classes/event/delete_submission.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace mod_turnitintooltwo\event; 18 | 19 | /* 20 | * Log event when submission is deleted 21 | */ 22 | 23 | defined('MOODLE_INTERNAL') || die(); 24 | 25 | class delete_submission extends \core\event\base { 26 | protected function init() { 27 | $this->data['crud'] = 'd'; 28 | $this->data['level'] = self::LEVEL_PARTICIPATING; // For 2.6, this appears to have been renamed to 'edulevel' in 2.7. 29 | $this->data['edulevel'] = self::LEVEL_PARTICIPATING; 30 | $this->data['objecttable'] = 'turnitintooltwo'; 31 | } 32 | 33 | public static function get_name() { 34 | return get_string('deletesubmission', 'mod_turnitintooltwo'); 35 | } 36 | 37 | public function get_description() { 38 | return $this->other['desc']; 39 | } 40 | 41 | public function get_url() { 42 | return new \moodle_url('/mod/turnitintooltwo/view.php', array( 'id' => $this->objectid)); 43 | } 44 | 45 | /** 46 | * Custom validation. 47 | * 48 | * @throws \coding_exception 49 | * @return void 50 | */ 51 | protected function validate_data() { 52 | parent::validate_data(); 53 | if (!isset($this->other['desc'])) { 54 | throw new \coding_exception('The \'desc\' value must be set in other.'); 55 | } 56 | 57 | if ($this->contextlevel != CONTEXT_MODULE) { 58 | throw new \coding_exception('Context level must be CONTEXT_MODULE.'); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /classes/event/list_submissions.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace mod_turnitintooltwo\event; 18 | 19 | /* 20 | * Log event when 21 | */ 22 | 23 | defined('MOODLE_INTERNAL') || die(); 24 | 25 | class list_submissions extends \core\event\base { 26 | protected function init() { 27 | $this->data['crud'] = 'r'; 28 | $this->data['level'] = self::LEVEL_PARTICIPATING; // For 2.6, this appears to have been renamed to 'edulevel' in 2.7. 29 | $this->data['edulevel'] = self::LEVEL_PARTICIPATING; 30 | $this->data['objecttable'] = 'turnitintooltwo'; 31 | } 32 | 33 | public static function get_name() { 34 | return get_string('listsubmissions', 'mod_turnitintooltwo'); 35 | } 36 | 37 | public function get_description() { 38 | return $this->other['desc']; 39 | } 40 | 41 | public function get_url() { 42 | return new \moodle_url('/mod/turnitintooltwo/view.php', array( 'id' => $this->objectid)); 43 | } 44 | 45 | /** 46 | * Custom validation. 47 | * 48 | * @throws \coding_exception 49 | * @return void 50 | */ 51 | protected function validate_data() { 52 | parent::validate_data(); 53 | if (!isset($this->other['desc'])) { 54 | throw new \coding_exception('The \'desc\' value must be set in other.'); 55 | } 56 | 57 | if ($this->contextlevel != CONTEXT_MODULE) { 58 | throw new \coding_exception('Context level must be CONTEXT_MODULE.'); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /classes/event/migrate_assignment.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * @package turnitintooltwo 19 | * @copyright 2012 iParadigms LLC * 20 | */ 21 | namespace mod_turnitintooltwo\event; 22 | 23 | /* 24 | * Log event when paper is submitted either by student or instructor on behalf of student. 25 | */ 26 | 27 | defined('MOODLE_INTERNAL') || die(); 28 | 29 | class migrate_assignment extends \core\event\base { 30 | protected function init() { 31 | $this->data['crud'] = 'c'; 32 | $this->data['level'] = self::LEVEL_PARTICIPATING; // For 2.6, this appears to have been renamed to 'edulevel' in 2.7. 33 | $this->data['edulevel'] = self::LEVEL_PARTICIPATING; 34 | $this->data['objecttable'] = 'turnitintooltwo'; 35 | } 36 | 37 | public static function get_name() { 38 | return get_string('migration_event_name', 'turnitintooltwo'); 39 | } 40 | 41 | public function get_description() { 42 | return $this->other['desc']; 43 | } 44 | 45 | public function get_url() { 46 | return new \moodle_url('/mod/turnitintooltwo/view.php', array( 'id' => $this->objectid)); 47 | } 48 | 49 | /** 50 | * Custom validation. 51 | * 52 | * @throws \coding_exception 53 | * @return void 54 | */ 55 | protected function validate_data() { 56 | parent::validate_data(); 57 | if (!isset($this->other['desc'])) { 58 | throw new \coding_exception('The \'desc\' value must be set in other.'); 59 | } 60 | 61 | if ($this->contextlevel != CONTEXT_MODULE) { 62 | throw new \coding_exception('Context level must be CONTEXT_MODULE.'); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /classes/event/view_submission.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace mod_turnitintooltwo\event; 18 | 19 | defined('MOODLE_INTERNAL') || die(); 20 | 21 | class view_submission extends \core\event\base { 22 | protected function init() { 23 | $this->data['crud'] = 'r'; 24 | $this->data['level'] = self::LEVEL_PARTICIPATING; // For 2.6, this appears to have been renamed to 'edulevel' in 2.7. 25 | $this->data['edulevel'] = self::LEVEL_PARTICIPATING; 26 | $this->data['objecttable'] = 'turnitintooltwo'; 27 | } 28 | 29 | public static function get_name() { 30 | return get_string('viewsubmission', 'mod_turnitintooltwo'); 31 | } 32 | 33 | public function get_description() { 34 | return $this->other['desc']; 35 | } 36 | 37 | public function get_url() { 38 | return new \moodle_url('/mod/turnitintooltwo/view.php', array( 'id' => $this->objectid)); 39 | } 40 | 41 | /** 42 | * Custom validation. 43 | * 44 | * @throws \coding_exception 45 | * @return void 46 | */ 47 | protected function validate_data() { 48 | parent::validate_data(); 49 | if (!isset($this->other['desc'])) { 50 | throw new \coding_exception('The \'desc\' value must be set in other.'); 51 | } 52 | 53 | if ($this->contextlevel != CONTEXT_MODULE) { 54 | throw new \coding_exception('Context level must be CONTEXT_MODULE.'); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /classes/nonsubmitters/nonsubmitters_message.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | defined('MOODLE_INTERNAL') || die(); 18 | 19 | class nonsubmitters_message { 20 | 21 | /** 22 | * Send non-submitters message to students. 23 | * 24 | * @param string $message 25 | * @return void 26 | */ 27 | public function send_message($userid, $subject, $message, $courseid) { 28 | global $CFG; 29 | 30 | $eventdata = new \core\message\message(); 31 | $eventdata->component = 'mod_turnitintooltwo'; 32 | $eventdata->name = 'nonsubmitters'; // This is the message name from messages.php. 33 | $eventdata->userfrom = \core_user::get_noreply_user(); 34 | $eventdata->userto = $userid; 35 | $eventdata->subject = $subject; 36 | $eventdata->fullmessage = $message; 37 | $eventdata->fullmessageformat = FORMAT_HTML; 38 | $eventdata->fullmessagehtml = $message; 39 | $eventdata->smallmessage = ''; 40 | $eventdata->notification = 1; // This is only set to 0 for personal messages between users. 41 | 42 | if ($CFG->branch >= 32) { 43 | $eventdata->courseid = $courseid; 44 | } 45 | 46 | message_send($eventdata); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /classes/task/turnitintooltwo_task.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace mod_turnitintooltwo\task; 18 | 19 | defined('MOODLE_INTERNAL') || die(); 20 | 21 | /** 22 | * Library function for turnitintooltwo task function. 23 | */ 24 | 25 | class turnitintooltwo_task extends \core\task\scheduled_task { 26 | 27 | public function get_name() { 28 | // Shown in admin screens. 29 | return get_string('task_name', 'mod_turnitintooltwo'); 30 | } 31 | 32 | /** 33 | * Do the job. 34 | * Throw exceptions on errors (the job will be retried). 35 | */ 36 | public function execute() { 37 | global $CFG, $tiitaskcall; 38 | 39 | // Run turnitintooltwo cron. 40 | require_once("{$CFG->dirroot}/mod/turnitintooltwo/lib.php"); 41 | $tiitaskcall = true; 42 | turnitintooltwo_cron(); 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /classes/view/members.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | defined('MOODLE_INTERNAL') || die(); 18 | 19 | /** 20 | * Members view class deals with generating the HTM for the members table. It 21 | * can generate members table for either tutors or students in a course by 22 | * calling the "build_members_view" method. Defaults to rendering the students 23 | * members table if no display role is given. 24 | */ 25 | class members_view { 26 | public $course; 27 | public $coursemodule; 28 | public $turnitintooltwoassignment; 29 | public $turnitintooltwoview; 30 | 31 | public function __construct($course=null, $coursemodule=null, $turnitintooltwoview=null, $turnitintooltwoassignment=null) { 32 | $this->course = $course; 33 | $this->coursemodule = $coursemodule; 34 | $this->turnitintooltwoview = $turnitintooltwoview; 35 | $this->turnitintooltwoassignment = $turnitintooltwoassignment; 36 | } 37 | 38 | /** 39 | * Method that generates the members view HTML. Depending on the displayrole 40 | * passed will generate the HTML for the users with that role. 41 | * @return string Members HTML for a role 42 | */ 43 | public function build_members_view($displayrole = "students") { 44 | $istutor = $this->is_tutor(); 45 | 46 | if (!$istutor) { 47 | turnitintooltwo_print_error('permissiondeniederror', 'turnitintooltwo'); 48 | exit(); 49 | } 50 | 51 | $wrapperclass = $displayrole == "tutors" ? "members-instructors" : "members-students"; 52 | 53 | // Wrapper element for strong CSS selectors. 54 | $output = html_writer::start_tag("div", array("class" => "mod_turnitintooltwo_members " . $wrapperclass)); 55 | 56 | $output .= $this->build_intro_message($displayrole); 57 | $output .= $this->build_members_table($displayrole); 58 | $output .= $this->build_add_tutors_form($displayrole); 59 | 60 | $output .= html_writer::end_tag("div"); 61 | 62 | return $output; 63 | } 64 | 65 | /** 66 | * Util method to check if the current user is an instructor by checking if 67 | * they can grade. 68 | * @return boolean Bool if the current user is an instructor 69 | */ 70 | public function is_tutor () { 71 | return has_capability('mod/turnitintooltwo:grade', context_module::instance($this->coursemodule->id)); 72 | } 73 | 74 | /** 75 | * Returns the Turnitin role for the display role passed in the query param 76 | * "do" (tutors or students) to view.php. 77 | * @param string $displayrole The do action passed to view.php when 78 | * displaying members 79 | * @return string Turnitin role that maps to the display role 80 | */ 81 | public function get_role_for_display_role ($displayrole) { 82 | return $displayrole == "tutors" ? 'Instructor' : 'Learner'; 83 | } 84 | 85 | /** 86 | * Generates HTM for the message that is displayed above the members table. 87 | * This differs depending on if we're showing the student members or 88 | * instructor members. 89 | * @param string $displayrole Role of the members we want to display for 90 | * @return string HTML message to display before the members 91 | * table 92 | */ 93 | public function build_intro_message ($displayrole = "students") { 94 | global $OUTPUT; 95 | 96 | if ($displayrole == "tutors") { 97 | $introtextkey = 'turnitintutors_desc'; 98 | } else { 99 | $introtextkey = 'turnitinstudents_desc'; 100 | } 101 | 102 | $introtext = get_string($introtextkey, 'turnitintooltwo'); 103 | 104 | return $OUTPUT->box($introtext, 'message message-members-intro'); 105 | } 106 | 107 | /** 108 | * Generates the HTML for the members table given a role will generate for 109 | * either the course students or instructors. 110 | * @param string $role Members with this role to display 111 | * @return string HTML of the members table 112 | */ 113 | public function build_members_table ($displayrole="students") { 114 | $turnitintooltwoassignment = $this->turnitintooltwoassignment; 115 | $turnitintooltwoview = $this->turnitintooltwoview; 116 | $coursemodule = $this->coursemodule; 117 | $role = $this->get_role_for_display_role($displayrole); 118 | 119 | return $turnitintooltwoview->init_tii_member_by_role_table($coursemodule, $turnitintooltwoassignment, $role); 120 | } 121 | 122 | /** 123 | * Generates the HTML for the add tutors form that is displayed under the 124 | * members table. Only generates the form for the display role "tutors" 125 | * otherwise will return an empty string (i.e. display nothing). 126 | * @param string $displayrole Which members table is being shown 127 | * @return string HTML for add tutors form to display 128 | */ 129 | public function build_add_tutors_form ($displayrole) { 130 | // early escape only show the add tutors in the tutors members list 131 | if ($displayrole != "tutors") { 132 | return ""; 133 | } 134 | 135 | $tutors = $this->turnitintooltwoassignment->get_tii_users_by_role("Instructor", "mdl"); 136 | return $this->turnitintooltwoview->show_add_tii_tutors_form($this->coursemodule, $tutors); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /css/colorbox.css: -------------------------------------------------------------------------------- 1 | /* 2 | ColorBox Core Style: 3 | The following CSS is consistent between example themes and should not be altered. 4 | */ 5 | #colorbox, #cboxOverlay, #cboxWrapper{position:absolute; top:0; left:0; z-index:9999; overflow:hidden;} 6 | #cboxOverlay{position:fixed; width:100%; height:100%;} 7 | #cboxMiddleLeft, #cboxBottomLeft{clear:left;} 8 | #cboxContent{position:relative;} 9 | #cboxLoadedContent{overflow:auto;} 10 | #cboxTitle{margin:0;} 11 | #cboxLoadingOverlay, #cboxLoadingGraphic{position:absolute; top:0; left:0; width:100%; height:100%;} 12 | #cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{cursor:pointer;} 13 | .cboxPhoto{float:left; margin:auto; border:0; display:block; max-width:none;} 14 | .cboxIframe{width:100%; height:100%; display:block; border:0;} 15 | #colorbox, #cboxContent, #cboxLoadedContent{box-sizing:content-box; -moz-box-sizing:content-box; -webkit-box-sizing:content-box;} 16 | 17 | /* 18 | User Style: 19 | Change the following styles to modify the appearance of ColorBox. They are 20 | ordered & tabbed in a way that represents the nesting of the generated HTML. 21 | */ 22 | #cboxOverlay{background:#000;} 23 | #colorbox{} 24 | #cboxContent{margin-top:32px; overflow:visible;} 25 | .cboxIframe{background:none;}/*#FFF*/ 26 | #cboxError{padding:50px; border:1px solid #ccc;} 27 | #cboxLoadedContent{background:none; padding:1px;} 28 | #cboxLoadingGraphic{background:url(../pix/colorbox/loading.gif) no-repeat center center;} 29 | #cboxLoadingOverlay{background:none;} 30 | #cboxTitle{position:absolute; top:-22px; left:0; color:#000; display:none !important;} 31 | #cboxCurrent{position:absolute; top:-22px; right:205px; text-indent:-9999px;} 32 | #cboxClose{text-indent:-9999px; width:20px; height:20px; position:absolute; top:-20px; background:url(../pix/colorbox/controls.png) no-repeat 0 0;} 33 | #cboxClose{background-position:-50px 0px; right:0;} 34 | #cboxClose:hover{background-position:-50px -25px;} 35 | 36 | 37 | iframe html{background:none;} 38 | 39 | /* Messages Inbox, Migration, Upload, Rubric and Quickmark boxes */ 40 | .messages #cboxLoadedContent, .messages .cboxIframe, .rubric_manager #cboxLoadedContent, .rubric_manager .cboxIframe, .quickmark_manager #cboxLoadedContent, .quickmark_manager .cboxIframe, 41 | .peermark_reviews #cboxLoadedContent, .peermark_reviews .cboxIframe, .peermark_manager #cboxLoadedContent, .peermark_manager .cboxIframe { background:none; } 42 | 43 | .migration #cboxLoadedContent, .migration #cboxIframe, .downloadpdf_window #cboxLoadedContent, .downloadpdf_window .cboxIframe, 44 | .gmpdfzip_window #cboxLoadedContent, .gmpdfzip_window .cboxIframe, .course_creation #cboxLoadedContent, .course_creation #cboxIframe { 45 | background: #FFF; 46 | } 47 | 48 | #cboxClose { text-indent:-36px; display:none; } 49 | 50 | .messages #cboxClose, .tii_unanonymise_reveal_form #cboxClose, .downloadpdf_window #cboxClose, .gmpdfzip_window #cboxClose, .rubric_manager #cboxClose, 51 | .rubric_view #cboxClose, .quickmark_manager #cboxClose, .peermark_manager #cboxClose, .peermark_reviews #cboxClose, .course_creation #cboxClose, 52 | .tii_unanonymise_reveal_form #cboxClose, .tii_unanonymise_reveal_form #cboxClose, .migration #cboxClose { 53 | display:none !important; 54 | } 55 | 56 | .upload #cboxClose { 57 | top: 2px; 58 | } 59 | 60 | .upload #cboxClose .closeText { 61 | position: relative; 62 | top: 2px; 63 | } 64 | 65 | .tii_unanonymise_reveal_form #cboxLoadedContent, .edit_end_date_form #cboxLoadedContent { 66 | height:100%; 67 | overflow: hidden !important; 68 | } 69 | 70 | #cboxOverlay{ 71 | z-index:9997; 72 | } 73 | 74 | .loading_gif { 75 | padding:16px; 76 | margin:0 auto; 77 | position: absolute; 78 | top: 48%; 79 | left: 48%; 80 | background:url(../pix/colorbox/loading.gif) no-repeat center center #000; 81 | height: 32px; 82 | width: 32px; 83 | -moz-border-radius: 12px; 84 | -webkit-border-radius: 12px; 85 | -khtml-border-radius: 12px; 86 | border-radius: 12px; 87 | z-index:9998; 88 | } 89 | 90 | .tii_unanonymise_reveal_form #cboxClose, .edit_end_date_form #cboxClose { 91 | top: 4px; 92 | right:4px; 93 | } 94 | 95 | .edit_end_date_form #cboxLoadedContent .mform .fitem .fitemtitle { 96 | width: 25%; 97 | } 98 | 99 | .edit_end_date_form #cboxLoadedContent .mform .fitem .felement { 100 | width: 70%; 101 | } 102 | 103 | .edit_end_date_form #cboxLoadedContent .mform .fitem fieldset.felement { 104 | margin-left: 25%; 105 | } -------------------------------------------------------------------------------- /css/hide_bg.css: -------------------------------------------------------------------------------- 1 | html { 2 | background:none; 3 | } -------------------------------------------------------------------------------- /css/jqueryui-editable.css: -------------------------------------------------------------------------------- 1 | /*! X-editable - v1.4.3 2 | * In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery 3 | * http://github.com/vitalets/x-editable 4 | * Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */ 5 | 6 | .editableform { 7 | margin-bottom: 0; /* overwrites bootstrap margin */ 8 | } 9 | 10 | .editableform .control-group { 11 | margin-bottom: 0; /* overwrites bootstrap margin */ 12 | white-space: nowrap; /* prevent wrapping buttons on new line */ 13 | line-height: 20px; /* overwriting bootstrap line-height. See #133 */ 14 | } 15 | 16 | .editable-buttons { 17 | display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */ 18 | vertical-align: top; 19 | margin-left: 7px; 20 | /* inline-block emulation for IE7*/ 21 | zoom: 1; 22 | *display: inline; 23 | } 24 | 25 | 26 | 27 | .editable-input { 28 | vertical-align: top; 29 | display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */ 30 | width: auto; /* bootstrap-responsive has width: 100% that breakes layout */ 31 | white-space: normal; /* reset white-space decalred in parent*/ 32 | /* display-inline emulation for IE7*/ 33 | zoom: 1; 34 | *display: inline; 35 | } 36 | 37 | .editable-buttons .editable-cancel { 38 | margin-left: 7px; 39 | } 40 | 41 | /*for jquery-ui buttons need set height to look more pretty*/ 42 | .editable-buttons button.ui-button-icon-only { 43 | height: 24px; 44 | width: 30px; 45 | } 46 | 47 | .editableform-loading { 48 | background: url('../pix/loading.gif') center center no-repeat; 49 | height: 25px; 50 | width: auto; 51 | min-width: 25px; 52 | } 53 | 54 | .editable-inline .editableform-loading { 55 | background-position: center 0px; 56 | } 57 | 58 | .editable-error-block { 59 | max-width: 300px; 60 | margin: 5px 0 0 0; 61 | width: auto; 62 | white-space: normal; 63 | } 64 | 65 | /*add padding for jquery ui*/ 66 | .editable-error-block.ui-state-error { 67 | padding: 3px; 68 | } 69 | 70 | .editable-error { 71 | color: red; 72 | } 73 | 74 | .editableform .editable-date { 75 | padding: 0; 76 | margin: 0; 77 | float: left; 78 | } 79 | 80 | 81 | /* checklist vertical alignment */ 82 | .editable-checklist label input[type="checkbox"], 83 | .editable-checklist label span { 84 | vertical-align: middle; 85 | margin: 0; 86 | } 87 | 88 | .editable-checklist label { 89 | white-space: nowrap; 90 | } 91 | 92 | /* set exact width of textarea to fit buttons toolbar */ 93 | .editable-wysihtml5 { 94 | width: 566px; 95 | height: 250px; 96 | } 97 | 98 | /* clear button shown as link in date inputs */ 99 | .editable-clear { 100 | clear: both; 101 | font-size: 0.9em; 102 | text-decoration: none; 103 | text-align: right; 104 | } 105 | 106 | /* IOS-style clear button for text inputs */ 107 | .editable-clear-x { 108 | background: url('../pix/clear.png') center center no-repeat; 109 | display: block; 110 | width: 13px; 111 | height: 13px; 112 | position: absolute; 113 | opacity: 0.6; 114 | z-index: 100; 115 | 116 | } 117 | 118 | .editable-clear-x:hover { 119 | opacity: 1; 120 | } 121 | .editable-container { 122 | max-width: none !important; /* without this rule poshytip/tooltip does not stretch */ 123 | } 124 | 125 | .editable-container.popover { 126 | /* width: 300px;*/ /* debug */ 127 | width: auto; /* without this rule popover does not stretch */ 128 | } 129 | 130 | .editable-container.editable-inline { 131 | display: inline-block; 132 | vertical-align: middle; 133 | width: auto; 134 | /* inline-block emulation for IE7*/ 135 | zoom: 1; 136 | *display: inline; 137 | } 138 | 139 | .editable-container.ui-widget { 140 | font-size: inherit; /* jqueryui widget font 1.1em too big, overwrite it */ 141 | } 142 | .editable-click, 143 | a.editable-click, 144 | a.editable-click:hover { 145 | text-decoration: none; 146 | border-bottom: dashed 1px #0088cc; 147 | } 148 | 149 | .editable-click.editable-disabled, 150 | a.editable-click.editable-disabled, 151 | a.editable-click.editable-disabled:hover { 152 | color: #585858; 153 | cursor: default; 154 | border-bottom: none; 155 | } 156 | 157 | .editable-empty, .editable-empty:hover{ 158 | font-style: italic; 159 | color: #DD1144; 160 | border-bottom: none; 161 | text-decoration: none; 162 | } 163 | 164 | .editable-unsaved { 165 | font-weight: bold; 166 | } 167 | 168 | .editable-unsaved:after { 169 | /* content: '*'*/ 170 | } 171 | 172 | /*see https://github.com/vitalets/x-editable/issues/139 */ 173 | .form-horizontal .editable 174 | { 175 | padding-top: 5px; 176 | display:inline-block; 177 | } 178 | 179 | -------------------------------------------------------------------------------- /css/student_noscript.css: -------------------------------------------------------------------------------- 1 | .mod_turnitintooltwo_submissions_data_table { 2 | margin-top:16px; 3 | } 4 | 5 | .mod_turnitintooltwo_submissions_data_table th { 6 | border:1px solid #999999; 7 | } 8 | 9 | .mod_turnitintooltwo_submissions_data_table td { 10 | border:1px solid #999999; 11 | } 12 | 13 | .mod_turnitintooltwo #tabs ul#part_tabs_menu, .mod_turnitintooltwo a.toggle_summary, .mod_turnitintooltwo a.toggle_peermarks, 14 | .mod_turnitintooltwo a.toggle_peermark_instructions, .mod_turnitintooltwo .mod_turnitintooltwo_eula, .mod_turnitintooltwo_messages_inbox, 15 | .mod_turnitintooltwo .noscript_hide, .mod_turnitintooltwo .download_original_open, .mod_turnitintooltwo th.raw_data, 16 | .mod_turnitintooltwo td.raw_data, .mod_turnitintooltwo_submissions_data_table th.cpart, 17 | .mod_turnitintooltwo_submissions_data_table th.ccheckbox, .mod_turnitintooltwo_submissions_data_table td.c0, 18 | .mod_turnitintooltwo_submissions_data_table td.c1 { 19 | display:none; 20 | } 21 | 22 | .mod_turnitintooltwo .peermark_instructions { 23 | display: block; 24 | } 25 | 26 | .mod_turnitintooltwo .part_table { 27 | background:#EFEFEF; 28 | border:1px solid #DEDEDE; 29 | padding:10px; 30 | } -------------------------------------------------------------------------------- /css/styles_block.css: -------------------------------------------------------------------------------- 1 | .block_turnitin .centered_cell { 2 | text-align:center; 3 | } 4 | 5 | .block_turnitin #block_loading { 6 | display:none; 7 | } -------------------------------------------------------------------------------- /db/access.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * @package turnitintooltwo 19 | * @copyright 2010 iParadigms LLC 20 | */ 21 | 22 | defined('MOODLE_INTERNAL') || die(); 23 | 24 | $capabilities = array( 25 | 26 | 'mod/turnitintooltwo:view' => array( 27 | 28 | 'captype' => 'read', 29 | 'contextlevel' => CONTEXT_MODULE, 30 | 'legacy' => array( 31 | 'guest' => CAP_ALLOW, 32 | 'student' => CAP_ALLOW, 33 | 'teacher' => CAP_ALLOW, 34 | 'editingteacher' => CAP_ALLOW 35 | ) 36 | ), 37 | 38 | 'mod/turnitintooltwo:read' => array( 39 | 40 | 'captype' => 'read', 41 | 'contextlevel' => CONTEXT_MODULE, 42 | 'legacy' => array( 43 | 'student' => CAP_ALLOW, 44 | 'teacher' => CAP_ALLOW, 45 | 'editingteacher' => CAP_ALLOW 46 | ) 47 | ), 48 | 49 | 'mod/turnitintooltwo:submit' => array( 50 | 51 | 'captype' => 'write', 52 | 'contextlevel' => CONTEXT_MODULE, 53 | 'legacy' => array( 54 | 'student' => CAP_ALLOW 55 | ) 56 | ), 57 | 58 | 'mod/turnitintooltwo:grade' => array( 59 | 60 | 'captype' => 'write', 61 | 'contextlevel' => CONTEXT_MODULE, 62 | 'legacy' => array( 63 | 'teacher' => CAP_ALLOW, 64 | 'editingteacher' => CAP_ALLOW 65 | ) 66 | ), 67 | 68 | 'mod/turnitintooltwo:addinstance' => array( 69 | 'riskbitmask' => RISK_XSS, 70 | 'captype' => 'write', 71 | 'contextlevel' => CONTEXT_MODULE, 72 | 73 | 'legacy' => array( 74 | 'teacher' => CAP_ALLOW, 75 | 'editingteacher' => CAP_ALLOW 76 | ), 77 | 'clonepermissionsfrom' => 'moodle/course:manageactivities' 78 | ) 79 | ); -------------------------------------------------------------------------------- /db/install.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * @package turnitintooltwo 19 | * @copyright 2019 iParadigms LLC 20 | */ 21 | 22 | defined('MOODLE_INTERNAL') || die(); 23 | 24 | /** 25 | * This method is called by Moodle after parsing install.xml upon installation of the plugin. It is only ran once. 26 | */ 27 | function xmldb_turnitintooltwo_install() { 28 | 29 | if (v1installed()) { 30 | copyStudentPrivacySettings(); 31 | } 32 | } 33 | 34 | /** 35 | * Check whether v1 is installed. 36 | */ 37 | function v1installed() { 38 | global $DB; 39 | 40 | $module = $DB->get_record('config_plugins', array('plugin' => 'mod_turnitintool')); 41 | return boolval($module); 42 | } 43 | 44 | /** 45 | * If a Moodle administrator wants to use Moodle Direct V2 having already been using V1, we should copy across 46 | * the student privacy settings upon installation because they can't be changed once submissions have been made. 47 | * 48 | * @throws dml_exception 49 | */ 50 | function copyStudentPrivacySettings() { 51 | global $DB; 52 | 53 | // We can't use get_config() as the config values from V1 aren't stored in mdl_config_plugins. 54 | $data = $DB->get_records_sql("SELECT name, value FROM {config} WHERE name LIKE 'turnitin_%'"); 55 | 56 | // The student privacy settings we would like to copy across. 57 | $properties = array("enablepseudo", "pseudofirstname", "pseudolastname", "lastnamegen", "pseudosalt", "pseudoemaildomain"); 58 | 59 | // Loop through each setting and set the value in V2. 60 | foreach ($properties as $property) { 61 | if (isset($data["turnitin_".$property])) { 62 | set_config($property, $data["turnitin_".$property]->value, 'turnitintooltwo'); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /db/log.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * @package turnitintooltwo 19 | * @copyright 2010 iParadigms LLC 20 | */ 21 | 22 | defined('MOODLE_INTERNAL') || die(); 23 | 24 | $logs = array( 25 | array('module' => 'turnitintooltwo', 'action' => 'view', 'mtable' => 'turnitintooltwo', 'field' => 'name'), 26 | array('module' => 'turnitintooltwo', 'action' => 'add', 'mtable' => 'turnitintooltwo', 'field' => 'name'), 27 | array('module' => 'turnitintooltwo', 'action' => 'update', 'mtable' => 'turnitintooltwo', 'field' => 'name') 28 | ); -------------------------------------------------------------------------------- /db/messages.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * @package turnitintooltwo 19 | * @copyright 2010 iParadigms LLC 20 | */ 21 | 22 | defined('MOODLE_INTERNAL') || die(); 23 | $messageproviders = array ( 24 | // Notify student with their digital receipt. 25 | 'submission' => array ( 26 | ), 27 | // Notify nonsubmitters for an assignment. 28 | 'nonsubmitters' => array (), 29 | // Notify instructors with their copy of the digital receipt. 30 | 'notify_instructor_of_submission' => array ( 31 | ) 32 | ); -------------------------------------------------------------------------------- /db/tasks.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * @package turnitintooltwo 19 | */ 20 | 21 | defined('MOODLE_INTERNAL') || die(); 22 | 23 | $tasks = array( 24 | array( 25 | 'classname' => 'mod_turnitintooltwo\task\turnitintooltwo_task', 26 | 'blocking' => 0, 27 | 'minute' => '*/5', 28 | 'hour' => '*', 29 | 'day' => '*', 30 | 'dayofweek' => '*', 31 | 'month' => '*' 32 | ) 33 | ); -------------------------------------------------------------------------------- /fonts/tii-icon-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/fonts/tii-icon-webfont.eot -------------------------------------------------------------------------------- /fonts/tii-icon-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/fonts/tii-icon-webfont.ttf -------------------------------------------------------------------------------- /fonts/tii-icon-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/fonts/tii-icon-webfont.woff -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | const sass = require('gulp-sass')(require('sass')); 3 | 4 | var minifyCss = require('gulp-clean-css'); 5 | var sourcemaps = require('gulp-sourcemaps'); 6 | var notify = require('gulp-notify'); 7 | var uglify = require('gulp-uglify'); 8 | var rename = require('gulp-rename'); 9 | 10 | gulp.task('sass', function() { 11 | return gulp.src('./sass/styles.scss') 12 | .pipe(sourcemaps.init()) 13 | .pipe(sass().on('error', sass.logError)) 14 | .pipe(minifyCss()) 15 | .pipe(sourcemaps.write('.')) 16 | .pipe(gulp.dest('.')) 17 | .pipe(notify("CSS Compiled!")); 18 | }); 19 | 20 | gulp.task('jsmin', function() { 21 | return gulp.src(['./jquery/turnitintooltwo*.js', '!./jquery/turnitintooltwo*.min.js']) 22 | .pipe(sourcemaps.init()) 23 | .pipe(uglify().on('error', function(e){ 24 | console.log(e); 25 | })) 26 | .pipe(rename({suffix: '.min'})) 27 | .pipe(sourcemaps.write()) 28 | .pipe(gulp.dest('./jquery/')) 29 | .pipe(notify('js minified')); 30 | }); 31 | 32 | gulp.task('watch', function() { 33 | gulp.watch('./sass/**/*.scss', gulp.series('sass')); 34 | gulp.watch('./jquery/turnitintooltwo*.js', gulp.series('jsmin')); 35 | }); 36 | 37 | gulp.task('default', gulp.series(['sass', 'jsmin', 'watch'])); -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * @package turnitintooltwo 19 | * @copyright 2010 iParadigms LLC 20 | */ 21 | 22 | require_once(__DIR__."/../../config.php"); 23 | require_once(__DIR__."/lib.php"); 24 | require_once(__DIR__."/turnitintooltwo_view.class.php"); 25 | 26 | $turnitintooltwoview = new turnitintooltwo_view(); 27 | 28 | // Load Javascript and CSS. 29 | $turnitintooltwoview->load_page_components(); 30 | 31 | $id = required_param('id', PARAM_INT); // Course id. 32 | 33 | // Configure URL correctly. 34 | $urlparams = array('id' => $id); 35 | $url = new moodle_url('/mod/turnitintooltwo/index.php', $urlparams); 36 | 37 | // Get course data. 38 | if (!$course = $DB->get_record("course", array("id" => $id))) { 39 | turnitintooltwo_print_error('courseiderror', 'turnitintooltwo'); 40 | } 41 | 42 | require_login($course->id); 43 | 44 | // Print the header. 45 | $turnitintooltwoview->output_header($url, get_string("modulenameplural", "turnitintooltwo"), $SITE->fullname); 46 | 47 | echo $turnitintooltwoview->show_assignments($course); 48 | 49 | echo $OUTPUT->footer(); -------------------------------------------------------------------------------- /jquery/colorbox.css: -------------------------------------------------------------------------------- 1 | /* 2 | ColorBox Core Style: 3 | The following CSS is consistent between example themes and should not be altered. 4 | */ 5 | #colorbox, #cboxOverlay, #cboxWrapper{position:absolute; top:0; left:0; z-index:9999; overflow:hidden;} 6 | #cboxOverlay{position:fixed; width:100%; height:100%;} 7 | #cboxMiddleLeft, #cboxBottomLeft{clear:left;} 8 | #cboxContent{position:relative;} 9 | #cboxLoadedContent{overflow:auto;} 10 | #cboxTitle{margin:0;} 11 | #cboxLoadingOverlay, #cboxLoadingGraphic{position:absolute; top:0; left:0; width:100%; height:100%;} 12 | #cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{cursor:pointer;} 13 | .cboxPhoto{float:left; margin:auto; border:0; display:block; max-width:none;} 14 | .cboxIframe{width:100%; height:100%; display:block; border:0;} 15 | #colorbox, #cboxContent, #cboxLoadedContent{box-sizing:content-box; -moz-box-sizing:content-box; -webkit-box-sizing:content-box;} 16 | 17 | /* 18 | User Style: 19 | Change the following styles to modify the appearance of ColorBox. They are 20 | ordered & tabbed in a way that represents the nesting of the generated HTML. 21 | */ 22 | #cboxOverlay{background:#000;} 23 | #colorbox{} 24 | #cboxContent{margin-top:32px; overflow:visible;} 25 | .cboxIframe{background:none;}/*#FFF*/ 26 | #cboxError{padding:50px; border:1px solid #ccc;} 27 | #cboxLoadedContent{background:none; padding:1px;} 28 | #cboxLoadingGraphic{background:url(../../../mod/turnitintooltwo/pix/colorbox/loading.gif) no-repeat center center;} 29 | #cboxLoadingOverlay{background:none;} 30 | #cboxTitle{position:absolute; top:-22px; left:0; color:#000; display:none !important;} 31 | #cboxCurrent{position:absolute; top:-22px; right:205px; text-indent:-9999px;} 32 | #cboxClose{text-indent:-9999px; width:20px; height:20px; position:absolute; top:-20px; background:url(../../../mod/turnitintooltwo/pix/colorbox/controls.png) no-repeat 0 0;} 33 | #cboxClose{background-position:-50px 0px; right:0;} 34 | #cboxClose:hover{background-position:-50px -25px;} 35 | 36 | 37 | iframe html{background:none;} 38 | 39 | /* Messages Inbox, Migration, Upload, Rubric and Quickmark boxes */ 40 | .messages #cboxLoadedContent, .messages .cboxIframe, .rubric_manager #cboxLoadedContent, .rubric_manager .cboxIframe, .quickmark_manager #cboxLoadedContent, .quickmark_manager .cboxIframe, 41 | .peermark_reviews #cboxLoadedContent, .peermark_reviews .cboxIframe, .peermark_manager #cboxLoadedContent, .peermark_manager .cboxIframe { background:none; } 42 | 43 | .migration #cboxLoadedContent, .migration #cboxIframe, .downloadpdf_window #cboxLoadedContent, .downloadpdf_window .cboxIframe, 44 | .gmpdfzip_window #cboxLoadedContent, .gmpdfzip_window .cboxIframe, .course_creation #cboxLoadedContent, .course_creation #cboxIframe { 45 | background: #FFF; 46 | } 47 | 48 | #cboxClose { text-indent:-36px; display:none; } 49 | 50 | .messages #cboxClose, .tii_unanonymise_reveal_form #cboxClose, .downloadpdf_window #cboxClose, .gmpdfzip_window #cboxClose, .rubric_manager #cboxClose, 51 | .rubric_view #cboxClose, .quickmark_manager #cboxClose, .peermark_manager #cboxClose, .peermark_reviews #cboxClose, .course_creation #cboxClose, 52 | .tii_unanonymise_reveal_form #cboxClose, .tii_unanonymise_reveal_form #cboxClose, .migration #cboxClose { 53 | display:none !important; 54 | } 55 | 56 | .upload #cboxClose { 57 | top: 2px; 58 | } 59 | 60 | .upload #cboxClose .closeText { 61 | position: relative; 62 | top: 2px; 63 | } 64 | 65 | .tii_unanonymise_reveal_form #cboxLoadedContent, .edit_end_date_form #cboxLoadedContent { 66 | height:100%; 67 | overflow: hidden !important; 68 | } 69 | 70 | #cboxOverlay{ 71 | z-index:9997; 72 | } 73 | 74 | .loading_gif { 75 | padding:16px; 76 | margin:0 auto; 77 | position: absolute; 78 | top: 48%; 79 | left: 48%; 80 | background:url(../../../mod/turnitintooltwo/pix/colorbox/loading.gif) no-repeat center center #000; 81 | height: 32px; 82 | width: 32px; 83 | -moz-border-radius: 12px; 84 | -webkit-border-radius: 12px; 85 | -khtml-border-radius: 12px; 86 | border-radius: 12px; 87 | z-index:9998; 88 | } 89 | 90 | .unanonymise_reveal_form #cboxClose, .edit_end_date_form #cboxClose { 91 | top: 4px; 92 | right:4px; 93 | } 94 | 95 | .edit_end_date_form #cboxLoadedContent .mform .fitem .fitemtitle { 96 | width: 25%; 97 | } 98 | 99 | .edit_end_date_form #cboxLoadedContent .mform .fitem .felement { 100 | width: 70%; 101 | } 102 | 103 | .edit_end_date_form #cboxLoadedContent .mform .fitem fieldset.felement { 104 | margin-left: 25%; 105 | } -------------------------------------------------------------------------------- /jquery/jquery.cookie.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery Cookie Plugin v1.3.1 3 | * https://github.com/carhartl/jquery-cookie 4 | * 5 | * Copyright 2013 Klaus Hartl 6 | * Released under the MIT license 7 | */ 8 | (function (factory) { 9 | if (typeof define === 'function' && define.amd && define.amd.jQuery) { 10 | // AMD. Register as anonymous module. 11 | define(['jquery'], factory); 12 | } else { 13 | // Browser globals. 14 | factory(jQuery); 15 | } 16 | }(function ($) { 17 | 18 | var pluses = /\+/g; 19 | 20 | function raw(s) { 21 | return s; 22 | } 23 | 24 | function decoded(s) { 25 | return decodeURIComponent(s.replace(pluses, ' ')); 26 | } 27 | 28 | function converted(s) { 29 | if (s.indexOf('"') === 0) { 30 | // This is a quoted cookie as according to RFC2068, unescape. 31 | s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\'); 32 | } 33 | try { 34 | return config.json ? JSON.parse(s) : s; 35 | } catch(er) {} 36 | } 37 | 38 | var config = $.cookie = function (key, value, options) { 39 | 40 | // Write. 41 | if (value !== undefined) { 42 | options = $.extend({}, config.defaults, options); 43 | 44 | if (typeof options.expires === 'number') { 45 | var days = options.expires, t = options.expires = new Date(); 46 | t.setDate(t.getDate() + days); 47 | } 48 | 49 | value = config.json ? JSON.stringify(value) : String(value); 50 | 51 | return (document.cookie = [ 52 | encodeURIComponent(key), '=', config.raw ? value : encodeURIComponent(value), 53 | options.expires ? '; expires=' + options.expires.toUTCString() : '', // Use expires attribute, max-age is not supported by IE. 54 | options.path ? '; path=' + options.path : '', 55 | options.domain ? '; domain=' + options.domain : '', 56 | options.secure ? '; secure' : '' 57 | ].join('')); 58 | } 59 | 60 | // Read. 61 | var decode = config.raw ? raw : decoded; 62 | var cookies = document.cookie.split('; '); 63 | var result = key ? undefined : {}; 64 | for (var i = 0, l = cookies.length; i < l; i++) { 65 | var parts = cookies[i].split('='); 66 | var name = decode(parts.shift()); 67 | var cookie = decode(parts.join('=')); 68 | 69 | if (key && key === name) { 70 | result = converted(cookie); 71 | break; 72 | } 73 | 74 | if (!key) { 75 | result[name] = converted(cookie); 76 | } 77 | } 78 | 79 | return result; 80 | }; 81 | 82 | config.defaults = {}; 83 | 84 | $.removeCookie = function (key, options) { 85 | if ($.cookie(key) !== undefined) { 86 | $.cookie(key, '', $.extend(options, { expires: -1 })); 87 | return true; 88 | } 89 | return false; 90 | }; 91 | 92 | })); 93 | -------------------------------------------------------------------------------- /jquery/jquery.dataTables.plugins.js: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | 6 | $.fn.dataTableExt.oApi.fnStandingRedraw = function(oSettings) { 7 | if(oSettings.oFeatures.bServerSide === false){ 8 | var before = oSettings._iDisplayStart; 9 | 10 | oSettings.oApi._fnReDraw(oSettings); 11 | 12 | // Var iDisplayStart has been reset to zero - so lets change it back. 13 | oSettings._iDisplayStart = before; 14 | oSettings.oApi._fnCalculateEnd(oSettings); 15 | } 16 | 17 | // Draw the 'current' page. 18 | oSettings.oApi._fnDraw(oSettings); 19 | }; 20 | 21 | $.fn.dataTableExt.oApi.fnReloadAjax = function (oSettings, sNewSource, fnCallback, bStandingRedraw) { 22 | if (typeof sNewSource != 'undefined' && sNewSource != null) { 23 | oSettings.sAjaxSource = sNewSource; 24 | } 25 | this.oApi._fnProcessingDisplay( oSettings, true ); 26 | var that = this; 27 | var iStart = oSettings._iDisplayStart; 28 | 29 | oSettings.fnServerData(oSettings.sAjaxSource, null, function(json) { 30 | /* Clear the old information from the table */ 31 | that.oApi._fnClearTable( oSettings ); 32 | 33 | /* Got the data - add it to the table */ 34 | for (var i = 0; i < json.aaData.length; i++) { 35 | that.oApi._fnAddData( oSettings, json.aaData[i] ); 36 | } 37 | 38 | oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); 39 | that.fnDraw(that); 40 | 41 | if (typeof bStandingRedraw != 'undefined' && bStandingRedraw === true) { 42 | oSettings._iDisplayStart = iStart; 43 | that.fnDraw(false); 44 | } 45 | 46 | that.oApi._fnProcessingDisplay(oSettings, false); 47 | 48 | /* Callback user function - for event handlers etc */ 49 | if (typeof fnCallback == 'function' && fnCallback != null) { 50 | fnCallback(oSettings); 51 | } 52 | }); 53 | }; 54 | 55 | $.fn.dataTableExt.oApi.fnSetFilteringDelay = function ( oSettings, iDelay ) { 56 | var _that = this; 57 | this.each( function ( i ) { 58 | $.fn.dataTableExt.iApiIndex = i; 59 | iDelay = (iDelay && (/^[0-9]+$/.test(iDelay))) ? iDelay : 250; 60 | 61 | var $this = this, oTimerId; 62 | var anControl = $( 'input', _that.fnSettings().aanFeatures.f ); 63 | 64 | anControl.unbind( 'keyup' ).bind( 'keyup', function() { 65 | var $$this = $this; 66 | window.clearTimeout(oTimerId); 67 | 68 | oTimerId = window.setTimeout(function() { 69 | $.fn.dataTableExt.iApiIndex = i; 70 | _that.fnFilter( anControl.val() ); 71 | }, iDelay); 72 | }); 73 | 74 | return this; 75 | } ); 76 | return this; 77 | }; -------------------------------------------------------------------------------- /jquery/jqueryui-editable.css: -------------------------------------------------------------------------------- 1 | /*! X-editable - v1.4.3 2 | * In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery 3 | * http://github.com/vitalets/x-editable 4 | * Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */ 5 | 6 | .editableform { 7 | margin-bottom: 0; /* overwrites bootstrap margin */ 8 | } 9 | 10 | .editableform .control-group { 11 | margin-bottom: 0; /* overwrites bootstrap margin */ 12 | white-space: nowrap; /* prevent wrapping buttons on new line */ 13 | line-height: 20px; /* overwriting bootstrap line-height. See #133 */ 14 | } 15 | 16 | .editable-buttons { 17 | display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */ 18 | vertical-align: top; 19 | margin-left: 7px; 20 | /* inline-block emulation for IE7*/ 21 | zoom: 1; 22 | *display: inline; 23 | } 24 | 25 | 26 | 27 | .editable-input { 28 | vertical-align: top; 29 | display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */ 30 | width: auto; /* bootstrap-responsive has width: 100% that breakes layout */ 31 | white-space: normal; /* reset white-space decalred in parent*/ 32 | /* display-inline emulation for IE7*/ 33 | zoom: 1; 34 | *display: inline; 35 | } 36 | 37 | .editable-buttons .editable-cancel { 38 | margin-left: 7px; 39 | } 40 | 41 | /*for jquery-ui buttons need set height to look more pretty*/ 42 | .editable-buttons button.ui-button-icon-only { 43 | height: 24px; 44 | width: 30px; 45 | } 46 | 47 | .editableform-loading { 48 | background: url('../../../mod/turnitintooltwo/pix/loading.gif') center center no-repeat; 49 | height: 25px; 50 | width: auto; 51 | min-width: 25px; 52 | } 53 | 54 | .editable-inline .editableform-loading { 55 | background-position: center 0px; 56 | } 57 | 58 | .editable-error-block { 59 | max-width: 300px; 60 | margin: 5px 0 0 0; 61 | width: auto; 62 | white-space: normal; 63 | } 64 | 65 | /*add padding for jquery ui*/ 66 | .editable-error-block.ui-state-error { 67 | padding: 3px; 68 | } 69 | 70 | .editable-error { 71 | color: red; 72 | } 73 | 74 | .editableform .editable-date { 75 | padding: 0; 76 | margin: 0; 77 | float: left; 78 | } 79 | 80 | 81 | /* checklist vertical alignment */ 82 | .editable-checklist label input[type="checkbox"], 83 | .editable-checklist label span { 84 | vertical-align: middle; 85 | margin: 0; 86 | } 87 | 88 | .editable-checklist label { 89 | white-space: nowrap; 90 | } 91 | 92 | /* set exact width of textarea to fit buttons toolbar */ 93 | .editable-wysihtml5 { 94 | width: 566px; 95 | height: 250px; 96 | } 97 | 98 | /* clear button shown as link in date inputs */ 99 | .editable-clear { 100 | clear: both; 101 | font-size: 0.9em; 102 | text-decoration: none; 103 | text-align: right; 104 | } 105 | 106 | /* IOS-style clear button for text inputs */ 107 | .editable-clear-x { 108 | background: url('../../../mod/turnitintooltwo/pix/clear.png') center center no-repeat; 109 | display: block; 110 | width: 13px; 111 | height: 13px; 112 | position: absolute; 113 | opacity: 0.6; 114 | z-index: 100; 115 | 116 | } 117 | 118 | .editable-clear-x:hover { 119 | opacity: 1; 120 | } 121 | .editable-container { 122 | max-width: none !important; /* without this rule poshytip/tooltip does not stretch */ 123 | } 124 | 125 | .editable-container.popover { 126 | /* width: 300px;*/ /* debug */ 127 | width: auto; /* without this rule popover does not stretch */ 128 | } 129 | 130 | .editable-container.editable-inline { 131 | display: inline-block; 132 | vertical-align: middle; 133 | width: auto; 134 | /* inline-block emulation for IE7*/ 135 | zoom: 1; 136 | *display: inline; 137 | } 138 | 139 | .editable-container.ui-widget { 140 | font-size: inherit; /* jqueryui widget font 1.1em too big, overwrite it */ 141 | } 142 | .editable-click, 143 | a.editable-click, 144 | a.editable-click:hover { 145 | text-decoration: none; 146 | border-bottom: dashed 1px #0088cc; 147 | } 148 | 149 | .editable-click.editable-disabled, 150 | a.editable-click.editable-disabled, 151 | a.editable-click.editable-disabled:hover { 152 | color: #585858; 153 | cursor: default; 154 | border-bottom: none; 155 | } 156 | 157 | .editable-empty, .editable-empty:hover{ 158 | font-style: italic; 159 | color: #DD1144; 160 | border-bottom: none; 161 | text-decoration: none; 162 | } 163 | 164 | .editable-unsaved { 165 | font-weight: bold; 166 | } 167 | 168 | .editable-unsaved:after { 169 | /* content: '*'*/ 170 | } 171 | 172 | /*see https://github.com/vitalets/x-editable/issues/139 */ 173 | .form-horizontal .editable 174 | { 175 | padding-top: 5px; 176 | display:inline-block; 177 | } 178 | 179 | -------------------------------------------------------------------------------- /jquery/plugins.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | defined('MOODLE_INTERNAL') || die(); 18 | 19 | $plugins = array( 20 | 'turnitintooltwo-dataTables' => array('files' => array('jquery.dataTables.js', 'jquery.dataTables.css')), 21 | 'turnitintooltwo-dataTables_plugins' => array('files' => array('jquery.dataTables.plugins.js')), 22 | 'turnitintooltwo-turnitintooltwo' => array('files' => array('turnitintooltwo-2025070302.min.js')), 23 | 'turnitintooltwo-turnitintooltwo_extra' => array('files' => array('turnitintooltwo_extra-2024120301.min.js')), 24 | 'turnitintooltwo-turnitintooltwo_settings' => array('files' => array('turnitintooltwo_settings-2025070302.min.js')), 25 | 'turnitintooltwo-datatables_columnfilter' => array('files' => array('jquery.dataTables.columnFilter.js')), 26 | 'turnitintooltwo-cookie' => array('files' => array('jquery.cookie.js')), 27 | 'turnitintooltwo-colorbox' => array('files' => array('jquery.colorbox.js', 'colorbox.css')), 28 | 'turnitintooltwo-uieditable' => array('files' => array('jqueryui-editable.js', 'jqueryui-editable.css')), 29 | 'turnitintooltwo-moment' => array('files' => array('moment.js')), 30 | 'turnitintooltwo-tooltipster' => array('files' => array('tooltipster.js', 'tooltipster.css')), 31 | 'turnitintooltwo-migration_tool' => array('files' => array()) // Required as this is called from V1. 32 | ); -------------------------------------------------------------------------------- /jquery/turnitintooltwo_settings-2025070302.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This small piece of script is a workaround that's needed to add tabs in to 3 | * the settings page. They need to be removed from the settings form and placed 4 | * outside that containing fieldset. 5 | */ 6 | $(document).ready(function($) { 7 | if ($('.settingsform fieldset div.formsettingheading').length > 0) { 8 | var tabmenu = $('.settingsform fieldset div.formsettingheading:first').html(); 9 | if (tabmenu.indexOf("tabtree") >= 0) { 10 | $('.settingsform fieldset div.formsettingheading:first').remove(); 11 | $('.settingsform h2:first').after(tabmenu); 12 | } 13 | } 14 | 15 | $('input[name="selectallcb"]').click(function() { 16 | if ($(this).prop('checked')) { 17 | $('.browser_checkbox').prop('checked', true); 18 | if ($('.browser_checkbox:checked').length > 0) { 19 | $('.create_checkboxes').slideDown(); 20 | } else { 21 | $('.create_checkboxes').slideUp(); 22 | } 23 | } else { 24 | $('.browser_checkbox').prop('checked', false); 25 | $('.create_checkboxes').slideUp(); 26 | } 27 | }); 28 | 29 | if ($('.test_connection').length > 0) { 30 | if ($('#id_s_turnitintooltwo_accountid').val() != '' || $('#id_s_turnitintooltwo_secretkey').val() != '') { 31 | $('.test_connection').show(); 32 | $('#test_link').show(); 33 | } 34 | 35 | $('#id_s_turnitintooltwo_accountid, #id_s_turnitintooltwo_secretkey, #id_s_turnitintooltwo_apiurl').keyup(function() { 36 | $('#testing_container').hide(); 37 | 38 | var accountid = $('#id_s_turnitintooltwo_accountid').val(); 39 | var accountshared = $('#id_s_turnitintooltwo_secretkey').val(); 40 | 41 | // Make sure they aren't empty strings. 42 | accountid = accountid.trim(); 43 | accountshared = accountshared.trim(); 44 | if (accountid.length == 0 || accountshared.length == 0) { 45 | $('#test_result').hide(); 46 | $('.test_connection').hide(); 47 | } else { 48 | $('.test_connection').show(); 49 | $('#test_link').show(); 50 | } 51 | }); 52 | 53 | $('#test_link').click(function() { 54 | $('#test_result').hide(); 55 | $('input, #id_s_turnitintooltwo_apiurl').prop('disabled', true); 56 | $('#test_link').hide(); 57 | $("#test_result").css('opacity', ''); 58 | $('#test_result').removeClass('test_link_success test_link_fail'); 59 | $('#testing_container').show(); 60 | 61 | // Change Url depending on Settings page. 62 | url = M.cfg.wwwroot + "/mod/turnitintooltwo/ajax.php"; 63 | 64 | var accountid = $('#id_s_turnitintooltwo_accountid').val(); 65 | var accountshared = $('#id_s_turnitintooltwo_secretkey').val(); 66 | var accounturl = $('#id_s_turnitintooltwo_apiurl').val(); 67 | 68 | $.ajax({ 69 | type: "POST", 70 | url: url, 71 | dataType: "json", 72 | data: {action: "test_connection", sesskey: M.cfg.sesskey, accountid: accountid, accountshared: accountshared, url: accounturl}, 73 | success: function(data) { 74 | eval(data); 75 | 76 | $('#testing_container').hide(); 77 | 78 | if (data.connection_status == "success") { 79 | $('#test_result').addClass('test_link_success'); 80 | } else { 81 | $('#test_result').addClass('test_link_fail'); 82 | } 83 | 84 | $('#test_result').html(data.msg); 85 | $('#test_result').show(); 86 | $('#test_link').show(); 87 | $('input, #id_s_turnitintooltwo_apiurl').prop('disabled', false); 88 | } 89 | }); 90 | }); 91 | } 92 | }); -------------------------------------------------------------------------------- /jquery/turnitintooltwo_settings-2025070302.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"turnitintooltwo_settings-2025070302.min.js.map","sources":["turnitintooltwo_settings-2025070302.js"],"names":["$","document","ready","tabmenu","length","html","indexOf","remove","after","click","this","prop","slideDown","slideUp","val","show","keyup","hide","accountid","accountshared","trim","css","removeClass","url","M","cfg","wwwroot","accounturl","ajax","type","dataType","data","action","sesskey","success","eval","connection_status","addClass","msg"],"mappings":"AAKAA,EAAEC,QAAQ,EAAEC,MAAM,SAASF,GACvB,IACQG,QADwD,EAA5DH,EAAE,+CAA+C,EAAEI,SAC/CD,QAAUH,EAAE,qDAAqD,EAAEK,KAAK,EAC1C,GAA9BF,QAAQG,QAAQ,SAAS,KACzBN,EAAE,qDAAqD,EAAEO,OAAO,EAChEP,EAAE,wBAAwB,EAAEQ,MAAML,OAAO,GAIjDH,EAAE,2BAA2B,EAAES,MAAM,WAC7BT,EAAEU,IAAI,EAAEC,KAAK,SAAS,GACtBX,EAAE,mBAAmB,EAAEW,KAAK,UAAW,CAAA,CAAI,EACC,EAAxCX,EAAE,2BAA2B,EAAEI,OAC/BJ,EAAE,oBAAoB,EAAEY,UAAU,EAElCZ,EAAE,oBAAoB,EAAEa,QAAQ,IAGpCb,EAAE,mBAAmB,EAAEW,KAAK,UAAW,CAAA,CAAK,EAC5CX,EAAE,oBAAoB,EAAEa,QAAQ,EAExC,CAAC,EAEkC,EAA/Bb,EAAE,kBAAkB,EAAEI,SAC4B,IAA9CJ,EAAE,iCAAiC,EAAEc,IAAI,GAAyD,IAA9Cd,EAAE,iCAAiC,EAAEc,IAAI,IAC7Fd,EAAE,kBAAkB,EAAEe,KAAK,EAC3Bf,EAAE,YAAY,EAAEe,KAAK,GAGzBf,EAAE,gGAAgG,EAAEgB,MAAM,WACtGhB,EAAE,oBAAoB,EAAEiB,KAAK,EAE7B,IAAIC,EAAYlB,EAAE,iCAAiC,EAAEc,IAAI,EACrDK,EAAgBnB,EAAE,iCAAiC,EAAEc,IAAI,EAG7DI,EAAYA,EAAUE,KAAK,EAC3BD,EAAgBA,EAAcC,KAAK,EACX,GAApBF,EAAUd,QAAuC,GAAxBe,EAAcf,QACvCJ,EAAE,cAAc,EAAEiB,KAAK,EACvBjB,EAAE,kBAAkB,EAAEiB,KAAK,IAE3BjB,EAAE,kBAAkB,EAAEe,KAAK,EAC3Bf,EAAE,YAAY,EAAEe,KAAK,EAE7B,CAAC,EAEDf,EAAE,YAAY,EAAES,MAAM,WAClBT,EAAE,cAAc,EAAEiB,KAAK,EACvBjB,EAAE,qCAAqC,EAAEW,KAAK,WAAY,CAAA,CAAI,EAC9DX,EAAE,YAAY,EAAEiB,KAAK,EACrBjB,EAAE,cAAc,EAAEqB,IAAI,UAAW,EAAE,EACnCrB,EAAE,cAAc,EAAEsB,YAAY,kCAAkC,EAChEtB,EAAE,oBAAoB,EAAEe,KAAK,EAG7BQ,IAAMC,EAAEC,IAAIC,QAAU,gCAEtB,IAAIR,UAAYlB,EAAE,iCAAiC,EAAEc,IAAI,EACrDK,cAAgBnB,EAAE,iCAAiC,EAAEc,IAAI,EACzDa,WAAa3B,EAAE,8BAA8B,EAAEc,IAAI,EAEvDd,EAAE4B,KAAK,CACHC,KAAM,OACNN,IAAKA,IACLO,SAAU,OACVC,KAAM,CAACC,OAAQ,kBAAmBC,QAAST,EAAEC,IAAIQ,QAASf,UAAWA,UAAWC,cAAeA,cAAeI,IAAKI,UAAU,EAC7HO,QAAS,SAASH,MACdI,KAAKJ,IAAI,EAET/B,EAAE,oBAAoB,EAAEiB,KAAK,EAEC,WAA1Bc,KAAKK,kBACLpC,EAAE,cAAc,EAAEqC,SAAS,mBAAmB,EAE9CrC,EAAE,cAAc,EAAEqC,SAAS,gBAAgB,EAG/CrC,EAAE,cAAc,EAAEK,KAAK0B,KAAKO,GAAG,EAC/BtC,EAAE,cAAc,EAAEe,KAAK,EACvBf,EAAE,YAAY,EAAEe,KAAK,EACrBf,EAAE,qCAAqC,EAAEW,KAAK,WAAY,CAAA,CAAK,CACnE,CACJ,CAAC,CACL,CAAC,EAET,CAAC"} -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "turnitintooltwo", 3 | "version": "1.0.0", 4 | "description": "Moodle Direct v2 ================", 5 | "homepage": "https://github.com/turnitin/moodle-mod_turnitintooltwo#readme", 6 | "bugs": { 7 | "url": "https://github.com/turnitin/moodle-mod_turnitintooltwo/issues" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/turnitin/moodle-mod_turnitintooltwo.git" 12 | }, 13 | "license": "GPL-3.0", 14 | "author": "", 15 | "type": "commonjs", 16 | "main": "gulpfile.js", 17 | "directories": { 18 | "test": "tests" 19 | }, 20 | "overrides": { 21 | "gulp-sourcemaps": { 22 | "postcss": ">=8.4.31" 23 | } 24 | }, 25 | "scripts": { 26 | "test": "echo \"Error: no test specified\" && exit 1" 27 | }, 28 | "devDependencies": { 29 | "gulp": "^5.0.1", 30 | "gulp-clean-css": "^4.3.0", 31 | "gulp-notify": "^5.0.0", 32 | "gulp-rename": "^2.1.0", 33 | "gulp-sass": "^6.0.1", 34 | "gulp-sourcemaps": "^3.0.0", 35 | "gulp-uglify": "^3.0.2", 36 | "sass": "^1.89.2" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /pix/back_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/back_disabled.png -------------------------------------------------------------------------------- /pix/back_enabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/back_enabled.png -------------------------------------------------------------------------------- /pix/back_enabled_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/back_enabled_hover.png -------------------------------------------------------------------------------- /pix/bootstrap/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/bootstrap/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /pix/bootstrap/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/bootstrap/glyphicons-halflings.png -------------------------------------------------------------------------------- /pix/changelog/resetcourse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/changelog/resetcourse.png -------------------------------------------------------------------------------- /pix/clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/clear.png -------------------------------------------------------------------------------- /pix/clearpixel.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/clearpixel.gif -------------------------------------------------------------------------------- /pix/colorbox/controls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/colorbox/controls.png -------------------------------------------------------------------------------- /pix/colorbox/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/colorbox/loading.gif -------------------------------------------------------------------------------- /pix/doc-x-grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/doc-x-grey.png -------------------------------------------------------------------------------- /pix/enrolicon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/enrolicon.gif -------------------------------------------------------------------------------- /pix/fileicon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/fileicon.gif -------------------------------------------------------------------------------- /pix/forward_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/forward_disabled.png -------------------------------------------------------------------------------- /pix/forward_enabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/forward_enabled.png -------------------------------------------------------------------------------- /pix/forward_enabled_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/forward_enabled_hover.png -------------------------------------------------------------------------------- /pix/globe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/globe.png -------------------------------------------------------------------------------- /pix/icon-dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/icon-dot.png -------------------------------------------------------------------------------- /pix/icon-student-read.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/icon-student-read.png -------------------------------------------------------------------------------- /pix/icon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/icon.gif -------------------------------------------------------------------------------- /pix/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/icon.png -------------------------------------------------------------------------------- /pix/jqueryui/ui-bg_flat_0_aaaaaa_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/jqueryui/ui-bg_flat_0_aaaaaa_40x100.png -------------------------------------------------------------------------------- /pix/jqueryui/ui-bg_flat_75_ffffff_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/jqueryui/ui-bg_flat_75_ffffff_40x100.png -------------------------------------------------------------------------------- /pix/jqueryui/ui-bg_glass_55_fbf9ee_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/jqueryui/ui-bg_glass_55_fbf9ee_1x400.png -------------------------------------------------------------------------------- /pix/jqueryui/ui-bg_glass_65_ffffff_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/jqueryui/ui-bg_glass_65_ffffff_1x400.png -------------------------------------------------------------------------------- /pix/jqueryui/ui-bg_glass_75_dadada_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/jqueryui/ui-bg_glass_75_dadada_1x400.png -------------------------------------------------------------------------------- /pix/jqueryui/ui-bg_glass_75_e6e6e6_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/jqueryui/ui-bg_glass_75_e6e6e6_1x400.png -------------------------------------------------------------------------------- /pix/jqueryui/ui-bg_glass_95_fef1ec_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/jqueryui/ui-bg_glass_95_fef1ec_1x400.png -------------------------------------------------------------------------------- /pix/jqueryui/ui-bg_highlight-soft_75_cccccc_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/jqueryui/ui-bg_highlight-soft_75_cccccc_1x100.png -------------------------------------------------------------------------------- /pix/jqueryui/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/jqueryui/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /pix/jqueryui/ui-icons_2e83ff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/jqueryui/ui-icons_2e83ff_256x240.png -------------------------------------------------------------------------------- /pix/jqueryui/ui-icons_454545_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/jqueryui/ui-icons_454545_256x240.png -------------------------------------------------------------------------------- /pix/jqueryui/ui-icons_888888_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/jqueryui/ui-icons_888888_256x240.png -------------------------------------------------------------------------------- /pix/jqueryui/ui-icons_cd0a0a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/jqueryui/ui-icons_cd0a0a_256x240.png -------------------------------------------------------------------------------- /pix/loader-lrg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/loader-lrg.gif -------------------------------------------------------------------------------- /pix/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/loader.gif -------------------------------------------------------------------------------- /pix/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/loading.gif -------------------------------------------------------------------------------- /pix/minus.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/minus.gif -------------------------------------------------------------------------------- /pix/nextdisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/nextdisabled.png -------------------------------------------------------------------------------- /pix/nextenabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/nextenabled.png -------------------------------------------------------------------------------- /pix/order_down.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/order_down.gif -------------------------------------------------------------------------------- /pix/order_up.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/order_up.gif -------------------------------------------------------------------------------- /pix/peermark-reviews.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/peermark-reviews.png -------------------------------------------------------------------------------- /pix/peermark-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/peermark-settings.png -------------------------------------------------------------------------------- /pix/plus.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/plus.gif -------------------------------------------------------------------------------- /pix/prevdisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/prevdisabled.png -------------------------------------------------------------------------------- /pix/prevenabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/prevenabled.png -------------------------------------------------------------------------------- /pix/printer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/printer.png -------------------------------------------------------------------------------- /pix/quickmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/quickmark.png -------------------------------------------------------------------------------- /pix/receipt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/receipt.png -------------------------------------------------------------------------------- /pix/refresh.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/refresh.gif -------------------------------------------------------------------------------- /pix/refreshfade.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/refreshfade.gif -------------------------------------------------------------------------------- /pix/rubric.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/rubric.png -------------------------------------------------------------------------------- /pix/sort_asc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/sort_asc.png -------------------------------------------------------------------------------- /pix/sort_asc_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/sort_asc_disabled.png -------------------------------------------------------------------------------- /pix/sort_both.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/sort_both.png -------------------------------------------------------------------------------- /pix/sort_desc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/sort_desc.png -------------------------------------------------------------------------------- /pix/sort_desc_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/sort_desc_disabled.png -------------------------------------------------------------------------------- /pix/sortdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/sortdown.png -------------------------------------------------------------------------------- /pix/sortnone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/sortnone.png -------------------------------------------------------------------------------- /pix/sortup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/sortup.png -------------------------------------------------------------------------------- /pix/tick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/tick.png -------------------------------------------------------------------------------- /pix/tii-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/tii-icon.png -------------------------------------------------------------------------------- /pix/tii-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turnitin/moodle-mod_turnitintooltwo/67c2632ce32730196e4d1d5cc92d6db60faeb9ce/pix/tii-logo.png -------------------------------------------------------------------------------- /sass/_utilities.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Helpers and general styles 3 | */ 4 | 5 | /* 6 | * Lets us clear floats for older moodles 7 | */ 8 | .clearfix:after { 9 | content: "."; 10 | visibility: hidden; 11 | display: block; 12 | height: 0; 13 | clear: both; 14 | } 15 | 16 | .sr-only { 17 | position: absolute; 18 | width: 1px; 19 | height: 1px; 20 | padding: 0; 21 | margin: -1px; 22 | overflow: hidden; 23 | clip: rect(0,0,0,0); 24 | border: 0; 25 | } 26 | 27 | h3.main { 28 | line-height: 40px; 29 | } 30 | 31 | .mod_turnitintooltwo { 32 | .fitem_fbutton { 33 | padding-top:12px; 34 | } 35 | 36 | span.dimmed { 37 | color:#999999; 38 | } 39 | 40 | #assignmentBrowserTable_wrapper { 41 | padding: 10px; 42 | } 43 | 44 | .nowrap { 45 | white-space:nowrap; 46 | } 47 | 48 | .italic { 49 | font-style: italic; 50 | } 51 | 52 | .underline { 53 | text-decoration: underline; 54 | } 55 | 56 | .bold, 57 | #or_container { 58 | font-weight:bold; 59 | } 60 | 61 | span.link { 62 | color: #0000FF; 63 | } 64 | } -------------------------------------------------------------------------------- /sass/_variables.scss: -------------------------------------------------------------------------------- 1 | // Colours 2 | $light-grey: #EFEFEF; 3 | $dark-grey: #A8A8A8; 4 | $light-blue: #bbe6ff; 5 | $light-blue2: #6fcaff; 6 | $gm-blue: #0070A8; 7 | $white: #fff; 8 | $red: #B94A48; 9 | $green: #19B719; 10 | $hover-blue: #00699e; 11 | 12 | // Digital Receipt Success; 13 | $bright-red: #CC0000; 14 | 15 | // Table border colours 16 | $border-color: $light-grey; 17 | 18 | // Odd / Even colours for table 19 | $odd-color: $light-grey; 20 | $even-color: $white; 21 | 22 | // Table padding 23 | $table-padding: 15px; 24 | $table-head-padding: $table-padding - 5px; -------------------------------------------------------------------------------- /sass/partials/_digital_receipt.scss: -------------------------------------------------------------------------------- 1 | .mod_turnitintooltwo_digital_receipt { 2 | display: inline-block; 3 | width: 150px; 4 | } 5 | 6 | #mod_turnitintooltwo #box_receipt { 7 | padding:20px; 8 | } 9 | 10 | #mod_turnitintooltwo #box_receipt .icon { 11 | width:64px; 12 | height:64px; 13 | } 14 | 15 | #mod_turnitintooltwo_digital_receipt_box { 16 | padding: 20px; 17 | background: #fff; 18 | 19 | .mod_turnitintooltwo_logo { 20 | display: block; 21 | margin: 0 auto; 22 | width: 214px; 23 | height: 68px; 24 | } 25 | 26 | #mod_turnitintooltwo_receipt_print { 27 | text-align: right; 28 | display: block; 29 | } 30 | 31 | } 32 | 33 | #mod_turnitintooltwo_upload_success { 34 | color: $bright-red; 35 | } -------------------------------------------------------------------------------- /sass/partials/_eula.scss: -------------------------------------------------------------------------------- 1 | .mod_turnitintooltwo_eula_text { 2 | padding-top: 15px; 3 | text-align: center; 4 | } 5 | 6 | .mod_turnitintooltwo_eula input[type="submit"] { 7 | margin: 0; 8 | } 9 | 10 | .mod_turnitintooltwo_eula { 11 | cursor:pointer; 12 | text-decoration: underline; 13 | text-align: center; 14 | border: 1px solid $bright-red; 15 | padding: 12px 12px 12px; 16 | color: $bright-red; 17 | margin-top:12px; 18 | margin-bottom:16px !important; 19 | font-size: 14px; 20 | font-weight: bold; 21 | display: block; 22 | } 23 | 24 | noscript.mod_turnitintooltwo_eula_noscript { 25 | border: 1px solid $bright-red; 26 | padding: 8px; 27 | background: $white; 28 | width: 99%; 29 | text-align:center; 30 | display:block; 31 | margin:16px 6px; 32 | line-height: 28px; 33 | } 34 | 35 | .mod_turnitintooltwo_eula_warn { 36 | color: $bright-red; 37 | } -------------------------------------------------------------------------------- /sass/partials/_inbox.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Tabs on inbox page - this is overriding jquery datatables styles. 3 | */ 4 | .mod_turnitintooltwo .ui-widget-header { 5 | background: $light-grey !important; 6 | border: 0 !important; 7 | margin-bottom: 6px !important; 8 | } 9 | 10 | .mod_turnitintooltwo .ui-widget-content { 11 | border: 0 !important; 12 | } 13 | 14 | .mod_turnitintooltwo .ui-tabs .ui-tabs-panel { 15 | padding: 0 !important; 16 | } 17 | 18 | .mod_turnitintooltwo .ui-tabs .ui-tabs-nav { 19 | padding: 10px 10px 0 !important; 20 | } 21 | 22 | /* 23 | * Unanonymise form in modal 24 | */ 25 | .mod_turnitintooltwo_unanonymise_form { 26 | background: #FFFFFF; 27 | padding: 12px 12px 0; 28 | height: 100%; 29 | overflow: hidden 30 | } 31 | 32 | #mod_turnitintooltwo_unanonymise_desc { 33 | text-align: center; 34 | font-weight: bold; 35 | display: block; 36 | margin-bottom: 10px; 37 | } 38 | 39 | .mod_turnitintooltwo_unanonymise_form textarea { 40 | height: 90px; 41 | width: 80%; 42 | } 43 | 44 | /* 45 | * Email non submitters form 46 | */ 47 | 48 | .mod_turnitintooltwo_nonsubmittersform textarea { 49 | height: 90px; 50 | width: 80%; 51 | } 52 | 53 | .mod_turnitintooltwo_general_warning { 54 | margin-top: 8px; 55 | } 56 | 57 | .mod_turnitintooltwo_nonsubmittersformsuccessmsg { 58 | text-align: center; 59 | padding-top: 46px; 60 | } 61 | 62 | #mod_turnitintooltwo_download_links { 63 | margin-left: 15px; 64 | top: -5px; 65 | } 66 | 67 | #mod_turnitintooltwo_rubric_view_form { 68 | padding-left: 6px; 69 | } 70 | 71 | .mod_turnitintooltwo_peermark-loading-span img.icon { 72 | margin-right: 0px; 73 | } -------------------------------------------------------------------------------- /sass/partials/_listbar.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Listbar - Contains datatables links, dropdowns and search 3 | */ 4 | 5 | .mod_turnitintooltwo_listbar-container { 6 | display: table; 7 | width: 100%; 8 | } 9 | 10 | .mod_turnitintooltwo_listbar { 11 | background: #fff; 12 | border: 1px solid $border-color; 13 | position: relative; 14 | display: table-cell; 15 | vertical-align: middle; 16 | padding: 10px; 17 | 18 | label, 19 | input, 20 | select { 21 | margin: 0; 22 | } 23 | 24 | select, 25 | input { 26 | height: 30px; 27 | padding: 0 5px; 28 | border: 1px solid #EFEFEF; 29 | -webkit-border-radius: 4px; 30 | -moz-border-radius: 4px; 31 | border-radius: 4px; 32 | background: #fff; 33 | } 34 | 35 | .mod_turnitintooltwo_refresh_link, 36 | .mod_turnitintooltwo_refreshing_link, 37 | .mod_turnitintooltwo_nonsubmitters_link { 38 | float: right; 39 | margin-left: 30px; 40 | padding: 5px 0; 41 | width: 195px; 42 | } 43 | 44 | .mod_turnitintooltwo_nonsubmitters_link { 45 | text-decoration: none; 46 | display: none; 47 | } 48 | 49 | /* 50 | * Messages inbox link in listbar 51 | */ 52 | .mod_turnitintooltwo_messages_inbox { 53 | float: right; 54 | margin-left: 30px; 55 | padding: 5px 0; 56 | text-decoration: none; 57 | } 58 | 59 | .mod_turnitintooltwo_messages_loading { 60 | float: none !important; 61 | margin: 0 !important; 62 | } 63 | 64 | // Zip file download links 65 | .mod_turnitintooltwo_zip_downloads { 66 | float: left; 67 | position: relative; 68 | top: 4px; 69 | height: 22px; 70 | 71 | img { 72 | position: relative; 73 | top: 4px; 74 | left: -2px; 75 | } 76 | 77 | div.mod_turnitintooltwo_origchecked_zip_open, 78 | a.mod_turnitintooltwo_gmpdfzip_box { 79 | padding: 3px 16px; 80 | display: block; 81 | } 82 | 83 | a.mod_turnitintooltwo_gmpdfzip_box:hover { 84 | background: $hover-blue; 85 | color: $white; 86 | } 87 | 88 | .mod_turnitintooltwo_zip_open { 89 | display: inline; 90 | } 91 | 92 | .mod_turnitintooltwo_dropdown-menu .mod_turnitintooltwo_origchecked_zip_open:hover { 93 | background-color: $hover-blue; 94 | display: block; 95 | line-height: 20px; 96 | color: $white; 97 | font-weight: normal; 98 | } 99 | 100 | .mod_turnitintooltwo_dropdown-menu { 101 | white-space: nowrap; 102 | margin-top: 2px !important; 103 | } 104 | } 105 | 106 | /* 107 | * DataTables filter (search bar) 108 | */ 109 | .dataTables_filter { 110 | float: right !important; 111 | text-align: left !important; 112 | } 113 | 114 | /* 115 | * DataTables length (how many per page) 116 | */ 117 | .dataTables_length { 118 | float: left !important; 119 | } 120 | } 121 | 122 | @media screen and (max-width: 1500px) { 123 | .dataTables_filter { 124 | input[type="search"] { 125 | max-width: 150px; 126 | } 127 | } 128 | } 129 | 130 | @media screen and (max-width: 1460px) { 131 | .mod_turnitintooltwo_listbar { 132 | font-size: 13px; 133 | } 134 | } 135 | 136 | @media screen and (max-width: 1350px) { 137 | .dataTables_filter { 138 | input[type="search"] { 139 | max-width: 80px; 140 | } 141 | } 142 | 143 | .mod_turnitintooltwo_listbar .mod_turnitintooltwo_messages_inbox, 144 | .mod_turnitintooltwo_listbar .mod_turnitintooltwo_refresh_link { 145 | margin-left: 5px; 146 | width: auto; 147 | } 148 | 149 | .mod_turnitintooltwo_listbar .mod_turnitintooltwo_refresh_link { 150 | padding-left: 5px; 151 | padding-right: 5px; 152 | } 153 | 154 | .mod_turnitintooltwo_listbar { 155 | #mod_turnitintooltwo_download_links { 156 | margin-left: 5px; 157 | 158 | .btn.dropdown-toggle { 159 | padding-left: 6px; 160 | padding-right: 6px; 161 | } 162 | } 163 | } 164 | } 165 | 166 | @media screen and (max-width: 1260px) { 167 | .mod_turnitintooltwo_listbar { 168 | font-size: 12px; 169 | 170 | .mod_turnitintooltwo_nonsubmitters_link { 171 | width: auto; 172 | margin-left: 0; 173 | padding: 5px 5px; 174 | } 175 | } 176 | 177 | .dataTables_filter { 178 | input[type="search"] { 179 | max-width: 95px; 180 | } 181 | } 182 | 183 | .mod_turnitintooltwo_listbar { 184 | #mod_turnitintooltwo_download_links { 185 | .btn.dropdown-toggle { 186 | padding-right: 0; 187 | } 188 | } 189 | } 190 | } 191 | 192 | // do not support Firefox 193 | @media screen and (max-width: 1024px) and (min-resolution: 1.1dppx) { 194 | .mod_turnitintooltwo_listbar { 195 | font-size: 11px; 196 | } 197 | .dataTables_filter input[type=search] { 198 | max-width: 45px; 199 | } 200 | } -------------------------------------------------------------------------------- /sass/partials/_members.scss: -------------------------------------------------------------------------------- 1 | .mod_turnitintooltwo_members { 2 | // Overwrite datatables CSS for loading message to cover the whole table 3 | // accurately. By default datatables centers the loading message vertically 4 | // and horizontally but it is only the size of the message meaning a user 5 | // can click the content being loaded behind the message as the loading mask 6 | // won't cover it all. Fix is to create a loading mask that covers all the 7 | // loading content and position the message within the mask 8 | .dataTables_wrapper .dataTables_processing { 9 | // cover entire table that is loading 10 | top: 0px; 11 | left: 0px; 12 | right: 0px; 13 | height: 100%; 14 | margin: 0px; 15 | padding: 0px; 16 | 17 | .loading-message { 18 | // position message within loading element 19 | position: absolute; 20 | top: 50%; 21 | left: 0px; 22 | right: 0px; 23 | margin-top: -10px; // half line-height 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /sass/partials/_modal.scss: -------------------------------------------------------------------------------- 1 | /* 2 | 1. Styles within modal 3 | 2. Styles for actual colorbox modal 4 | 3. Styles for close bar at the top 5 | */ 6 | 7 | /* 8 | * 1. Within the modal 9 | */ 10 | 11 | .mod_turnitintooltwo #id_submissiontext { 12 | width: 80%; 13 | height: 320px; 14 | } 15 | 16 | /* 17 | * 2. Colorbox modal iframe 18 | */ 19 | #colorbox { 20 | margin-top: 60px; 21 | outline: 0 !important; 22 | overflow: visible !important; 23 | } 24 | 25 | .cboxIframe { 26 | border-radius: 5px; 27 | } 28 | 29 | #cboxContent { 30 | margin-top: 0 !important; 31 | } 32 | 33 | /* 34 | * 3. Modal close bar 35 | */ 36 | #tii_close_bar { 37 | position: fixed; 38 | z-index: 9999; 39 | right: 0; 40 | top: 0; 41 | width: 100%; 42 | height: 45px; 43 | background: rgba(0, 0, 0, .3); 44 | 45 | a { 46 | color: #fff; 47 | display: block; 48 | background: #000; 49 | width: 100px; 50 | text-align: center; 51 | float: right; 52 | text-decoration: none; 53 | height: 45px; 54 | line-height: 43px; 55 | } 56 | } -------------------------------------------------------------------------------- /sass/partials/_part_details.scss: -------------------------------------------------------------------------------- 1 | .mod_turnitintooltwo_part_details { 2 | font-size: 13px; 3 | margin-bottom:0px; 4 | width:100%; 5 | border: 1px solid $border-color; 6 | 7 | tr { 8 | border-right: 1px solid $border-color; 9 | } 10 | 11 | th { 12 | padding: 6px 12px 6px; 13 | border-bottom: 1px solid $border-color; 14 | } 15 | 16 | td { 17 | border: 1px solid $border-color; 18 | border-top: 0; 19 | padding: 12px 12px 4px; 20 | } 21 | 22 | td.data, 23 | td.export_data, 24 | td.rubric_qm { 25 | text-align: center; 26 | } 27 | 28 | td.export_data { 29 | padding-top:12px; 30 | } 31 | 32 | td.introduction_cell { 33 | border:0; 34 | padding:0; 35 | } 36 | 37 | td.peermarks { 38 | border:0; 39 | } 40 | 41 | td.peermark_assignments_cell { 42 | padding:0; 43 | border:0; 44 | } 45 | 46 | .editable-click { 47 | border:none; 48 | position: relative; 49 | padding-right: 24px; 50 | 51 | &:hover { 52 | border-bottom: 0 !important; 53 | } 54 | } 55 | 56 | .editor-pencil { 57 | padding-left: 25px; 58 | } 59 | 60 | /* 61 | * Introduction (summary section) 62 | */ 63 | .introduction, 64 | .peermark_instructions { 65 | padding: 6px 10px; 66 | border-bottom: 1px solid $border-color; 67 | display: none; 68 | } 69 | 70 | .introduction h2 { 71 | margin: 8px 0; 72 | } 73 | 74 | .introduction p { 75 | margin: 6px 0; 76 | } 77 | 78 | /* 79 | * Export options 80 | */ 81 | .row_export_xls, 82 | .row_export_pdf, 83 | .row_export_orig, 84 | .mod_turnitintooltwo_zip_open, 85 | .row_rubric_manager, 86 | .row_quickmark_manager { 87 | display:inline; 88 | } 89 | 90 | .toggle_peermark_instructions img { 91 | display: block; 92 | } 93 | 94 | .toggle_summary, 95 | .toggle_peermarks, 96 | .toggle_peermark_instructions { 97 | cursor: pointer; 98 | float:left; 99 | position: relative; 100 | top:-3px; 101 | margin-right:8px; 102 | } 103 | 104 | .peermark_header { 105 | margin-bottom:8px; 106 | float:left; 107 | } 108 | } 109 | 110 | #turnitin_sync_all_grades { 111 | float: right; 112 | font-size: 16px; 113 | } 114 | 115 | .turnitin_sync_grades, .turnitin_syncing_grades { 116 | cursor: pointer; 117 | margin-bottom: 20px; 118 | } 119 | 120 | .turnitin_syncing_grades { 121 | display: none; 122 | } 123 | 124 | .mod_turnitintooltwo_peermark_details { 125 | width: 100%; 126 | border-top: 1px solid $border-color; 127 | 128 | td { 129 | padding:8px 12px; 130 | border-bottom-width: 0; 131 | } 132 | 133 | td.peermark_instructions_cell { 134 | border:0; 135 | padding:0; 136 | } 137 | } 138 | 139 | .mod_turnitintooltwo_quickmark_manager_launch { 140 | padding: 2px 0 2px 30px; 141 | height: 20px; 142 | color: #0070A8 !important; 143 | } 144 | 145 | .mod_turnitintooltwo_rubric_manager_launch, 146 | .mod_turnitintooltwo_rubric_view_launch { 147 | padding:4px 0px 4px 0px; 148 | line-height: 22px; 149 | color: #0070A8 !important; 150 | } 151 | 152 | .tii_peermark_manager_launch { 153 | color: #009900 !important; 154 | } 155 | 156 | .tii_peermark_reviews_launch { 157 | color: #009900 !important; 158 | } 159 | 160 | .tii_peermark_manager_launch, 161 | .tii_peermark_reviews_launch { 162 | padding: 4px 0 4px 46px; 163 | height: 22px; 164 | } 165 | 166 | .mod_turnitintooltwo .peermark_loading_row { 167 | text-align: center; 168 | margin:0 auto 8px; 169 | } 170 | 171 | @media screen and (max-width: 1400px) { 172 | td.cell { 173 | position: relative; 174 | } 175 | 176 | .mod_turnitintooltwo_part_details .editable-click { 177 | position: unset; 178 | &:before { 179 | top: 5px; 180 | right: 5px; 181 | } 182 | } 183 | } -------------------------------------------------------------------------------- /sass/partials/_table.scss: -------------------------------------------------------------------------------- 1 | /* 2 | 1. DataTable Table 3 | 2. DataTable Pagination 4 | 3. Score colour 5 | */ 6 | 7 | 8 | /* 9 | * 1. Table styles and related 10 | */ 11 | .mod_turnitintooltwo_submissions_data_table, 12 | #mod_turnitintooltwo_course_browser_table { 13 | width:100%; 14 | font-size: 13px; 15 | border:1px solid $border-color; 16 | width:100% !important; 17 | margin-top: 6px !important; 18 | 19 | .ccheckbox { 20 | text-align: center; 21 | padding: 8px 10px 2px !important; 22 | } 23 | 24 | .odd { 25 | background: $odd-color !important; 26 | 27 | .sorting_1 { 28 | background: darken($odd-color, 3%) !important; 29 | } 30 | } 31 | 32 | .even { 33 | background: $even-color !important; 34 | 35 | .sorting_1 { 36 | background: darken($even-color, 2%) !important; 37 | } 38 | } 39 | 40 | a { 41 | text-decoration: none; 42 | } 43 | 44 | thead th { 45 | border-bottom: 0 !important; 46 | } 47 | 48 | th { 49 | padding: $table-head-padding 20px !important; 50 | } 51 | 52 | td { 53 | padding: $table-padding 10px !important; 54 | font-size: 13px; 55 | vertical-align: top; 56 | } 57 | 58 | .sorting_disabled { 59 | cursor: default; 60 | } 61 | 62 | .left { 63 | text-align: left; 64 | } 65 | 66 | .right { 67 | text-align: right; 68 | } 69 | 70 | .grademark_open, 71 | .grademark_grade, 72 | .origreport_score { 73 | float:right; 74 | } 75 | 76 | .grademark_grade, 77 | .origreport_score { 78 | padding-right:8px; 79 | } 80 | 81 | th.narrow, 82 | td.narrow { 83 | width: 60px; 84 | } 85 | 86 | .submit_nothing, .submission_title, .delete_paper { 87 | cursor: pointer; 88 | } 89 | 90 | .score_colour { 91 | width:36px; 92 | display:inline-block; 93 | float:right; 94 | } 95 | 96 | .late_submission { 97 | color: #d31900; 98 | } 99 | 100 | #tii_digital_receipt_icon { 101 | margin-top: -3px; 102 | margin-right: 5px; 103 | } 104 | } 105 | 106 | /* 107 | * 2. DataTables pagination 108 | */ 109 | .dataTables_paginate { 110 | margin-top: 6px; 111 | font-size:12px; 112 | float: right; 113 | 114 | a { 115 | display: inline-block; 116 | border: 1px solid $border-color; 117 | padding: 2px 5px; 118 | background-position: left -2px; 119 | } 120 | 121 | .current { 122 | background: #EFEFEF; 123 | } 124 | 125 | span a { 126 | border-right: 0; 127 | } 128 | 129 | .previous { 130 | border-right: 0; 131 | } 132 | 133 | } 134 | 135 | .dataTables_info { 136 | float:left; 137 | clear:none; 138 | margin-top: 8px; 139 | text-transform: uppercase; 140 | font-size: 11px; 141 | } 142 | 143 | 144 | /* 145 | * 3. Score colour for originality report. 146 | */ 147 | .mod_turnitintooltwo .score_colour_ { background: #999999; } 148 | .mod_turnitintooltwo .score_colour_0 { background: #3552B7; } 149 | .mod_turnitintooltwo .score_colour_10 { background: #617B8D; } 150 | .mod_turnitintooltwo .score_colour_20 { background: #A1B556; } 151 | .mod_turnitintooltwo .score_colour_30 { background: #DAE235; } 152 | .mod_turnitintooltwo .score_colour_40 { background: #EDAC28; } 153 | .mod_turnitintooltwo .score_colour_50 { background: #EDD42F; } 154 | .mod_turnitintooltwo .score_colour_60 { background: #ECAD28; } 155 | .mod_turnitintooltwo .score_colour_70 { background: #E15A21; } 156 | .mod_turnitintooltwo .score_colour_80 { background: #E05A21; } 157 | .mod_turnitintooltwo .score_colour_90 { background: #DC4321; } 158 | .mod_turnitintooltwo .score_colour_100 { background: #DB4221; } 159 | 160 | 161 | .mod_turnitintooltwo .enrol_link { 162 | padding: 6px 18px 0 0; 163 | } -------------------------------------------------------------------------------- /sass/settings_partials/_class_migration_tab.scss: -------------------------------------------------------------------------------- 1 | /* 2 | Located at mod/turnitintooltwo/settings_extras.php?cmd=courses 3 | */ 4 | 5 | .mod_turnitintooltwo_edit_course_end_date_form { 6 | padding: 12px 12px 0; 7 | background: $white; 8 | height: 100%; 9 | overflow: hidden; 10 | 11 | #edit_end_date_desc { 12 | text-align: center; 13 | margin-bottom: 20px; 14 | } 15 | 16 | .fitemtitle { 17 | float: none !important; 18 | text-align: center !important; 19 | width: 100% !important; 20 | display: block !important; 21 | } 22 | 23 | .fdate_selector { 24 | float: none !important; 25 | display: block !important; 26 | margin: 0 auto !important; 27 | width: 256px !important; 28 | } 29 | 30 | .fbutton { 31 | width: 100% !important; 32 | margin: 0 !important; 33 | } 34 | 35 | #id_save_end_date { 36 | margin: 0 auto !important; 37 | display: block !important; 38 | } 39 | } -------------------------------------------------------------------------------- /sass/settings_partials/_settings_tab.scss: -------------------------------------------------------------------------------- 1 | #page-admin-setting-modsettingturnitintooltwo { 2 | 3 | #test_link, 4 | #testing_container { 5 | margin-bottom:8px; 6 | } 7 | 8 | #test_link img { 9 | position: relative; 10 | top:4px; 11 | } 12 | 13 | #test_result { 14 | margin: 4px 0 0; 15 | padding: 5px 10px; 16 | width: 500px; 17 | text-align: center; 18 | } 19 | 20 | .test_link_success { 21 | border: 1px solid #00CC00; 22 | background: #C3FDB8; 23 | } 24 | 25 | .test_link_fail { 26 | border:1px solid #CC0000; 27 | background: #E77471; 28 | } 29 | 30 | .smallicon { 31 | vertical-align: middle; 32 | } 33 | 34 | // Upgrade 35 | .tii_upgrade_check, 36 | .tii_upgrading_check { 37 | font-size: 12px; 38 | } 39 | 40 | .tii_upgrade_check { 41 | text-decoration: underline; 42 | cursor: pointer; 43 | } 44 | 45 | .tii_upgrade_check, 46 | .tii_upgrading_check { 47 | width: 30px; 48 | height: 30px; 49 | display: inline-block; 50 | } 51 | .tii_upgrade_check img, 52 | .tii_upgrading_check img { 53 | padding: 0 0 5px 5px; 54 | vertical-align: middle; 55 | } 56 | 57 | .tii_upgrading_check img { 58 | position: relative; 59 | top: 3px; 60 | } 61 | } -------------------------------------------------------------------------------- /sass/styles.scss: -------------------------------------------------------------------------------- 1 | @import "variables"; 2 | 3 | @import "utilities"; 4 | 5 | // Partials 6 | @import "partials/listbar"; 7 | @import "partials/table"; 8 | @import "partials/part_details"; 9 | @import "partials/modal"; 10 | @import "partials/eula"; 11 | @import "partials/digital_receipt"; 12 | @import "partials/inbox"; 13 | @import "partials/members"; 14 | 15 | // Settings Page Partials 16 | @import "settings_partials/class_migration_tab"; 17 | @import "settings_partials/settings_tab"; 18 | 19 | // Other - Got nowhere to go 20 | @import "other"; 21 | -------------------------------------------------------------------------------- /sdk/log.class.php: -------------------------------------------------------------------------------- 1 | rotateLogs( $filepath ); 20 | parent::setDateFormat( 'Y-m-d G:i:s O' ); 21 | parent::__construct($filepath, self::LOGLEVEL); 22 | } 23 | 24 | private function rotateLogs( $filepath ) { 25 | if ( !file_exists( $filepath ) ) { 26 | mkdir( $filepath, 0777, true ); 27 | } 28 | $dir=opendir( $filepath ); 29 | $files=array(); 30 | while ($entry=readdir( $dir )) { 31 | if ( substr( basename( $entry ) ,0 ,1 )!='.' AND substr_count(basename( $entry ),parent::PREFIX ) > 0 ) { 32 | $files[]=basename( $entry ); 33 | } 34 | } 35 | sort( $files ); 36 | for ($i=0; $i -------------------------------------------------------------------------------- /sdk/perflog.class.php: -------------------------------------------------------------------------------- 1 | start_time = microtime(true); 9 | } 10 | 11 | public function stop_timer($ch) { 12 | $total_response_time = (microtime(true) - $this->start_time); 13 | $this->log($ch, $total_response_time); 14 | } 15 | 16 | protected function log($ch, $total_response_time) { 17 | // Override this method to implement your own logging. 18 | } 19 | 20 | } 21 | 22 | //?> -------------------------------------------------------------------------------- /sdk/sdkexception.class.php: -------------------------------------------------------------------------------- 1 | setFaultCode( $faultcode ); //$this->faultcode = $faultcode; 23 | $this->setMessage( $message ); 24 | $this->setOutputTitle( 'Turnitin SDK Exception' ); 25 | $logger = new TurnitinLogger( $logpath ); 26 | if ( $logger ) $logger->logError( $this->getOutputTitle() . ': ' . $this->getFaultCode() . ' - ' . $this->getMessage() ); 27 | } 28 | 29 | /** 30 | * @ignore 31 | * 32 | * @param string $message 33 | */ 34 | private function setMessage( $message ) { 35 | $this->message = $message; 36 | } 37 | 38 | /** 39 | * @ignore 40 | * 41 | * @param string $outputtitle 42 | */ 43 | private function setOutputTitle( $outputtitle ) { 44 | $this->outputtitle = $outputtitle; 45 | } 46 | 47 | /** 48 | * @ignore 49 | * 50 | * @return string 51 | */ 52 | private function getOutputTitle() { 53 | return $this->outputtitle; 54 | } 55 | 56 | /** 57 | * @ignore 58 | * 59 | * @param string $faultcode 60 | */ 61 | private function setFaultCode( $faultcode ) { 62 | $this->faultcode = $faultcode; 63 | } 64 | 65 | /** 66 | * Get the API Fault Code 67 | * 68 | * Possible Fault Code strings: 69 | *
    70 | *
  • invaliddata 71 | *
  • unknownobject 72 | *
  • nosourcedids 73 | *
  • unauthorizedrequest 74 | *
  • deletefailure 75 | *
  • unknownvocabulary 76 | *
  • targetreadfailure 77 | *
  • apiconnecterror 78 | *
  • Authentication Fault 79 | *
80 | * 81 | * @return string 82 | */ 83 | public function getFaultCode() { 84 | return $this->faultcode; 85 | } 86 | 87 | } 88 | 89 | //?> -------------------------------------------------------------------------------- /sdk/tiiform.class.php: -------------------------------------------------------------------------------- 1 | hasbutton ) ) ? true : $this->hasbutton; 21 | } 22 | 23 | /** 24 | * Determines if the LTI form output should have a submit button 25 | * 26 | * @param type $hasbutton 27 | */ 28 | public function setHasButton( $hasbutton) { 29 | $this->hasbutton = $hasbutton; 30 | } 31 | 32 | /** 33 | * Get the Button Text for an LTI Launch submit button 34 | * 35 | * @return string 36 | */ 37 | public function getButtonText() { 38 | return $this->buttontext; 39 | } 40 | 41 | /** 42 | * Set the Button Text for an LTI Launch submit button 43 | * 44 | * @param string $buttontext 45 | */ 46 | public function setButtonText( $buttontext ) { 47 | $this->buttontext = $buttontext; 48 | } 49 | 50 | /** 51 | * Get the Button Style for an LTI Launch submit button 52 | * 53 | * @return string 54 | */ 55 | public function getButtonStyle() { 56 | return $this->buttonstyle; 57 | } 58 | 59 | /** 60 | * Set the Button Style for an LTI Launch submit button 61 | * 62 | * @param string $buttonstyle 63 | */ 64 | public function setButtonStyle( $buttonstyle ) { 65 | $this->buttonstyle = $buttonstyle; 66 | } 67 | 68 | /** 69 | * Get the Form Target for an LTI Launch 70 | * 71 | * A window target to display the LTI launch destination screen in 72 | * 73 | * @return string 74 | */ 75 | public function getFormTarget() { 76 | return isset( $this->formtarget ) ? $this->formtarget : '_blank'; 77 | } 78 | 79 | /** 80 | * Set the Form Target for an LTI Launch 81 | * 82 | * A window target to display the LTI launch destination screen in 83 | * 84 | * @param string $formtarget 85 | */ 86 | public function setFormTarget( $formtarget ) { 87 | $this->formtarget = $formtarget; 88 | } 89 | 90 | /** 91 | * Gets a the Boolean WideMode, this boolean determines the layout of the LTI UI, by default the view will be fixed width 'modal' output. 92 | * By setting WideMode to true the layout will be not be fixed width and will stretch to fit the window / frame 93 | * 94 | * @return boolean 95 | */ 96 | public function getWideMode() { 97 | return (boolean)(integer)$this->widemode; 98 | } 99 | 100 | /** 101 | * Sets a the Boolean WideMode, this boolean determines the layout of the LTI UI, by default the view will be fixed width 'modal' output. 102 | * By setting WideMode to true the layout will be not be fixed width and will stretch to fit the window / frame 103 | * 104 | * @param boolean $widemode 105 | */ 106 | public function setWideMode( $widemode ) { 107 | $this->widemode = $widemode; 108 | } 109 | 110 | } 111 | 112 | //?> -------------------------------------------------------------------------------- /sdk/tiimembership.class.php: -------------------------------------------------------------------------------- 1 | membershipid = $membershipid; 32 | } 33 | 34 | /** 35 | * Get the Membership ID for this Membership 36 | * 37 | * The membership ID is the ID Turnitin uses to identify an enrollment on a class 38 | * 39 | * @param integer $membershipid 40 | */ 41 | public function getMembershipId() { 42 | return $this->membershipid; 43 | } 44 | 45 | /** 46 | * Set an array of Membership IDs for this Membership data object 47 | * 48 | * The membership ID is the ID Turnitin uses to identify an enrollment on a class 49 | * 50 | * @param array $membershipids 51 | */ 52 | public function setMembershipIds( $membershipids ) { 53 | $this->membershipids = $membershipids; 54 | } 55 | 56 | /** 57 | * Get an array of Membership IDs for this Membership data object 58 | * 59 | * The membership ID is the ID Turnitin uses to identify an enrollment on a class 60 | * 61 | * @return array 62 | */ 63 | public function getMembershipIds() { 64 | return $this->membershipids; 65 | } 66 | 67 | /** 68 | * Set the User ID for this Membership 69 | * 70 | * The User ID of the User enrolled on this Class 71 | * 72 | * @return integer 73 | */ 74 | public function setUserId( $userid ) { 75 | $this->userid = $userid; 76 | } 77 | 78 | /** 79 | * Get the User ID for this Membership 80 | * 81 | * The User ID of the User enrolled on this Class 82 | * 83 | * @return integer 84 | */ 85 | public function getUserId() { 86 | return $this->userid; 87 | } 88 | 89 | /** 90 | * Set the Class ID for this Membership 91 | * 92 | * The Class ID a User is enrolled on 93 | * 94 | * @param integer $classid 95 | */ 96 | public function setClassId( $classid ) { 97 | $this->classid = $classid; 98 | } 99 | 100 | /** 101 | * Get the Class ID for this Membership 102 | * 103 | * The Class ID a User is enrolled on 104 | * 105 | * @return integer 106 | */ 107 | public function getClassId() { 108 | return $this->classid; 109 | } 110 | 111 | /** 112 | * Set the Role for this Membership 113 | * 114 | * The Role the user is enrolled on the Class as, Learner or Instructor 115 | * 116 | * @param string $role 117 | */ 118 | public function setRole( $role ) { 119 | switch ( strtolower( $role ) ) { 120 | case 'student': 121 | $role = 'Learner'; 122 | break; 123 | case 'learner': 124 | $role = 'Learner'; 125 | break; 126 | case 'instructor': 127 | $role = 'Instructor'; 128 | break; 129 | } 130 | $this->role = $role; 131 | } 132 | 133 | /** 134 | * Get the Role for this Membership 135 | * 136 | * The Role the user is enrolled on the Class as, Learner or Instructor 137 | * 138 | * @return string 139 | */ 140 | public function getRole() { 141 | return $this->role; 142 | } 143 | 144 | } 145 | 146 | //?> -------------------------------------------------------------------------------- /sdk/tiipseudouser.class.php: -------------------------------------------------------------------------------- 1 | setPseudoDomain( $pseudodomain ); 31 | } 32 | 33 | /** 34 | * Set the Email Address for this Pseudo User 35 | * 36 | * Takes a real LMS email address which is converted into a fake / pseudo email address when retrieved. 37 | * This function is mainly useful when personally identifiable user data should not be transmitted and stored in Turnitin. 38 | * 39 | * @return string 40 | */ 41 | public function setEmail($email) { 42 | $this->email = $email; 43 | } 44 | 45 | /** 46 | * Get the Email Address for this Pseudo User 47 | * 48 | * This function returns a fake user email, created using the pseudo domain and pseudo salt to SHA hash 49 | * the email address and form a fake / pseudo email address by combining the hash with the Pseudo Domain 50 | * 51 | * @return string 52 | */ 53 | public function getEmail() { 54 | if ( substr( $this->pseudodomain, 0, 1 ) != '@' ) { 55 | $this->pseudodomain = '@' . $this->pseudodomain; 56 | } 57 | return sha1( $this->email.$this->pseudosalt ) . $this->pseudodomain; 58 | } 59 | 60 | /** 61 | * Get the Pseudo Domain for this Pseudo User 62 | * 63 | * @return string 64 | */ 65 | public function getPseudoDomain() { 66 | return $this->pseudodomain; 67 | } 68 | 69 | /** 70 | * Set the Pseudo Domain for this Pseudo User 71 | * 72 | * @param string $pseudodomain 73 | */ 74 | private function setPseudoDomain($pseudodomain) { 75 | $this->pseudodomain = $pseudodomain; 76 | } 77 | 78 | /** 79 | * Get the Pseudo Salt for this Pseudo User 80 | * 81 | * A salt string to use in order to make the Pseudo User Email address less reproducable 82 | * 83 | * @return text 84 | */ 85 | public function getPseudoSalt() { 86 | return $this->pseudosalt; 87 | } 88 | 89 | /** 90 | * Set the Pseudo Salt for this Pseudo User 91 | * 92 | * A salt string to use in order to make the Pseudo User Email address less reproducable 93 | * 94 | * @param text $pseudosalt 95 | */ 96 | public function setPseudoSalt($pseudosalt) { 97 | $this->pseudosalt = $pseudosalt; 98 | } 99 | 100 | } 101 | 102 | //?> -------------------------------------------------------------------------------- /sdk/tiirubric.class.php: -------------------------------------------------------------------------------- 1 | rubricid; 29 | } 30 | 31 | /** 32 | * Set the Id for this Rubric 33 | * 34 | * @param integer $rubricid 35 | */ 36 | public function setRubricId($rubricid) { 37 | $this->rubricid = $rubricid; 38 | } 39 | 40 | /** 41 | * Get the Name for this Rubric 42 | * 43 | * @return text 44 | */ 45 | public function getRubricName() { 46 | return $this->rubricname; 47 | } 48 | 49 | /** 50 | * Set the Name for this Rubric 51 | * 52 | * @param text $rubricname 53 | */ 54 | public function setRubricName($rubricname) { 55 | $this->rubricname = $rubricname; 56 | } 57 | 58 | /** 59 | * Get the Rubric Group Name 60 | * 61 | * @return text 62 | */ 63 | public function getRubricGroupName() { 64 | return $this->rubricgroupname; 65 | } 66 | 67 | /** 68 | * Set the Group Name for this Rubric 69 | * 70 | * @param text $rubricgroupname 71 | */ 72 | public function setRubricGroupName($rubricgroupname) { 73 | $this->rubricgroupname = $rubricgroupname; 74 | } 75 | } 76 | 77 | //?> -------------------------------------------------------------------------------- /settingslib.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * LDAP enrolment plugin admin setting classes 19 | * 20 | * @package mod_turnitintooltwo 21 | * @author John McGettrick 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die(); 26 | 27 | class admin_setting_configtext_int_only extends admin_setting_configtext { 28 | 29 | /** 30 | * Config text constructor 31 | * 32 | * @param string $name unique ascii name, 'mysetting' for settings in config, 'myplugin/mysetting' for config_plugins. 33 | * @param string $visiblename localised 34 | * @param string $description long localised info 35 | * @param string $defaultsetting 36 | * @param int $size default field size 37 | */ 38 | public function __construct($name, $visiblename, $description, $defaultsetting, $size=null) { 39 | $this->paramtype = PARAM_INT; 40 | $this->size = (!is_null($size)) ? $size : 30; 41 | 42 | admin_setting::__construct($name, $visiblename, $description, $defaultsetting); 43 | } 44 | 45 | public function write_setting($data) { 46 | $data = trim($data); 47 | $validated = $this->validate($data); 48 | if ($validated !== true) { 49 | return $validated; 50 | } 51 | return ($this->config_write($this->name, $data) ? '' : get_string('errorsetting', 'admin')); 52 | } 53 | 54 | public function validate($data) { 55 | global $PAGE; 56 | 57 | // Don't force the plugin to be fully set up when initializing PHPUNIT tests environment. 58 | if (defined('PHPUNIT_UTIL') && strlen($data) === 0) { 59 | return true; 60 | } 61 | 62 | // Don't force the plugin to be fully set up when installing. 63 | if ($PAGE->pagelayout === 'maintenance' && strlen($data) === 0) { 64 | return true; 65 | } 66 | return parent::validate($data); 67 | } 68 | } 69 | 70 | class admin_setting_config_tii_secret_key extends admin_setting_configpasswordunmask { 71 | 72 | /** 73 | * Validate data before storage 74 | * @param string data 75 | * @return mixed true if ok string if error found 76 | */ 77 | public function validate($data) { 78 | global $PAGE; 79 | 80 | // Don't force the plugin to be fully set up when initializing PHPUNIT tests environment. 81 | if (defined('PHPUNIT_UTIL') && strlen($data) === 0) { 82 | return true; 83 | } 84 | 85 | // Don't force the plugin to be fully set up when installing. 86 | if ($PAGE->pagelayout === 'maintenance' && strlen($data) === 0) { 87 | return true; 88 | } 89 | 90 | $cleaned = clean_param($data, $this->paramtype); 91 | if ("$data" === "$cleaned") { // Implicit conversion to string is needed to do exact comparison. 92 | return true; 93 | } else { 94 | return get_string('validateerror', 'admin'); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /templates/modal_migration_tool.mustache: -------------------------------------------------------------------------------- 1 | {{< core/modal }} 2 | {{$title}} 3 |
4 | {{# str }} migrationtooltitle, turnitintooltwo {{/ str }} 5 |
6 | {{/title}} 7 | {{$body}} 8 |
9 |

{{# str }} migrationtoolinfo, turnitintooltwo {{/ str }}

10 |
11 |
12 |

{{# str }} migrating, turnitintooltwo {{/ str }}

13 |
14 | 15 |
16 |

{{# str }} migrationredirect, turnitintooltwo {{/ str }}

17 |
18 | {{/body}} 19 | {{$footer}} 20 |
21 | 22 | 23 |
24 | {{/footer}} 25 | {{/ core/modal }} -------------------------------------------------------------------------------- /tests/unit/classes/digitalreceipt/instructor_message_test.php: -------------------------------------------------------------------------------- 1 | dirroot . '/mod/turnitintooltwo/classes/digitalreceipt/instructor_message.php'); 7 | 8 | /** 9 | * Tests for classes/digitalreceipt/instructor_message 10 | * 11 | * @package turnitintooltwo 12 | */ 13 | class mod_turnitintooltwo_instructor_message_testcase extends advanced_testcase { 14 | 15 | /** 16 | * Test data being passed in will generate the correct output text. 17 | */ 18 | public function test_build_instructor_message() { 19 | $instructormessage = new instructor_message(); 20 | 21 | $data = [ 22 | 'submission_title' => 'Foo', 23 | 'assignment_name' => 'Bar', 24 | 'course_fullname' => 'Foobar', 25 | 'submission_date' => '01-09-1994', 26 | 'submission_id' => '1234567' 27 | ]; 28 | 29 | $this->assertEquals( 30 | format_string('A submission entitled Foo has been made to assignment Bar in the class Foobar.

Submission ID: 1234567
Submission Date: 01-09-1994
'), 31 | $instructormessage->build_instructor_message($data) 32 | ); 33 | } 34 | 35 | /** 36 | * Test data being passed in will generate the correct output text, with assignment part. 37 | */ 38 | public function test_build_instructor_message_with_assignment_part() { 39 | $instructor_message = new instructor_message(); 40 | 41 | $data = [ 42 | 'submission_title' => 'Foo', 43 | 'assignment_name' => 'Bar', 44 | 'course_fullname' => 'Foobar', 45 | 'submission_date' => '01-09-1994', 46 | 'submission_id' => '1234567', 47 | 'assignment_part' => 'Part 2' 48 | ]; 49 | 50 | $this->assertEquals( 51 | format_string('A submission entitled Foo has been made to assignment Bar: Part 2 in the class Foobar.

Submission ID: 1234567
Submission Date: 01-09-1994
'), 52 | $instructor_message->build_instructor_message($data) 53 | ); 54 | } 55 | 56 | /** 57 | * Test that multiple messages get sent for instructors. 58 | */ 59 | public function test_send_instructor_message() { 60 | $this->resetAfterTest(); 61 | $this->preventResetByRollback(); 62 | 63 | $sink = $this->redirectMessages(); 64 | 65 | $instructormessage = new instructor_message(); 66 | 67 | // Generate two new users to send messages to. 68 | $user1 = $this->getDataGenerator()->create_user(); 69 | $user2 = $this->getDataGenerator()->create_user(); 70 | 71 | $instructors = [ 72 | $user1, 73 | $user2 74 | ]; 75 | 76 | // Send message to both instructors. 77 | $instructormessage->send_instructor_message($instructors, 'Instructor Message', 123); 78 | 79 | $messages = $sink->get_messages(); 80 | 81 | $this->assertEquals(2, count($messages)); 82 | $this->assertEquals('Instructor Message', $messages[0]->fullmessage); 83 | $this->assertEquals('Instructor Message', $messages[1]->fullmessage); 84 | 85 | $this->assertEquals($user1->id, $messages[0]->useridto); 86 | $this->assertEquals($user2->id, $messages[1]->useridto); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /tests/unit/classes/digitalreceipt/receipt_message_test.php: -------------------------------------------------------------------------------- 1 | dirroot . '/mod/turnitintooltwo/classes/digitalreceipt/receipt_message.php'); 11 | 12 | class mod_turnitintooltwo_receipt_message_testcase extends advanced_testcase { 13 | 14 | public function test_send_message() { 15 | global $DB; 16 | 17 | $this->resetAfterTest(); // Reset the DB when finished 18 | $this->preventResetByRollback(); // Messaging doesn't support rollback 19 | 20 | $sink = $this->redirectMessages(); // Collect the emails 21 | 22 | $userOne = $this->getDataGenerator()->create_user(); 23 | 24 | $receipt_message = new receipt_message(); 25 | 26 | $receipt_message->send_message($userOne, "Test message for email", 123); 27 | 28 | $this->assertEquals(1, $sink->count()); // One email sent 29 | 30 | $messages = $sink->get_messages(); 31 | 32 | // Correct user was sent an email 33 | $this->assertEquals($userOne->id, $messages[0]->useridto); 34 | $this->assertEquals("This is your Turnitin Digital Receipt", $messages[0]->subject); 35 | $this->assertEquals("Test message for email", $messages[0]->fullmessage); 36 | $this->assertEquals("Test message for email", $messages[0]->fullmessagehtml); 37 | $this->assertEquals(1, $messages[0]->fullmessageformat); // HTML format 38 | } 39 | 40 | public function test_build_message_single_part() { 41 | 42 | $receipt_message = new receipt_message(); 43 | 44 | $date = date('c'); 45 | 46 | $message = []; 47 | $message['firstname'] = 'test_user_firstname'; 48 | $message['lastname'] = 'test_user_lastname'; 49 | $message['submission_title'] = 'test submission title'; 50 | $message['assignment_name'] = 'test assignment name'; 51 | $message['course_fullname'] = 'test course name'; 52 | $message['submission_date'] = $date; 53 | $message['submission_id'] = '12345'; 54 | 55 | $response = $receipt_message->build_message($message); 56 | 57 | $message_text = format_string("Dear %s %s,

You have successfully submitted the file %s to the assignment %s in the class %s on %s. Your submission id is %s. Your full digital receipt can be viewed and printed from the assignment inbox or from the print/download button in the document viewer.

Thank you for using Turnitin,

The Turnitin Team"); 58 | 59 | $this->assertEquals(sprintf($message_text, $message['firstname'], $message['lastname'], $message['submission_title'], $message['assignment_name'], $message['course_fullname'], $date, $message['submission_id']) , $response); 60 | } 61 | 62 | public function test_build_message_multi_part() { 63 | $receipt_message = new receipt_message(); 64 | 65 | $date = date('c'); 66 | 67 | $message = []; 68 | $message['firstname'] = 'test_user_firstname'; 69 | $message['lastname'] = 'test_user_lastname'; 70 | $message['submission_title'] = 'test submission title'; 71 | $message['assignment_name'] = 'test assignment name'; 72 | $message['assignment_part'] = 'assignment_part'; 73 | $message['course_fullname'] = 'test course name'; 74 | $message['submission_date'] = $date; 75 | $message['submission_id'] = '12345'; 76 | 77 | $response = $receipt_message->build_message($message); 78 | 79 | $messagetext = format_string("Dear %s %s,

You have successfully submitted the file %s to the assignment %s: %s in the class %s on %s. Your submission id is %s. Your full digital receipt can be viewed and printed from the assignment inbox or from the print/download button in the document viewer.

Thank you for using Turnitin,

The Turnitin Team"); 80 | 81 | $this->assertEquals(sprintf($messagetext, $message['firstname'], $message['lastname'], 82 | $message['submission_title'], $message['assignment_name'], $message['assignment_part'], 83 | $message['course_fullname'], $date, $message['submission_id']), $response); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /tests/unit/classes/nonsubmitters/nonsubmitters_message_test.php: -------------------------------------------------------------------------------- 1 | dirroot . '/mod/turnitintooltwo/classes/nonsubmitters/nonsubmitters_message.php'); 7 | 8 | /** 9 | * Tests for classes/digitalreceipt/nonsubmitters_message 10 | * 11 | * @package turnitintooltwo 12 | */ 13 | class mod_turnitintooltwo_nonsubmitter_message_testcase extends advanced_testcase { 14 | 15 | /** 16 | * Test that non submitter messages send. 17 | */ 18 | public function test_send_instructor_message() { 19 | $this->resetAfterTest(); 20 | $this->preventResetByRollback(); 21 | 22 | $sink = $this->redirectMessages(); 23 | 24 | $nonsubmitters_message = new nonsubmitters_message(); 25 | 26 | // Generate two new users to send messages to. 27 | $user1 = $this->getDataGenerator()->create_user(); 28 | 29 | // Send message to both instructors. 30 | $nonsubmitters_message->send_message($user1->id, 'Nonsubmitters Subject', 'Nonsubmitters Message', 1); 31 | 32 | $messages = $sink->get_messages(); 33 | 34 | $this->assertEquals(1, count($messages)); 35 | $this->assertEquals('Nonsubmitters Subject', $messages[0]->subject); 36 | $this->assertEquals('Nonsubmitters Message', $messages[0]->fullmessage); 37 | $this->assertEquals($user1->id, $messages[0]->useridto); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/unit/classes/view/members_test.php: -------------------------------------------------------------------------------- 1 | dirroot . '/mod/turnitintooltwo/classes/view/members.php'); 7 | require_once($CFG->dirroot . '/mod/turnitintooltwo/turnitintooltwo_assignment.class.php'); 8 | require_once($CFG->dirroot . '/mod/turnitintooltwo/turnitintooltwo_view.class.php'); 9 | require_once($CFG->dirroot . '/webservice/tests/helpers.php'); 10 | require_once($CFG->dirroot . '/mod/lti/lib.php'); 11 | 12 | /** 13 | * Tests for classes/view/members 14 | * 15 | * @package turnitintooltwo 16 | */ 17 | class mod_turnitintooltwo_view_members_testcase extends advanced_testcase { 18 | /** 19 | * Test display role given returns as the expected Turnitin role 20 | */ 21 | public function test_get_role_for_display_role() { 22 | $members = new members_view(); 23 | 24 | $role = $members->get_role_for_display_role(null); 25 | $this->assertEquals('Learner', $role); 26 | 27 | $role = $members->get_role_for_display_role("tutors"); 28 | $this->assertEquals('Instructor', $role); 29 | 30 | $role = $members->get_role_for_display_role("students"); 31 | $this->assertEquals('Learner', $role); 32 | 33 | $role = $members->get_role_for_display_role("foobar"); 34 | $this->assertEquals('Learner', $role); 35 | } 36 | 37 | /** 38 | * Test given a role the correct intro message for the members view is 39 | * generated. 40 | */ 41 | public function test_build_intro_message() { 42 | $members = new members_view(); 43 | 44 | $actualmessage = $members->build_intro_message(); 45 | $expectedmessagetext = get_string('turnitinstudents_desc', 'turnitintooltwo'); 46 | 47 | $this->assertStringContainsString($expectedmessagetext, $actualmessage); 48 | 49 | $actualmessage = $members->build_intro_message("students"); 50 | $expectedmessagetext = get_string("turnitinstudents_desc", "turnitintooltwo"); 51 | 52 | $this->assertStringContainsString($expectedmessagetext, $actualmessage); 53 | 54 | $actualmessage = $members->build_intro_message("foobar"); 55 | $expectedmessagetext = get_string("turnitinstudents_desc", "turnitintooltwo"); 56 | 57 | $this->assertStringContainsString($expectedmessagetext, $actualmessage); 58 | 59 | $actualmessage = $members->build_intro_message("tutors"); 60 | $expectedmessagetext = get_string("turnitintutors_desc", "turnitintooltwo"); 61 | 62 | $this->assertStringContainsString($expectedmessagetext, $actualmessage); 63 | } 64 | 65 | /** 66 | * Test given a display role the correct table HTML is generated 67 | */ 68 | public function test_build_members_table() { 69 | // fake/stub a turnitin two view class and the method to render the 70 | // table 71 | $observer = $this->getMockBuilder(turnitintooltwo_view::class) 72 | ->setMethods(['init_tii_member_by_role_table']) 73 | ->getMock(); 74 | 75 | // add assertions to the turnitin two view class method that renders the 76 | // members table is called with the expected arguments 77 | $observer->expects($this->exactly(4)) 78 | ->method('init_tii_member_by_role_table') 79 | ->willReturn('fake table!
') 80 | ->withConsecutive( 81 | [$this->equalTo('fakemodule'), $this->equalTo('faketiiassignment'), $this->equalTo('Learner')], 82 | [$this->equalTo('fakemodule'), $this->equalTo('faketiiassignment'), $this->equalTo('Instructor')], 83 | [$this->equalTo('fakemodule'), $this->equalTo('faketiiassignment'), $this->equalTo('Learner')], 84 | [$this->equalTo('fakemodule'), $this->equalTo('faketiiassignment'), $this->equalTo('Learner')] 85 | ); 86 | 87 | // create out members view instance passing our stubbed turnitin two 88 | // view class instance 89 | $members = new members_view('fakecourse', 'fakemodule', $observer, 'faketiiassignment'); 90 | 91 | // check with valid Learner role 92 | $table = $members->build_members_table('students'); 93 | $this->assertEquals('fake table!
', $table); 94 | 95 | // check with valid Instructor role 96 | $table = $members->build_members_table('tutors'); 97 | $this->assertEquals('fake table!
', $table); 98 | 99 | // check no role falls back to Learner 100 | $table = $members->build_members_table(); 101 | $this->assertEquals('fake table!
', $table); 102 | 103 | // check invalid role falls back to Learner 104 | $table = $members->build_members_table('foobar'); 105 | $this->assertEquals('fake table!
', $table); 106 | } 107 | 108 | /** 109 | * Test given a display role the correct add tutors form is generated. 110 | */ 111 | public function test_build_add_tutors_form() { 112 | // fake/stub a turnitin two view class and method to render the add 113 | // tutors form 114 | $faketiiview = $this->getMockBuilder(turnitintooltwo_view::class) 115 | ->setMethods(['show_add_tii_tutors_form']) 116 | ->getMock(); 117 | 118 | // add assertions that the generate add tutors form is called as 119 | // expected 120 | $faketiiview->expects($this->once()) 121 | ->method('show_add_tii_tutors_form') 122 | ->willReturn('
fake form!
') 123 | ->withConsecutive( 124 | [$this->equalTo('fakemodule'), $this->equalTo('faketutors')] 125 | ); 126 | 127 | // fake/stub a fake tii assignment 128 | $faketiiassignment = $this->getMockBuilder(turnitintooltwo_assignment::class) 129 | ->disableOriginalConstructor() 130 | ->setMethods(['get_tii_users_by_role']) 131 | ->getMock(); 132 | 133 | // make assignment get users by role to always return something, we 134 | // check that our tii two view stub gets called with the result of this 135 | // stub. 136 | $faketiiassignment->expects($this->once()) 137 | ->method('get_tii_users_by_role') 138 | ->willReturn('faketutors'); 139 | 140 | // create our members view class instance with the fake tii view and 141 | // assignment 142 | $members = new members_view(null, 'fakemodule', $faketiiview, $faketiiassignment); 143 | 144 | // test when not displaying tutor members 145 | $form = $members->build_add_tutors_form("foobar"); 146 | $this->assertEquals('', $form); 147 | 148 | // test when displaying tutor members 149 | $form = $members->build_add_tutors_form("tutors"); 150 | $this->assertEquals('
fake form!
', $form); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /tests/unit/mod_form_test.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Unit tests for (some of) turnitintooltwo/mod_form.php. 19 | * 20 | * @package turnitintooltwo 21 | * @copyright 2018 Turnitin 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | global $CFG; 26 | 27 | require_once($CFG->dirroot . '/mod/turnitintooltwo/mod_form.php'); 28 | 29 | class mod_form_test extends advanced_testcase { 30 | 31 | /** 32 | * Test that when current has a submitpapers the submitpapers from the config is not used. 33 | * I.E. instructor default overrides the system default 34 | */ 35 | public function test_should_populate_submitpapersto_to_the_value_in_current_when_submitpapersto_not_null() { 36 | $this->resetAfterTest(); 37 | 38 | $current = new stdClass(); 39 | $current->submitpapersto = 1; 40 | 41 | // Test that System Default is not applied 42 | set_config('default_submitpapersto', 0, 'turnitintooltwo'); 43 | 44 | $current = mod_turnitintooltwo_mod_form::populate_submitpapersto($current); 45 | 46 | $this->assertEquals($current->submitpapersto, 1); 47 | } 48 | 49 | /** 50 | * Test that when current does not have a submitpapers the submitpapers from the config is used. 51 | * I.E. when there is no instructor default the system default is used 52 | */ 53 | public function test_should_populate_submitpapersto_to_the_value_in_config_when_submitpapersto_null() { 54 | $this->resetAfterTest(); 55 | 56 | $current = new stdClass(); 57 | $current->submitpapersto = null; 58 | 59 | // Test that System Default is not applied 60 | set_config('default_submitpapersto', 0, 'turnitintooltwo'); 61 | 62 | $current = mod_turnitintooltwo_mod_form::populate_submitpapersto($current); 63 | 64 | $this->assertEquals($current->submitpapersto, 0); 65 | } 66 | } -------------------------------------------------------------------------------- /tests/unit/turnitintooltwo_assignment_test.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Unit tests for (some of) mod/turnitintooltwo/view.php. 19 | * 20 | * @package mod_turnitintooltwo 21 | * @copyright 2017 Turnitin 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die(); 26 | 27 | global $CFG; 28 | require_once($CFG->dirroot . '/mod/turnitintooltwo/turnitintooltwo_assignment.class.php'); 29 | 30 | /** 31 | * Tests for inbox 32 | * 33 | * @package turnitintooltwo 34 | */ 35 | class mod_turnitintooltwo_assignment_testcase extends advanced_testcase { 36 | 37 | /** 38 | * Test that the title is truncated to the passed in limit. 39 | */ 40 | public function test_truncate_title() { 41 | $turnitintooltwo = new stdClass(); 42 | $turnitintooltwo->id = 1; 43 | 44 | $turnitintooltwoassignment = new turnitintooltwo_assignment(0, $turnitintooltwo); 45 | 46 | // Test that a string under the limit is returned with a suffix added. 47 | $originaltitle = 'Test String'; 48 | $expectedtitle = 'Test String (Moodle TT)'; 49 | $limit = 100; 50 | $title = $turnitintooltwoassignment->truncate_title($originaltitle, $limit, 'TT'); 51 | $this->assertEquals($expectedtitle, $title); 52 | $this->assertLessThan($limit, strlen($title)); 53 | 54 | // Test that a string over the limit is returned truncated with a suffix added and is equal to the limit in length. 55 | $originaltitle = 'Test String is truncated and has a suffix added on the end with brackets showing the moodle coursetype'; 56 | $limit = 30; 57 | $title = $turnitintooltwoassignment->truncate_title($originaltitle, $limit, 'TT'); 58 | $this->assertStringContainsString('Test String', $title); 59 | $this->assertStringNotContainsString('added on the end', $title); 60 | $this->assertStringContainsString('... (Moodle TT)', $title); 61 | $this->assertEquals($limit, strlen($title)); 62 | } 63 | 64 | /** 65 | * Test that a checkbox field is initialised and not overwritten if already set. 66 | */ 67 | public function test_set_checkbox_field() { 68 | $turnitintooltwo = new stdClass(); 69 | $turnitintooltwo->id = 1; 70 | 71 | $turnitintooltwoassignment = new turnitintooltwo_assignment(0, $turnitintooltwo); 72 | $turnitintooltwoassignment->set_checkbox_field('testvar1'); 73 | 74 | // Verify that checkbox fields are set to 0 by default. 75 | $this->assertEquals(0, $turnitintooltwoassignment->turnitintooltwo->testvar1); 76 | 77 | // Verify that checkbox fields are set to passed in value. 78 | $value = 20; 79 | $turnitintooltwoassignment->set_checkbox_field('testvar2', $value); 80 | $this->assertEquals($value, $turnitintooltwoassignment->turnitintooltwo->testvar2); 81 | 82 | // Set checkbox fields. 83 | $turnitintooltwoassignment->turnitintooltwo->testvar1 = 1; 84 | 85 | // Verify that checkbox fields aren't changed as they are already set. 86 | $turnitintooltwoassignment->set_checkbox_field('testvar1'); 87 | $this->assertEquals(1, $turnitintooltwoassignment->turnitintooltwo->testvar1); 88 | } 89 | 90 | /** 91 | * Test that the course returned is the one we expect. 92 | */ 93 | public function test_course_data() { 94 | global $DB; 95 | 96 | $this->resetAfterTest(); 97 | 98 | $turnitintooltwo = new stdClass(); 99 | $turnitintooltwo->id = 1; 100 | 101 | $turnitintooltwoassignment = new turnitintooltwo_assignment(0, $turnitintooltwo); 102 | 103 | // Create a V2 course. 104 | $course = new stdClass(); 105 | $course->courseid = 1; 106 | $course->ownerid = 1; 107 | $course->turnitin_ctl = "Test Course"; 108 | $course->turnitin_cid = 10; 109 | $course->course_type = "TT"; 110 | 111 | // Insert the course to the turnitintooltwo courses table. 112 | $DB->insert_record('turnitintooltwo_courses', $course); 113 | 114 | // Test that we return the correct course when calling get_course_data with course type TT. 115 | $response = $turnitintooltwoassignment->get_course_data(1, "TT"); 116 | $this->assertEquals(10, $response->turnitin_cid); 117 | $this->assertEquals("TT", $response->course_type); 118 | 119 | // Insert a new V2 course. 120 | $course->turnitin_cid = 20; 121 | $course->course_type = "V1"; 122 | $DB->insert_record('turnitintooltwo_courses', $course); 123 | 124 | // Test course type V1 125 | $response = $turnitintooltwoassignment->get_course_data(1, "V1"); 126 | $this->assertEquals(20, $response->turnitin_cid); 127 | $this->assertEquals("V1", $response->course_type); 128 | } 129 | } -------------------------------------------------------------------------------- /tests/unit/turnitintooltwo_comms_test.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Unit tests for (some of) mod/turnitintooltwo/view.php. 19 | * 20 | * @package mod_turnitintooltwo 21 | * @copyright 2017 Turnitin 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die(); 26 | 27 | global $CFG; 28 | require_once($CFG->dirroot . '/mod/turnitintooltwo/turnitintooltwo_comms.class.php'); 29 | 30 | /** 31 | * Tests for API comms class 32 | * 33 | * @package turnitintooltwo 34 | */ 35 | class mod_turnitintooltwo_comms_testcase extends advanced_testcase { 36 | 37 | public function test_handle_exceptions() { 38 | global $CFG; 39 | 40 | $this->resetAfterTest(); 41 | 42 | // Set Turnitin account values in config as they are used in comms. 43 | set_config('apiurl', 'http://invalid', 'turnitintooltwo'); 44 | set_config('accountid', '1001', 'turnitintooltwo'); 45 | set_config('secretkey', 'ABCDEFGH', 'turnitintooltwo'); 46 | 47 | // Throw fake exception. 48 | try { 49 | throw new Exception("Throw a fake exception for testing."); 50 | } catch(Exception $e) { 51 | } 52 | 53 | $turnitintooltwocomms = new turnitintooltwo_comms(); 54 | // Check error string with debugging set to developer level. 55 | $CFG->debug = DEBUG_DEVELOPER; 56 | $errorstring = $turnitintooltwocomms->handle_exceptions($e, "", false, true); 57 | 58 | // Error string should contain the file, line and the message. 59 | if (is_callable(array($e, 'getFile'))) { 60 | $this->assertStringContainsString($e->getFile(), $errorstring); 61 | } 62 | if (is_callable(array($e, 'getLine'))) { 63 | $this->assertStringContainsString((string)$e->getLine(), $errorstring); 64 | } 65 | if (is_callable(array($e, 'getMessage'))) { 66 | $this->assertStringContainsString($e->getMessage(), $errorstring); 67 | } 68 | 69 | // Check error string with debugging set to normal level. 70 | $CFG->debug = DEBUG_NONE; 71 | $errorstring = $turnitintooltwocomms->handle_exceptions($e, "", false, true); 72 | 73 | // Error string should not contain the file and line, only the message. 74 | if (is_callable(array($e, 'getFile'))) { 75 | $this->assertStringNotContainsString($e->getFile(), $errorstring); 76 | } 77 | if (is_callable(array($e, 'getLine'))) { 78 | $this->assertStringNotContainsString((string)$e->getLine(), $errorstring); 79 | } 80 | if (is_callable(array($e, 'getMessage'))) { 81 | $this->assertStringContainsString($e->getMessage(), $errorstring); 82 | } 83 | } 84 | 85 | } -------------------------------------------------------------------------------- /tests/unit/turnitintooltwo_submission_test.php: -------------------------------------------------------------------------------- 1 | dirroot . '/mod/turnitintooltwo/turnitintooltwo_assignment.class.php'); 9 | require_once($CFG->dirroot . '/mod/turnitintooltwo/turnitintooltwo_submission.class.php'); 10 | require_once($CFG->dirroot . '/webservice/tests/helpers.php'); 11 | require_once($CFG->dirroot . '/mod/lti/lib.php'); 12 | require_once($CFG->dirroot . '/course/lib.php'); 13 | 14 | /** 15 | * Tests for classes/view/members 16 | * 17 | * @package turnitintooltwo 18 | */ 19 | class mod_turnitintooltwo_submission_testcase extends advanced_testcase { 20 | /** 21 | * Test create submission function returns the expected bollean given a data array. 22 | */ 23 | public function test_create_submission() { 24 | global $DB; 25 | 26 | $this->resetAfterTest(); 27 | 28 | $turnitintooltwo = new stdClass(); 29 | $turnitintooltwo->id = 1; 30 | 31 | $turnitintooltwoassignment = new turnitintooltwo_assignment(0, $turnitintooltwo); 32 | 33 | $submission = new turnitintooltwo_submission(0, "moodle", $turnitintooltwoassignment, 1); 34 | 35 | $data = array(); 36 | $data['submissiontype'] = 1; 37 | $data['submissiontext'] = "Submission text"; 38 | $data['submissiontitle'] = "Submission title"; 39 | $data['studentsname'] = 1; 40 | $data['submissionpart'] = 1; 41 | $data['submissionagreement'] = 1; 42 | 43 | $response = $submission->create_submission($data); 44 | 45 | $this->assertEquals($response, true); 46 | 47 | /** 48 | * Test where create_submissions is false. 49 | * First we stub the class, 50 | * Then we stub the method insert_submission() to always return false. 51 | * Then we call our stubbed class with the method we want to test. 52 | */ 53 | // Create a stub 54 | $stub = $this->getMockBuilder('turnitintooltwo_submission') 55 | ->getMock(); 56 | 57 | // Configure the stub. 58 | $stub->method('insert_submission') 59 | ->willReturn(false); 60 | 61 | $response = $stub->create_submission($data); 62 | 63 | $this->assertEquals($response, false); 64 | } 65 | 66 | /** 67 | * Test create submission function returns the expected bollean given a data array. 68 | */ 69 | public function test_insert_submission() { 70 | global $DB; 71 | 72 | $this->resetAfterTest(); 73 | 74 | $turnitintooltwo = new stdClass(); 75 | $turnitintooltwo->id = 1; 76 | 77 | $turnitintooltwoassignment = new turnitintooltwo_assignment(0, $turnitintooltwo); 78 | 79 | $submission = new turnitintooltwo_submission(0, "moodle", $turnitintooltwoassignment, 1); 80 | 81 | $data = new stdClass(); 82 | $data->userid = 1; 83 | $data->turnitintooltwoid = 1; 84 | $data->submission_part = 1; 85 | $data->submission_title = "Submission title"; 86 | $data->submission_type = 1; 87 | $data->submission_objectid = null; 88 | $data->submission_unanon = 0; 89 | $data->submission_grade = null; 90 | $data->submission_gmimaged = 0; 91 | $data->submission_hash = $data->userid.'_'.$data->turnitintooltwoid.'_'.$data->submission_part; 92 | 93 | $response = $submission->insert_submission($data); 94 | $this->assertEquals($response, true); 95 | 96 | $response = $submission->insert_submission(""); 97 | $this->assertEquals($response, false); 98 | } 99 | 100 | public function test_count_graded_submissions() { 101 | global $DB; 102 | 103 | $this->resetAfterTest(); 104 | 105 | $turnitintooltwo = new stdClass(); 106 | $turnitintooltwo->id = 1; 107 | 108 | $turnitintooltwoassignment = new turnitintooltwo_assignment(0, $turnitintooltwo); 109 | 110 | $submission = new turnitintooltwo_submission(0, "moodle", $turnitintooltwoassignment, 1); 111 | 112 | $data = new stdClass(); 113 | $data->userid = 1; 114 | $data->turnitintooltwoid = $turnitintooltwo->id; 115 | $data->submission_part = 1; 116 | $data->submission_title = "Submission title"; 117 | $data->submission_type = 1; 118 | $data->submission_objectid = null; 119 | $data->submission_unanon = 0; 120 | $data->submission_grade = 75; 121 | $data->submission_gmimaged = 0; 122 | $data->submission_hash = $data->userid.'_'.$data->turnitintooltwoid.'_'.$data->submission_part; 123 | 124 | $response = $submission->insert_submission($data); 125 | $count = $submission->count_graded_submissions($turnitintooltwo->id); 126 | 127 | $this->assertEquals($count, 1); 128 | 129 | // Testing when there is no grades 130 | $submissionrecord = $DB->get_record('turnitintooltwo_submissions', array('turnitintooltwoid' => $turnitintooltwo->id)); 131 | $DB->update_record('turnitintooltwo_submissions', array('id' => $submissionrecord->id, 'submission_grade' => 0)); 132 | 133 | $count = $submission->count_graded_submissions($turnitintooltwo->id); 134 | 135 | $this->assertEquals($count, 0); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /turnitintooltwo_class.class.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * @package turnitintooltwo 19 | * @copyright 2012 iParadigms LLC * 20 | */ 21 | 22 | defined('MOODLE_INTERNAL') || die(); 23 | 24 | require_once(__DIR__.'/turnitintooltwo_comms.class.php'); 25 | 26 | class turnitintooltwo_class { 27 | 28 | private $id; 29 | private $turnitinid; 30 | private $title; 31 | private $turnitintitle; 32 | public $sharedrubrics; 33 | 34 | public function __construct($id) { 35 | global $DB; 36 | 37 | $this->id = $id; 38 | 39 | if ($turnitincourse = $DB->get_record('turnitintooltwo_courses', 40 | array("courseid" => $id, "course_type" => "TT"))) { 41 | $this->turnitinid = $turnitincourse->turnitin_cid; 42 | $this->turnitintitle = $turnitincourse->turnitin_ctl; 43 | } 44 | } 45 | 46 | /** 47 | * Update class from Turnitin, mainly to get shared rubrics 48 | * 49 | * @return void 50 | */ 51 | public function read_class_from_tii() { 52 | // Initialise Comms Object. 53 | $turnitincomms = new turnitintooltwo_comms(); 54 | $turnitincall = $turnitincomms->initialise_api(); 55 | 56 | $tiiclass = new TiiClass(); 57 | 58 | try { 59 | $tiiclass->setClassId($this->turnitinid); 60 | $response = $turnitincall->readClass($tiiclass); 61 | $readclass = $response->getClass(); 62 | 63 | $rubrics = $readclass->getSharedRubrics(); 64 | $rubricarray = array(); 65 | foreach ($rubrics as $rubric) { 66 | $rubricarray[$rubric->getRubricGroupName()][$rubric->getRubricId()] = $rubric->getRubricName(); 67 | } 68 | 69 | $this->sharedrubrics = $rubricarray; 70 | 71 | } catch (Exception $e) { 72 | $turnitincomms->handle_exceptions($e, 'coursegeterror', false); 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /turnitintooltwo_form.class.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * @package turnitintooltwo 19 | * @copyright 2012 iParadigms LLC 20 | */ 21 | 22 | defined('MOODLE_INTERNAL') || die(); 23 | 24 | require_once($CFG->libdir."/formslib.php"); 25 | 26 | class turnitintooltwo_form extends moodleform { 27 | 28 | /** 29 | * The form definition contains a customdata array. This contains all the elements as an array, 30 | * each element is passed with data in the following format: 31 | * array(type e.g. "text", id/name of element, label string, string identifier for help text, 32 | * options (e.g. for select, advcheckbox or file upload), rule, rule error msg, param_type, 33 | * array for disabled if rule (dependent field, condition, value) 34 | * 35 | * @global type $CFG 36 | */ 37 | public function definition() { 38 | $mform =& $this->_form; 39 | 40 | foreach ($this->_customdata["elements"] as $element) { 41 | switch ($element[0]) { 42 | case "static": 43 | case "select": 44 | case "date_time_selector": 45 | case "date_selector": 46 | $mform->addElement($element[0], $element[1], $element[2], $element[4]); 47 | break; 48 | case "filemanager": 49 | $mform->addElement($element[0], $element[1], $element[2], '', $element[4]); 50 | break; 51 | case "html": 52 | $mform->addElement($element[0], $element[1]); 53 | break; 54 | case "advcheckbox": 55 | $labelbefore = $element[2]; 56 | $labelafter = null; 57 | if (!empty($this->_customdata["checkbox_label_after"])) { 58 | $labelbefore = null; 59 | $labelafter = $element[2]; 60 | } 61 | $mform->addElement($element[0], $element[1], $labelbefore, $labelafter, null, $element[4]); 62 | break; 63 | case "hidden": 64 | case "text": 65 | $mform->addElement($element[0], $element[1], $element[2]); 66 | $mform->setType($element[1], PARAM_RAW); 67 | break; 68 | default: 69 | $mform->addElement($element[0], $element[1], $element[2]); 70 | break; 71 | } 72 | 73 | // Set form data. Only used for submission form. 74 | if (isset($_SESSION['form_data']->{$element[1]})) { 75 | $mform->setDefault($element[1], $_SESSION['form_data']->{$element[1]}); 76 | } 77 | 78 | if (!empty($element[3])) { 79 | $mform->addHelpButton($element[1], $element[3], 'turnitintooltwo'); 80 | } 81 | 82 | if (!empty($element[5])) { 83 | $mform->setType($element[1], PARAM_TEXT); 84 | $mform->addRule($element[1], $element[6], $element[5], null, 'client'); 85 | } 86 | 87 | if (!empty($element[7])) { 88 | $disabledif = $element[7]; 89 | $mform->disabledIf($element[1], $disabledif[0], $disabledif[1], $disabledif[2]); 90 | } 91 | } 92 | 93 | // Apply a class to the form if specified. 94 | if (isset($this->_customdata["class"])) { 95 | $mform->_formname = $this->_customdata["class"]; 96 | } 97 | 98 | // Show the moodleform standard submit and cancel buttons. 99 | if (!isset($this->_customdata["hide_submit"])) { 100 | $submitlabel = null; 101 | if (isset($this->_customdata["submit_label"])) { 102 | $submitlabel = $this->_customdata["submit_label"]; 103 | } 104 | if (!isset($this->_customdata["show_cancel"])) { 105 | $this->_customdata["show_cancel"] = "true"; 106 | } 107 | 108 | $this->add_action_buttons($this->_customdata["show_cancel"], $submitlabel); 109 | } 110 | 111 | // Disable the form change checker - added in 2.3.2. 112 | if (is_callable(array($mform, 'disable_form_change_checker'))) { 113 | if (isset($this->_customdata["disable_form_change_checker"])) { 114 | $mform->disable_form_change_checker(); 115 | } 116 | } 117 | 118 | // Show multiple submit buttons if needed. 119 | if (isset($this->_customdata["multi_submit_buttons"])) { 120 | $buttonarray = array(); 121 | foreach ($this->_customdata["multi_submit_buttons"] as $btn) { 122 | $buttonarray[] = &$mform->createElement('submit', $btn[0], $btn[1]); 123 | } 124 | 125 | $mform->addGroup($buttonarray, 'buttonar', '', array(' '), false); 126 | } 127 | } 128 | 129 | /** 130 | * Display the form, saving the contents of the output buffer overiding Moodle's 131 | * display function that prints to screen when called 132 | * 133 | * @return the form as an object to print to screen at our convenience 134 | */ 135 | public function display() { 136 | ob_start(); 137 | parent::display(); 138 | $form = ob_get_contents(); 139 | ob_end_clean(); 140 | 141 | return $form; 142 | } 143 | } 144 | 145 | class turnitin_plagiarism_plugin_form extends moodleform { 146 | 147 | // Define the form. 148 | public function definition () { 149 | global $CFG; 150 | 151 | $mform =& $this->_form; 152 | 153 | require_once($CFG->dirroot.'/plagiarism/turnitin/turnitinplugin_view.class.php'); 154 | 155 | $turnitinpluginview = new turnitinplugin_view(); 156 | $turnitinpluginview->add_elements_to_settings_form($mform, array(), "defaults"); 157 | 158 | $this->add_action_buttons(true); 159 | } 160 | } -------------------------------------------------------------------------------- /turnitintooltwo_perflog.class.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | defined('MOODLE_INTERNAL') || die(); 18 | 19 | require_once(__DIR__.'/sdk/perflog.class.php'); 20 | require_once(__DIR__.'/lib.php'); 21 | 22 | class turnitintooltwo_performancelog extends PerformanceLog { 23 | 24 | /** 25 | * Log networking performance details of an individual request 26 | * 27 | * @param resource $ch The cURL handle corresponding to the request to log 28 | * @param float $totalresponsetime Total time taken for the request in seconds 29 | */ 30 | protected function log($ch, $totalresponsetime) { 31 | global $CFG, $USER, $action; 32 | 33 | static $config; 34 | if (empty($config)) { 35 | $config = turnitintooltwo_admin_config(); 36 | } 37 | 38 | if ($config->enableperformancelogs) { 39 | // We only keep 10 log files, delete any additional files. 40 | $prefix = "perflog_"; 41 | 42 | $dirpath = $CFG->tempdir."/turnitintooltwo/logs"; 43 | if (!file_exists($dirpath)) { 44 | mkdir($dirpath, 0777, true); 45 | } 46 | $dir = opendir($dirpath); 47 | $files = array(); 48 | while ($entry = readdir($dir)) { 49 | if (substr(basename($entry), 0, 1) != "." AND substr_count(basename($entry), $prefix) > 0) { 50 | $files[] = basename($entry); 51 | } 52 | } 53 | sort($files); 54 | for ($i = 0; $i < count($files) - 10; $i++) { 55 | unlink($dirpath."/".$files[$i]); 56 | } 57 | 58 | // Prepare string. 59 | $str = ''; 60 | if (!empty($action)) { 61 | $str .= " - $action"; 62 | } else { 63 | $do = (!empty($_REQUEST['do'])) ? $_REQUEST['do'] : ''; 64 | if (!empty($do)) { 65 | $str .= " - {$do}"; 66 | } 67 | } 68 | $httpstatus = curl_getinfo($ch, CURLINFO_HTTP_CODE); 69 | $str .= " - HTTP:" . $httpstatus; 70 | if ($httpstatus === 0 && curl_getinfo($ch, CURLINFO_SIZE_UPLOAD) === 0) { 71 | // CURLINFO_CONNECT_TIME is not reliable when the request fails to connect. 72 | $connecttime = $totalresponsetime; 73 | } else { 74 | $connecttime = curl_getinfo($ch, CURLINFO_CONNECT_TIME); 75 | } 76 | $str .= " - connect:" . sprintf('%0.3f', $connecttime); 77 | $str .= " - total:" . sprintf('%0.3f', $totalresponsetime); 78 | $str .= " - up:" . curl_getinfo($ch, CURLINFO_SIZE_UPLOAD); 79 | $str .= " - down:" . curl_getinfo($ch, CURLINFO_SIZE_DOWNLOAD); 80 | $str .= " - userid:" . $USER->id; 81 | if (array_key_exists('REQUEST_URI', $_SERVER)) { 82 | $str .= " - " . $_SERVER['REQUEST_URI']; 83 | } 84 | 85 | if ($httpstatus === 0) { 86 | $str .= " - " . curl_error($ch); 87 | } 88 | 89 | // Write to log file. 90 | $filepath = $dirpath."/".$prefix.gmdate('Y-m-d', time()).".txt"; 91 | $file = fopen($filepath, 'a'); 92 | $output = date('Y-m-d H:i:s O') . $str . "\r\n"; 93 | fwrite($file, $output); 94 | fclose($file); 95 | } 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * @package turnitintooltwo 19 | * @copyright 2012 iParadigms LLC 20 | */ 21 | 22 | defined('MOODLE_INTERNAL') || die(); 23 | 24 | if (empty($plugin)) { 25 | $plugin = new StdClass(); 26 | } 27 | 28 | $plugin->version = 2025072901; 29 | $plugin->release = "4.1+"; 30 | $plugin->requires = 2022112800; // Require Moodle 4.1.0+ 31 | $plugin->component = 'mod_turnitintooltwo'; 32 | $plugin->maturity = MATURITY_STABLE; 33 | 34 | global $CFG; 35 | $plugin->cron = 0; 36 | if (!empty($CFG->version)) { 37 | $plugin->cron = ($CFG->version > 2014051200) ? 0 : 1800; 38 | } 39 | --------------------------------------------------------------------------------