From 2645acd82770f7e919afc6a3c3e0787d3e49e20a Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Mon, 6 Jul 2015 20:09:47 -0700 Subject: [PATCH 001/119] First stab at custom fields - model side only, to start --- ...7_04_212443_create_custom_fields_table.php | 35 ++++++++ app/helpers.php | 26 +++--- app/models/CustomField.php | 80 +++++++++++++++++++ app/models/CustomFieldset.php | 10 +++ app/models/Elegant.php | 3 + app/models/Model.php | 9 +++ app/tests/CustomFieldTest.php | 78 ++++++++++++++++++ app/validators.php | 5 ++ docker/develop.sh | 5 +- 9 files changed, 239 insertions(+), 12 deletions(-) create mode 100644 app/database/migrations/2015_07_04_212443_create_custom_fields_table.php create mode 100644 app/models/CustomField.php create mode 100644 app/models/CustomFieldset.php create mode 100644 app/tests/CustomFieldTest.php diff --git a/app/database/migrations/2015_07_04_212443_create_custom_fields_table.php b/app/database/migrations/2015_07_04_212443_create_custom_fields_table.php new file mode 100644 index 0000000000..05bf670adb --- /dev/null +++ b/app/database/migrations/2015_07_04_212443_create_custom_fields_table.php @@ -0,0 +1,35 @@ +string('name'); + $table->string('format'); + $table->string('element'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + Schema::drop('custom_fields'); + } + +} diff --git a/app/helpers.php b/app/helpers.php index e6586c20ee..0dafa977e5 100755 --- a/app/helpers.php +++ b/app/helpers.php @@ -5,14 +5,18 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -function ParseFloat($floatString){ - - // use comma for thousands until local info is property used - $LocaleInfo = localeconv(); - //$thousands = isset($LocaleInfo["mon_thousands_sep"]) ? $LocaleInfo["mon_thousands_sep"] : ","; - //$floatString = str_replace($LocaleInfo["mon_thousands_sep"] , "", $floatString); - //$floatString = str_replace($LocaleInfo["decimal_point"] , ".", $floatString); - $floatString = str_replace("," , "", $floatString); - $floatString = str_replace($LocaleInfo["decimal_point"] , ".", $floatString); - return floatval($floatString); -} \ No newline at end of file + +if(!function_exists("ParseFloat")) { + //this may be only necessary to run tests? + function ParseFloat($floatString){ + + // use comma for thousands until local info is property used + $LocaleInfo = localeconv(); + //$thousands = isset($LocaleInfo["mon_thousands_sep"]) ? $LocaleInfo["mon_thousands_sep"] : ","; + //$floatString = str_replace($LocaleInfo["mon_thousands_sep"] , "", $floatString); + //$floatString = str_replace($LocaleInfo["decimal_point"] , ".", $floatString); + $floatString = str_replace("," , "", $floatString); + $floatString = str_replace($LocaleInfo["decimal_point"] , ".", $floatString); + return floatval($floatString); + } +} diff --git a/app/models/CustomField.php b/app/models/CustomField.php new file mode 100644 index 0000000000..1649a171b0 --- /dev/null +++ b/app/models/CustomField.php @@ -0,0 +1,80 @@ + "[a-zA-Z]*", + "NUMERIC" => "[0-9]*", + "MAC" => "[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}", + "IP" => "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])" + ]; + + public static function saving($custom_field) { + //print(" SAVING CALLBACK FIRING!!!!! "); + if($custom_field->isDirty("name")) { + //print("DIRTINESS DETECTED!"); + //$fields=array_keys($custom_field->getAttributes()); + ; + //add timestamp fields, add id column + //array_push($fields,$custom_field->getKeyName()); + /*if($custom_field::timestamps) { + + }*/ + //print("Fields are: ".print_r($fields,true)); + if(in_array($custom_field->db_column_name(),Schema::getColumnListing('assets'))) { + return false; + } + } + return true; + } + + /*public static function boot() { + parent::boot(); + + self::saving(function ($data) { + print("DOES THIS AT LEAST CATCH IT?!"); + self::check_db_name($data); + }); + }*/ + + public function fieldset() { + return $this->hasMany('CustomFieldset'); //?!?!?!?!?!? + } + + public $rules=[ + 'name' => 'unique_column' + ]; + + //public function + + //need helper to go from regex->English + //need helper to go from English->regex + + //need helper for save() stuff - basically to alter table for the fields in question + + public function check_format($value) { + return preg_match('/^'.$this->attributes['format'].'$/',$value)===1; + } + + public function db_column_name() { + return preg_replace("/\s/","_",strtolower($this->name)); + } + + //mutators for 'format' attribute + public function getFormatAttribute($value) { + foreach(self::$PredefinedFormats AS $name => $pattern) { + if($pattern===$value) { + return $name; + } + } + return $value; + } + + public function setFormatAttribute($value) { + if(self::$PredefinedFormats[$value]) { + $this->attributes['format']=self::$PredefinedFormats[$value]; + } else { + $this->attributes['format']=$value; + } + } +} diff --git a/app/models/CustomFieldset.php b/app/models/CustomFieldset.php new file mode 100644 index 0000000000..957d8353cc --- /dev/null +++ b/app/models/CustomFieldset.php @@ -0,0 +1,10 @@ +hasMany('CustomField'); + } + + //requiredness goes *here* + //sequence goes here? +} diff --git a/app/models/Elegant.php b/app/models/Elegant.php index c2f0ddd77e..da85848ff7 100755 --- a/app/models/Elegant.php +++ b/app/models/Elegant.php @@ -1,5 +1,8 @@ belongsTo('Manufacturer','manufacturer_id'); } + + public function custom_fieldset() + { + $foo=new CustomField(); + $foo2=new CustomFieldset(); + return $this->belongsTo('CustomFieldset','custom_fieldset_id'); + } /** * ----------------------------------------------- diff --git a/app/tests/CustomFieldTest.php b/app/tests/CustomFieldTest.php new file mode 100644 index 0000000000..e3090ac7bb --- /dev/null +++ b/app/tests/CustomFieldTest.php @@ -0,0 +1,78 @@ +name="test 1"; + $f->format="IP"; + $f->element="text"; + + $f->save(); + + $this->assertFalse($f->check_format("300.2.3.4")); + } + + public function testGoodIP() { + $f=new CustomField(); + $f->name="test 1"; + $f->format="IP"; + $f->element="text"; + + $f->save(); + + $this->assertTrue($f->check_format("1.2.3.4")); + } + + public function testFormat() { + $f=new CustomField(); + $f->name="test 1"; + $f->format="IP"; + $f->element="text"; + + $f->save(); + + //print_r($f->attributes); + //print($f); + //print("Uhm, format is: ".$f->attributes['format']); + //print("Lemme try this: ".$f->getAttribute('format')); + //print("Moar: ".print_r($f->getAttributes(),true)); + $this->assertEquals($f->getAttributes()['format'],CustomField::$PredefinedFormats['IP']); //this seems undocumented... + $this->assertEquals($f->format,"IP"); + } + + public function testDbName() { + $f=new CustomField(); + $f->name="An Example Name"; + $this->assertEquals($f->db_column_name(),"an_example_name"); + } + + public function testValidation() { + $f=new CustomField(); + + $f->name='Id'; + $f->format='IP'; + $f->element="text"; + /*$this->assertDoesntThrow(function () { + $f->save(); + });*/ + $this->assertFalse(CustomField::saving($f)); //horrible hacky workaround to even problems + //for Laravel testing. Blech. + + $g=new CustomField(); + $g->name='totally_unique_name'; + $g->format='IP'; + $g->element="text"; + //$this->assertTrue($g->validate($g->toArray())); + $this->assertTrue(CustomField::saving($g)); + /*$this->assertThrows(function () { + $f->save(); + });*/ + } +} diff --git a/app/validators.php b/app/validators.php index c3050b526b..4e3d89730c 100755 --- a/app/validators.php +++ b/app/validators.php @@ -7,3 +7,8 @@ Validator::extend('alpha_space', function ($attribute,$value,$parameters) { // patterm must be matched at least once (empty strings will not pass) // (ungreedy?!) ,multiline }); + +Validator::extend('unique_column',function ($attribute,$value,$parameters) { + + return false; +}); diff --git a/docker/develop.sh b/docker/develop.sh index b94d14e0d1..bf550ea1a6 100644 --- a/docker/develop.sh +++ b/docker/develop.sh @@ -1,3 +1,6 @@ #!/bin/bash -docker run -v \ No newline at end of file +#docker run -v docker start mysql +# docker run --name snipe-mysql -e MYSQL_ROOT_PASSWORD=fartwingus -e MYSQL_DATABASE=snipeit -e MYSQL_USER=snipeit -e MYSQL_PASSWORD=whateverdood -d mysql +docker run -d snipe-mysql +docker run -d -v ~/Documents/snipeyhead/snipe-it/:/var/www/html -p $(boot2docker ip)::80 --link snipe-mysql:mysql --name=snipeit snipeit From 4b68efb80bbf2f93927707152aa448d17b79f886 Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Wed, 12 Aug 2015 15:52:25 -0700 Subject: [PATCH 002/119] use CustomModel; is stupid, and doesn't mean anything. --- app/models/Model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/Model.php b/app/models/Model.php index b6e7762a4f..334f734ce3 100755 --- a/app/models/Model.php +++ b/app/models/Model.php @@ -1,6 +1,6 @@ Date: Mon, 21 Sep 2015 16:41:48 -0700 Subject: [PATCH 003/119] Typo in the word 'language' --- app/config/app.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/config/app.php b/app/config/app.php index c834ee8d11..27e0c7cbd6 100755 --- a/app/config/app.php +++ b/app/config/app.php @@ -20,7 +20,7 @@ return array( | Application Locale |-------------------------------------------------------------------------- | - | This locale ties into the languaage files in app/lang, which contain the + | This locale ties into the language files in app/lang, which contain the | language files for each translation. | */ From 22ea008bb4e79ee3f154944a9888135f80342a41 Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Mon, 21 Sep 2015 16:42:43 -0700 Subject: [PATCH 004/119] New documentation on Docker method of running Snipe-IT. New environment variables available to customize how Snipe-IT ought to work under Docker. Locale, timezone, and custom-URL support. Documentation pushes users to move more towards 'env-files' rather than environment variables. Fixes #1020 --- Dockerfile | 3 +++ docker/README.md | 65 ++++++++++++++++++++++++++++++------------------ docker/app.php | 4 +++ 3 files changed, 48 insertions(+), 24 deletions(-) diff --git a/Dockerfile b/Dockerfile index fb68bcaa3a..7a53df1a53 100644 --- a/Dockerfile +++ b/Dockerfile @@ -53,6 +53,9 @@ RUN cd /var/www/html;composer install ############### APPLICATION INSTALL/INIT ################# +RUN cd /var/www/html;MYSQL_PORT_3306_TCP_ADDR='' MYSQL_PORT_3306_TCP_PORT='' MYSQL_ENV_MYSQL_DATABASE='' \ +MYSQL_ENV_MYSQL_USER='' MYSQL_ENV_MYSQL_PASSWORD='' php artisan --env=production -n key:generate + #RUN php artisan app:install # too interactive! Try something else diff --git a/docker/README.md b/docker/README.md index a91fe17ca4..4dea45d41b 100644 --- a/docker/README.md +++ b/docker/README.md @@ -10,36 +10,53 @@ Then you can use your newly built image as ```snipeit``` ### How to get up and running ### +* The best way to handle all of the various settings for your various containers is to use an `env-file`. +See the Docker documentation for more details. It should be just a simple text file with environment +variable names and values, separated by ```=``` signs. + +Your docker.env should look something like this: + +```env +# Mysql Parameters +MYSQL_ROOT_PASSWORD=YOUR_SUPER_SECRET_PASSWORD +MYSQL_DATABASE=snipeit +MYSQL_USER=snipeit +MYSQL_PASSWORD=YOUR_snipeit_USER_PASSWORD + +# Email Parameters +# - the hostname/IP address of your mailserver +MAIL_PORT_587_TCP_ADDR=smtp.whatever.com +#the port for the mailserver (probably 587, could be another) +MAIL_PORT_587_TCP_PORT=587 +# the default from address, and from name for emails +MAIL_ENV_FROM_ADDR=youremail@yourdomain.com +MAIL_ENV_FROM_NAME=Your Full Email Name +# - pick 'tls' for SMTP-over-SSL, 'tcp' for unencrypted +MAIL_ENV_ENCRYPTION=tcp +# SMTP username and password +MAIL_ENV_USERNAME=your_email_username +MAIL_ENV_PASSWORD=your_email_password + +# Snipe-IT Settings +SNIPEIT_TIMEZONE=UTC +SNIPEIT_LOCALE=en +SERVER_URL=https://myserver.com +``` * First get a MySQL container running -Figure out what you want for your: - -* MySQL root password -* MySQL Database name for Snipe-IT -* MySQL User name for the user who will access Snipe-IT -* MySQL Password for that user - ```sh -docker run --name mysql -e MYSQL_ROOT_PASSWORD=SUPERDUPERSECRETPASSWORD -e MYSQL_DATABASE=snipeit -e MYSQL_USER=snipeit -e MYSQL_PASSWORD=tinglewingler -d -p $(boot2docker ip)::3306 mysql +docker run --name snipe-mysql --env-file=my_env_file -d -p $(docker-machine ip b2d)::3306 mysql ``` -That should set you up with your database to use. (You can also use an environment file using ```--env-file```; see ```docker run --help``` for details) +That should set you up with your database to use. (You can also specify environment variables on the command-line instead of the env-file, but that can get very clunky very quickly; see ```docker run --help``` for details) -You'll want to handle E-Mail - you can do this with a Docker container (not documented here), or point to any other external mail server. If you did want to do it using Docker, make sure to expose port 587 for mail submission, and use ```--link mail:...```. Regardless, the environment variables necessary are: - - * MAIL_PORT_587_TCP_ADDR - the hostname/IP address of your mailserver - * MAIL_PORT_587_TCP_PORT - the port for the mailserver (probably 587, could be another) - * MAIL_ENV_FROM_ADDR, MAIL_ENV_FROM_NAME - the default from address, and from name for emails - * MAIL_ENV_ENCRYPTION - pick 'tls' for SMTP-over-SSL, 'tcp' for unencrypted - * MAIL_ENV_USERNAME - SMTP username - * MAIL_ENV_PASSWORD - SMTP password - -You can assemble these options into an env-file, or specify them on the command line when you run your Snipe-IT container. +* If your Email solution requires its own container, start that container or service. Make sure to expose port 587 for mail submission, and use ```--link mail:...```. Now you can start your Snipe-IT container - ```sh -docker run -d -p $(boot2docker ip)::80 --name="snipeit" --link mysql:mysql [--env-file or -e options...] snipeit +docker run -d -p $(docker-machine ip b2d)::80 --name="snipeit" --link snipe-mysql:mysql --env-file=my_env_file snipeit ``` +If you have a separate container running for email, you will also want a ```--link``` setting for email as well. You can find out what port Snipe-IT is running on with: @@ -55,15 +72,15 @@ docker exec -i -t snipeit php artisan app:install (Go ahead and answer the questions however you like. Type 'yes' when asked whether or not you want to run migrations.) -#NOTE: +~~#NOTE:~~ -You may have to run: +~~You may have to run:~~ ```sh -docker exec -i -t snipeit php artisan key:generate --env=production +~~docker exec -i -t snipeit php artisan key:generate --env=production~~ ``` -to get the production application key set correctly; I'm not yet sure why this is (I think it's a bug?) +~~to get the production application key set correctly; I'm not yet sure why this is (I think it's a bug?)~~ # ~~If you want to seed~~ diff --git a/docker/app.php b/docker/app.php index ff8d82304e..529ed6c85a 100644 --- a/docker/app.php +++ b/docker/app.php @@ -14,6 +14,10 @@ return array( */ 'debug' => false, + + 'timezone' => isset($_ENV['SNIPEIT_TIMEZONE']) ? $_ENV['SNIPEIT_TIMEZONE'] : 'UTC', + 'locale' => isset($_ENV['SNIPEIT_LOCALE']) ? $_ENV['SNIPEIT_LOCALE'] : 'en', + /* |-------------------------------------------------------------------------- From 273d838a42d96cf0227a1664b7ba74f7bc208f31 Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Tue, 20 Oct 2015 17:06:07 -0700 Subject: [PATCH 005/119] Wide swing at custom fields --- ...21_235926_create_custom_field_fieldset.php | 39 + .../2015_09_22_000104_create_fieldset.php | 34 + ...09_22_003321_add_fieldset_id_to_assets.php | 31 + .../2015_09_22_003413_migrate_mac_address.php | 32 + app/models/CustomField.php | 2 +- app/models/CustomFieldset.php | 2 +- app/models/Model.php | 2 +- docker.env | 20 + .../_generated/AcceptanceTesterActions.php | 1971 +++++++++++++++++ .../_generated/FunctionalTesterActions.php | 350 +++ .../_support/_generated/UnitTesterActions.php | 348 +++ 11 files changed, 2828 insertions(+), 3 deletions(-) create mode 100644 app/database/migrations/2015_09_21_235926_create_custom_field_fieldset.php create mode 100644 app/database/migrations/2015_09_22_000104_create_fieldset.php create mode 100644 app/database/migrations/2015_09_22_003321_add_fieldset_id_to_assets.php create mode 100644 app/database/migrations/2015_09_22_003413_migrate_mac_address.php create mode 100644 docker.env create mode 100644 tests/_support/_generated/AcceptanceTesterActions.php create mode 100644 tests/_support/_generated/FunctionalTesterActions.php create mode 100644 tests/_support/_generated/UnitTesterActions.php diff --git a/app/database/migrations/2015_09_21_235926_create_custom_field_fieldset.php b/app/database/migrations/2015_09_21_235926_create_custom_field_fieldset.php new file mode 100644 index 0000000000..186414dbbf --- /dev/null +++ b/app/database/migrations/2015_09_21_235926_create_custom_field_fieldset.php @@ -0,0 +1,39 @@ +integer('custom_field_id'); + $table->integer('fieldset_id'); + + $table->integer('order'); + $table->boolean('required'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('custom_field_fieldset'); + // Schema::table('custom_field_fieldset', function(Blueprint $table) + // { + // // + // }); + } + +} diff --git a/app/database/migrations/2015_09_22_000104_create_fieldset.php b/app/database/migrations/2015_09_22_000104_create_fieldset.php new file mode 100644 index 0000000000..37eea586ee --- /dev/null +++ b/app/database/migrations/2015_09_22_000104_create_fieldset.php @@ -0,0 +1,34 @@ +integer('fieldset_id'); + } + // + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } + +} diff --git a/app/database/migrations/2015_09_22_003413_migrate_mac_address.php b/app/database/migrations/2015_09_22_003413_migrate_mac_address.php new file mode 100644 index 0000000000..0c65d294f4 --- /dev/null +++ b/app/database/migrations/2015_09_22_003413_migrate_mac_address.php @@ -0,0 +1,32 @@ +fields()->create({name: "MAC Address",required: false, order: 1}); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } + +} diff --git a/app/models/CustomField.php b/app/models/CustomField.php index 1649a171b0..4678ecbdcd 100644 --- a/app/models/CustomField.php +++ b/app/models/CustomField.php @@ -38,7 +38,7 @@ class CustomField extends Elegant }*/ public function fieldset() { - return $this->hasMany('CustomFieldset'); //?!?!?!?!?!? + return $this->belongsToMany('Fieldset'); //?!?!?!?!?!? } public $rules=[ diff --git a/app/models/CustomFieldset.php b/app/models/CustomFieldset.php index 957d8353cc..58afc69e5e 100644 --- a/app/models/CustomFieldset.php +++ b/app/models/CustomFieldset.php @@ -2,7 +2,7 @@ class CustomFieldset extends Elegant { public function fields() { - return $this->hasMany('CustomField'); + return $this->belongsToMany('CustomField'); } //requiredness goes *here* diff --git a/app/models/Model.php b/app/models/Model.php index 334f734ce3..12c838ef29 100755 --- a/app/models/Model.php +++ b/app/models/Model.php @@ -47,7 +47,7 @@ class Model extends Elegant { $foo=new CustomField(); $foo2=new CustomFieldset(); - return $this->belongsTo('CustomFieldset','custom_fieldset_id'); + return $this->belongsTo('Fieldset','fieldset_id'); } /** diff --git a/docker.env b/docker.env new file mode 100644 index 0000000000..67c9b37d70 --- /dev/null +++ b/docker.env @@ -0,0 +1,20 @@ +# Docker Environment File + +#Database Variables +MYSQL_DATABASE=snipeit +MYSQL_USER=snipeit +MYSQL_PASSWORD=tinglewingler + +#Email Variables +MAIL_PORT_587_TCP_ADDR=smtp.mandrillapp.com +MAIL_PORT_587_TCP_PORT=587 +MAIL_ENV_FROM_ADDR=uberbrady@gmail.com +MAIL_ENV_FROM_NAME=Brady Wetherington +MAIL_ENV_ENCRYPTION=tcp +MAIL_ENV_USERNAME=uberbrady@gmail.com +MAIL_ENV_PASSWORD=N7AqLufTZMULWHWYwJ0ZCw + +#SNIPE-IT Variables +SNIPEIT_TIMEZONE=America/Los_Angeles +SNIPEIT_LOCALE=es-ES +SERVER_URL=https://192.168.99.100:32775 diff --git a/tests/_support/_generated/AcceptanceTesterActions.php b/tests/_support/_generated/AcceptanceTesterActions.php new file mode 100644 index 0000000000..4643a9166d --- /dev/null +++ b/tests/_support/_generated/AcceptanceTesterActions.php @@ -0,0 +1,1971 @@ +setHeader('X-Requested-With', 'Codeception'); + * $I->amOnPage('test-headers.php'); + * ?> + * ``` + * + * @param string $name the name of the request header + * @param string $value the value to set it to for subsequent + * requests + * @see \Codeception\Module\PhpBrowser::setHeader() + */ + public function setHeader($name, $value) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('setHeader', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Deletes the header with the passed name. Subsequent requests + * will not have the deleted header in its request. + * + * Example: + * ```php + * setHeader('X-Requested-With', 'Codeception'); + * $I->amOnPage('test-headers.php'); + * // ... + * $I->deleteHeader('X-Requested-With'); + * $I->amOnPage('some-other-page.php'); + * ?> + * ``` + * + * @param string $name the name of the header to delete. + * @see \Codeception\Module\PhpBrowser::deleteHeader() + */ + public function deleteHeader($name) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('deleteHeader', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Authenticates user for HTTP_AUTH + * + * @param $username + * @param $password + * @see \Codeception\Module\PhpBrowser::amHttpAuthenticated() + */ + public function amHttpAuthenticated($username, $password) { + return $this->getScenario()->runStep(new \Codeception\Step\Condition('amHttpAuthenticated', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Open web page at the given absolute URL and sets its hostname as the base host. + * + * ``` php + * amOnUrl('http://codeception.com'); + * $I->amOnPage('/quickstart'); // moves to http://codeception.com/quickstart + * ?> + * ``` + * @see \Codeception\Module\PhpBrowser::amOnUrl() + */ + public function amOnUrl($url) { + return $this->getScenario()->runStep(new \Codeception\Step\Condition('amOnUrl', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Changes the subdomain for the 'url' configuration parameter. + * Does not open a page; use `amOnPage` for that. + * + * ``` php + * amOnSubdomain('user'); + * $I->amOnPage('/'); + * // moves to http://user.mysite.com/ + * ?> + * ``` + * + * @param $subdomain + * + * @return mixed + * @see \Codeception\Module\PhpBrowser::amOnSubdomain() + */ + public function amOnSubdomain($subdomain) { + return $this->getScenario()->runStep(new \Codeception\Step\Condition('amOnSubdomain', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Low-level API method. + * If Codeception commands are not enough, use [Guzzle HTTP Client](http://guzzlephp.org/) methods directly + * + * Example: + * + * ``` php + * executeInGuzzle(function (\GuzzleHttp\Client $client) { + * $client->get('/get', ['query' => ['foo' => 'bar']]); + * }); + * ?> + * ``` + * + * It is not recommended to use this command on a regular basis. + * If Codeception lacks important Guzzle Client methods, implement them and submit patches. + * + * @param callable $function + * @see \Codeception\Module\PhpBrowser::executeInGuzzle() + */ + public function executeInGuzzle($function) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('executeInGuzzle', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Opens the page for the given relative URI. + * + * ``` php + * amOnPage('/'); + * // opens /register page + * $I->amOnPage('/register'); + * ?> + * ``` + * + * @param $page + * @see \Codeception\Lib\InnerBrowser::amOnPage() + */ + public function amOnPage($page) { + return $this->getScenario()->runStep(new \Codeception\Step\Condition('amOnPage', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Perform a click on a link or a button, given by a locator. + * If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string. + * For buttons, the "value" attribute, "name" attribute, and inner text are searched. + * For links, the link text is searched. + * For images, the "alt" attribute and inner text of any parent links are searched. + * + * The second parameter is a context (CSS or XPath locator) to narrow the search. + * + * Note that if the locator matches a button of type `submit`, the form will be submitted. + * + * ``` php + * click('Logout'); + * // button of form + * $I->click('Submit'); + * // CSS button + * $I->click('#form input[type=submit]'); + * // XPath + * $I->click('//form/*[@type=submit]'); + * // link in context + * $I->click('Logout', '#nav'); + * // using strict locator + * $I->click(['link' => 'Login']); + * ?> + * ``` + * + * @param $link + * @param $context + * @see \Codeception\Lib\InnerBrowser::click() + */ + public function click($link, $context = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('click', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the current page contains the given string. + * Specify a locator as the second parameter to match a specific region. + * + * ``` php + * see('Logout'); // I can suppose user is logged in + * $I->see('Sign Up','h1'); // I can suppose it's a signup page + * $I->see('Sign Up','//body/h1'); // with XPath + * ?> + * ``` + * + * @param $text + * @param null $selector + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::see() + */ + public function canSee($text, $selector = null) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('see', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the current page contains the given string. + * Specify a locator as the second parameter to match a specific region. + * + * ``` php + * see('Logout'); // I can suppose user is logged in + * $I->see('Sign Up','h1'); // I can suppose it's a signup page + * $I->see('Sign Up','//body/h1'); // with XPath + * ?> + * ``` + * + * @param $text + * @param null $selector + * @see \Codeception\Lib\InnerBrowser::see() + */ + public function see($text, $selector = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('see', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the current page doesn't contain the text specified. + * Give a locator as the second parameter to match a specific region. + * + * ```php + * dontSee('Login'); // I can suppose user is already logged in + * $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page + * $I->dontSee('Sign Up','//body/h1'); // with XPath + * ?> + * ``` + * + * @param $text + * @param null $selector + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::dontSee() + */ + public function cantSee($text, $selector = null) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSee', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the current page doesn't contain the text specified. + * Give a locator as the second parameter to match a specific region. + * + * ```php + * dontSee('Login'); // I can suppose user is already logged in + * $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page + * $I->dontSee('Sign Up','//body/h1'); // with XPath + * ?> + * ``` + * + * @param $text + * @param null $selector + * @see \Codeception\Lib\InnerBrowser::dontSee() + */ + public function dontSee($text, $selector = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSee', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that there's a link with the specified text. + * Give a full URL as the second parameter to match links with that exact URL. + * + * ``` php + * seeLink('Logout'); // matches Logout + * $I->seeLink('Logout','/logout'); // matches Logout + * ?> + * ``` + * + * @param $text + * @param null $url + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::seeLink() + */ + public function canSeeLink($text, $url = null) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeLink', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that there's a link with the specified text. + * Give a full URL as the second parameter to match links with that exact URL. + * + * ``` php + * seeLink('Logout'); // matches Logout + * $I->seeLink('Logout','/logout'); // matches Logout + * ?> + * ``` + * + * @param $text + * @param null $url + * @see \Codeception\Lib\InnerBrowser::seeLink() + */ + public function seeLink($text, $url = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeLink', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the page doesn't contain a link with the given string. + * If the second parameter is given, only links with a matching "href" attribute will be checked. + * + * ``` php + * dontSeeLink('Logout'); // I suppose user is not logged in + * $I->dontSeeLink('Checkout now', '/store/cart.php'); + * ?> + * ``` + * + * @param $text + * @param null $url + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::dontSeeLink() + */ + public function cantSeeLink($text, $url = null) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeLink', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the page doesn't contain a link with the given string. + * If the second parameter is given, only links with a matching "href" attribute will be checked. + * + * ``` php + * dontSeeLink('Logout'); // I suppose user is not logged in + * $I->dontSeeLink('Checkout now', '/store/cart.php'); + * ?> + * ``` + * + * @param $text + * @param null $url + * @see \Codeception\Lib\InnerBrowser::dontSeeLink() + */ + public function dontSeeLink($text, $url = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeLink', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that current URI contains the given string. + * + * ``` php + * seeInCurrentUrl('home'); + * // to match: /users/1 + * $I->seeInCurrentUrl('/users/'); + * ?> + * ``` + * + * @param $uri + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::seeInCurrentUrl() + */ + public function canSeeInCurrentUrl($uri) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInCurrentUrl', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that current URI contains the given string. + * + * ``` php + * seeInCurrentUrl('home'); + * // to match: /users/1 + * $I->seeInCurrentUrl('/users/'); + * ?> + * ``` + * + * @param $uri + * @see \Codeception\Lib\InnerBrowser::seeInCurrentUrl() + */ + public function seeInCurrentUrl($uri) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInCurrentUrl', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the current URI doesn't contain the given string. + * + * ``` php + * dontSeeInCurrentUrl('/users/'); + * ?> + * ``` + * + * @param $uri + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::dontSeeInCurrentUrl() + */ + public function cantSeeInCurrentUrl($uri) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInCurrentUrl', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the current URI doesn't contain the given string. + * + * ``` php + * dontSeeInCurrentUrl('/users/'); + * ?> + * ``` + * + * @param $uri + * @see \Codeception\Lib\InnerBrowser::dontSeeInCurrentUrl() + */ + public function dontSeeInCurrentUrl($uri) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInCurrentUrl', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the current URL is equal to the given string. + * Unlike `seeInCurrentUrl`, this only matches the full URL. + * + * ``` php + * seeCurrentUrlEquals('/'); + * ?> + * ``` + * + * @param $uri + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::seeCurrentUrlEquals() + */ + public function canSeeCurrentUrlEquals($uri) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCurrentUrlEquals', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the current URL is equal to the given string. + * Unlike `seeInCurrentUrl`, this only matches the full URL. + * + * ``` php + * seeCurrentUrlEquals('/'); + * ?> + * ``` + * + * @param $uri + * @see \Codeception\Lib\InnerBrowser::seeCurrentUrlEquals() + */ + public function seeCurrentUrlEquals($uri) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCurrentUrlEquals', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the current URL doesn't equal the given string. + * Unlike `dontSeeInCurrentUrl`, this only matches the full URL. + * + * ``` php + * dontSeeCurrentUrlEquals('/'); + * ?> + * ``` + * + * @param $uri + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::dontSeeCurrentUrlEquals() + */ + public function cantSeeCurrentUrlEquals($uri) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeCurrentUrlEquals', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the current URL doesn't equal the given string. + * Unlike `dontSeeInCurrentUrl`, this only matches the full URL. + * + * ``` php + * dontSeeCurrentUrlEquals('/'); + * ?> + * ``` + * + * @param $uri + * @see \Codeception\Lib\InnerBrowser::dontSeeCurrentUrlEquals() + */ + public function dontSeeCurrentUrlEquals($uri) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeCurrentUrlEquals', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the current URL matches the given regular expression. + * + * ``` php + * seeCurrentUrlMatches('~$/users/(\d+)~'); + * ?> + * ``` + * + * @param $uri + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::seeCurrentUrlMatches() + */ + public function canSeeCurrentUrlMatches($uri) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCurrentUrlMatches', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the current URL matches the given regular expression. + * + * ``` php + * seeCurrentUrlMatches('~$/users/(\d+)~'); + * ?> + * ``` + * + * @param $uri + * @see \Codeception\Lib\InnerBrowser::seeCurrentUrlMatches() + */ + public function seeCurrentUrlMatches($uri) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCurrentUrlMatches', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that current url doesn't match the given regular expression. + * + * ``` php + * dontSeeCurrentUrlMatches('~$/users/(\d+)~'); + * ?> + * ``` + * + * @param $uri + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::dontSeeCurrentUrlMatches() + */ + public function cantSeeCurrentUrlMatches($uri) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeCurrentUrlMatches', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that current url doesn't match the given regular expression. + * + * ``` php + * dontSeeCurrentUrlMatches('~$/users/(\d+)~'); + * ?> + * ``` + * + * @param $uri + * @see \Codeception\Lib\InnerBrowser::dontSeeCurrentUrlMatches() + */ + public function dontSeeCurrentUrlMatches($uri) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeCurrentUrlMatches', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Executes the given regular expression against the current URI and returns the first match. + * If no parameters are provided, the full URI is returned. + * + * ``` php + * grabFromCurrentUrl('~$/user/(\d+)/~'); + * $uri = $I->grabFromCurrentUrl(); + * ?> + * ``` + * + * @param null $uri + * + * @internal param $url + * @return mixed + * @see \Codeception\Lib\InnerBrowser::grabFromCurrentUrl() + */ + public function grabFromCurrentUrl($uri = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('grabFromCurrentUrl', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the specified checkbox is checked. + * + * ``` php + * seeCheckboxIsChecked('#agree'); // I suppose user agreed to terms + * $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user agreed to terms, If there is only one checkbox in form. + * $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); + * ?> + * ``` + * + * @param $checkbox + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::seeCheckboxIsChecked() + */ + public function canSeeCheckboxIsChecked($checkbox) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCheckboxIsChecked', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the specified checkbox is checked. + * + * ``` php + * seeCheckboxIsChecked('#agree'); // I suppose user agreed to terms + * $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user agreed to terms, If there is only one checkbox in form. + * $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); + * ?> + * ``` + * + * @param $checkbox + * @see \Codeception\Lib\InnerBrowser::seeCheckboxIsChecked() + */ + public function seeCheckboxIsChecked($checkbox) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCheckboxIsChecked', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Check that the specified checkbox is unchecked. + * + * ``` php + * dontSeeCheckboxIsChecked('#agree'); // I suppose user didn't agree to terms + * $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user didn't check the first checkbox in form. + * ?> + * ``` + * + * @param $checkbox + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::dontSeeCheckboxIsChecked() + */ + public function cantSeeCheckboxIsChecked($checkbox) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeCheckboxIsChecked', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Check that the specified checkbox is unchecked. + * + * ``` php + * dontSeeCheckboxIsChecked('#agree'); // I suppose user didn't agree to terms + * $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user didn't check the first checkbox in form. + * ?> + * ``` + * + * @param $checkbox + * @see \Codeception\Lib\InnerBrowser::dontSeeCheckboxIsChecked() + */ + public function dontSeeCheckboxIsChecked($checkbox) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeCheckboxIsChecked', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the given input field or textarea contains the given value. + * For fuzzy locators, fields are matched by label text, the "name" attribute, CSS, and XPath. + * + * ``` php + * seeInField('Body','Type your comment here'); + * $I->seeInField('form textarea[name=body]','Type your comment here'); + * $I->seeInField('form input[type=hidden]','hidden_value'); + * $I->seeInField('#searchform input','Search'); + * $I->seeInField('//form/*[@name=search]','Search'); + * $I->seeInField(['name' => 'search'], 'Search'); + * ?> + * ``` + * + * @param $field + * @param $value + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::seeInField() + */ + public function canSeeInField($field, $value) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInField', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the given input field or textarea contains the given value. + * For fuzzy locators, fields are matched by label text, the "name" attribute, CSS, and XPath. + * + * ``` php + * seeInField('Body','Type your comment here'); + * $I->seeInField('form textarea[name=body]','Type your comment here'); + * $I->seeInField('form input[type=hidden]','hidden_value'); + * $I->seeInField('#searchform input','Search'); + * $I->seeInField('//form/*[@name=search]','Search'); + * $I->seeInField(['name' => 'search'], 'Search'); + * ?> + * ``` + * + * @param $field + * @param $value + * @see \Codeception\Lib\InnerBrowser::seeInField() + */ + public function seeInField($field, $value) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInField', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that an input field or textarea doesn't contain the given value. + * For fuzzy locators, the field is matched by label text, CSS and XPath. + * + * ``` php + * dontSeeInField('Body','Type your comment here'); + * $I->dontSeeInField('form textarea[name=body]','Type your comment here'); + * $I->dontSeeInField('form input[type=hidden]','hidden_value'); + * $I->dontSeeInField('#searchform input','Search'); + * $I->dontSeeInField('//form/*[@name=search]','Search'); + * $I->dontSeeInField(['name' => 'search'], 'Search'); + * ?> + * ``` + * + * @param $field + * @param $value + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::dontSeeInField() + */ + public function cantSeeInField($field, $value) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInField', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that an input field or textarea doesn't contain the given value. + * For fuzzy locators, the field is matched by label text, CSS and XPath. + * + * ``` php + * dontSeeInField('Body','Type your comment here'); + * $I->dontSeeInField('form textarea[name=body]','Type your comment here'); + * $I->dontSeeInField('form input[type=hidden]','hidden_value'); + * $I->dontSeeInField('#searchform input','Search'); + * $I->dontSeeInField('//form/*[@name=search]','Search'); + * $I->dontSeeInField(['name' => 'search'], 'Search'); + * ?> + * ``` + * + * @param $field + * @param $value + * @see \Codeception\Lib\InnerBrowser::dontSeeInField() + */ + public function dontSeeInField($field, $value) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInField', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks if the array of form parameters (name => value) are set on the form matched with the + * passed selector. + * + * ``` php + * seeInFormFields('form[name=myform]', [ + * 'input1' => 'value', + * 'input2' => 'other value', + * ]); + * ?> + * ``` + * + * For multi-select elements, or to check values of multiple elements with the same name, an + * array may be passed: + * + * ``` php + * seeInFormFields('.form-class', [ + * 'multiselect' => [ + * 'value1', + * 'value2', + * ], + * 'checkbox[]' => [ + * 'a checked value', + * 'another checked value', + * ], + * ]); + * ?> + * ``` + * + * Additionally, checkbox values can be checked with a boolean. + * + * ``` php + * seeInFormFields('#form-id', [ + * 'checkbox1' => true, // passes if checked + * 'checkbox2' => false, // passes if unchecked + * ]); + * ?> + * ``` + * + * Pair this with submitForm for quick testing magic. + * + * ``` php + * 'value', + * 'field2' => 'another value', + * 'checkbox1' => true, + * // ... + * ]; + * $I->submitForm('//form[@id=my-form]', $form, 'submitButton'); + * // $I->amOnPage('/path/to/form-page') may be needed + * $I->seeInFormFields('//form[@id=my-form]', $form); + * ?> + * ``` + * + * @param $formSelector + * @param $params + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::seeInFormFields() + */ + public function canSeeInFormFields($formSelector, $params) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInFormFields', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks if the array of form parameters (name => value) are set on the form matched with the + * passed selector. + * + * ``` php + * seeInFormFields('form[name=myform]', [ + * 'input1' => 'value', + * 'input2' => 'other value', + * ]); + * ?> + * ``` + * + * For multi-select elements, or to check values of multiple elements with the same name, an + * array may be passed: + * + * ``` php + * seeInFormFields('.form-class', [ + * 'multiselect' => [ + * 'value1', + * 'value2', + * ], + * 'checkbox[]' => [ + * 'a checked value', + * 'another checked value', + * ], + * ]); + * ?> + * ``` + * + * Additionally, checkbox values can be checked with a boolean. + * + * ``` php + * seeInFormFields('#form-id', [ + * 'checkbox1' => true, // passes if checked + * 'checkbox2' => false, // passes if unchecked + * ]); + * ?> + * ``` + * + * Pair this with submitForm for quick testing magic. + * + * ``` php + * 'value', + * 'field2' => 'another value', + * 'checkbox1' => true, + * // ... + * ]; + * $I->submitForm('//form[@id=my-form]', $form, 'submitButton'); + * // $I->amOnPage('/path/to/form-page') may be needed + * $I->seeInFormFields('//form[@id=my-form]', $form); + * ?> + * ``` + * + * @param $formSelector + * @param $params + * @see \Codeception\Lib\InnerBrowser::seeInFormFields() + */ + public function seeInFormFields($formSelector, $params) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInFormFields', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks if the array of form parameters (name => value) are not set on the form matched with + * the passed selector. + * + * ``` php + * dontSeeInFormFields('form[name=myform]', [ + * 'input1' => 'non-existent value', + * 'input2' => 'other non-existent value', + * ]); + * ?> + * ``` + * + * To check that an element hasn't been assigned any one of many values, an array can be passed + * as the value: + * + * ``` php + * dontSeeInFormFields('.form-class', [ + * 'fieldName' => [ + * 'This value shouldn\'t be set', + * 'And this value shouldn\'t be set', + * ], + * ]); + * ?> + * ``` + * + * Additionally, checkbox values can be checked with a boolean. + * + * ``` php + * dontSeeInFormFields('#form-id', [ + * 'checkbox1' => true, // fails if checked + * 'checkbox2' => false, // fails if unchecked + * ]); + * ?> + * ``` + * + * @param $formSelector + * @param $params + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::dontSeeInFormFields() + */ + public function cantSeeInFormFields($formSelector, $params) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInFormFields', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks if the array of form parameters (name => value) are not set on the form matched with + * the passed selector. + * + * ``` php + * dontSeeInFormFields('form[name=myform]', [ + * 'input1' => 'non-existent value', + * 'input2' => 'other non-existent value', + * ]); + * ?> + * ``` + * + * To check that an element hasn't been assigned any one of many values, an array can be passed + * as the value: + * + * ``` php + * dontSeeInFormFields('.form-class', [ + * 'fieldName' => [ + * 'This value shouldn\'t be set', + * 'And this value shouldn\'t be set', + * ], + * ]); + * ?> + * ``` + * + * Additionally, checkbox values can be checked with a boolean. + * + * ``` php + * dontSeeInFormFields('#form-id', [ + * 'checkbox1' => true, // fails if checked + * 'checkbox2' => false, // fails if unchecked + * ]); + * ?> + * ``` + * + * @param $formSelector + * @param $params + * @see \Codeception\Lib\InnerBrowser::dontSeeInFormFields() + */ + public function dontSeeInFormFields($formSelector, $params) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInFormFields', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Submits the given form on the page, optionally with the given form + * values. Give the form fields values as an array. + * + * Skipped fields will be filled by their values from the page. + * You don't need to click the 'Submit' button afterwards. + * This command itself triggers the request to form's action. + * + * You can optionally specify what button's value to include + * in the request with the last parameter as an alternative to + * explicitly setting its value in the second parameter, as + * button values are not otherwise included in the request. + * + * Examples: + * + * ``` php + * submitForm('#login', [ + * 'login' => 'davert', + * 'password' => '123456' + * ]); + * // or + * $I->submitForm('#login', [ + * 'login' => 'davert', + * 'password' => '123456' + * ], 'submitButtonName'); + * + * ``` + * + * For example, given this sample "Sign Up" form: + * + * ``` html + *
+ * Login: + *
+ * Password: + *
+ * Do you agree to our terms? + *
+ * Select pricing plan: + * + * + *
+ * ``` + * + * You could write the following to submit it: + * + * ``` php + * submitForm( + * '#userForm', + * [ + * 'user' => [ + * 'login' => 'Davert', + * 'password' => '123456', + * 'agree' => true + * ] + * ], + * 'submitButton' + * ); + * ``` + * Note that "2" will be the submitted value for the "plan" field, as it is + * the selected option. + * + * You can also emulate a JavaScript submission by not specifying any + * buttons in the third parameter to submitForm. + * + * ```php + * submitForm( + * '#userForm', + * [ + * 'user' => [ + * 'login' => 'Davert', + * 'password' => '123456', + * 'agree' => true + * ] + * ] + * ); + * ``` + * + * Pair this with seeInFormFields for quick testing magic. + * + * ``` php + * 'value', + * 'field2' => 'another value', + * 'checkbox1' => true, + * // ... + * ]; + * $I->submitForm('//form[@id=my-form]', $form, 'submitButton'); + * // $I->amOnPage('/path/to/form-page') may be needed + * $I->seeInFormFields('//form[@id=my-form]', $form); + * ?> + * ``` + * + * Parameter values can be set to arrays for multiple input fields + * of the same name, or multi-select combo boxes. For checkboxes, + * either the string value can be used, or boolean values which will + * be replaced by the checkbox's value in the DOM. + * + * ``` php + * submitForm('#my-form', [ + * 'field1' => 'value', + * 'checkbox' => [ + * 'value of first checkbox', + * 'value of second checkbox, + * ], + * 'otherCheckboxes' => [ + * true, + * false, + * false + * ], + * 'multiselect' => [ + * 'first option value', + * 'second option value' + * ] + * ]); + * ?> + * ``` + * + * Mixing string and boolean values for a checkbox's value is not supported + * and may produce unexpected results. + * + * Field names ending in "[]" must be passed without the trailing square + * bracket characters, and must contain an array for its value. This allows + * submitting multiple values with the same name, consider: + * + * ```php + * $I->submitForm('#my-form', [ + * 'field[]' => 'value', + * 'field[]' => 'another value', // 'field[]' is already a defined key + * ]); + * ``` + * + * The solution is to pass an array value: + * + * ```php + * // this way both values are submitted + * $I->submitForm('#my-form', [ + * 'field' => [ + * 'value', + * 'another value', + * ] + * ]); + * ``` + * + * @param $selector + * @param $params + * @param $button + * @see \Codeception\Lib\InnerBrowser::submitForm() + */ + public function submitForm($selector, $params, $button = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('submitForm', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Fills a text field or textarea with the given string. + * + * ``` php + * fillField("//input[@type='text']", "Hello World!"); + * $I->fillField(['name' => 'email'], 'jon@mail.com'); + * ?> + * ``` + * + * @param $field + * @param $value + * @see \Codeception\Lib\InnerBrowser::fillField() + */ + public function fillField($field, $value) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('fillField', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Selects an option in a select tag or in radio button group. + * + * ``` php + * selectOption('form select[name=account]', 'Premium'); + * $I->selectOption('form input[name=payment]', 'Monthly'); + * $I->selectOption('//form/select[@name=account]', 'Monthly'); + * ?> + * ``` + * + * Provide an array for the second argument to select multiple options: + * + * ``` php + * selectOption('Which OS do you use?', array('Windows','Linux')); + * ?> + * ``` + * + * @param $select + * @param $option + * @see \Codeception\Lib\InnerBrowser::selectOption() + */ + public function selectOption($select, $option) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('selectOption', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Ticks a checkbox. For radio buttons, use the `selectOption` method instead. + * + * ``` php + * checkOption('#agree'); + * ?> + * ``` + * + * @param $option + * @see \Codeception\Lib\InnerBrowser::checkOption() + */ + public function checkOption($option) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('checkOption', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Unticks a checkbox. + * + * ``` php + * uncheckOption('#notify'); + * ?> + * ``` + * + * @param $option + * @see \Codeception\Lib\InnerBrowser::uncheckOption() + */ + public function uncheckOption($option) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('uncheckOption', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Attaches a file relative to the Codeception data directory to the given file upload field. + * + * ``` php + * attachFile('input[@type="file"]', 'prices.xls'); + * ?> + * ``` + * + * @param $field + * @param $filename + * @see \Codeception\Lib\InnerBrowser::attachFile() + */ + public function attachFile($field, $filename) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('attachFile', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * If your page triggers an ajax request, you can perform it manually. + * This action sends a GET ajax request with specified params. + * + * See ->sendAjaxPostRequest for examples. + * + * @param $uri + * @param $params + * @see \Codeception\Lib\InnerBrowser::sendAjaxGetRequest() + */ + public function sendAjaxGetRequest($uri, $params = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('sendAjaxGetRequest', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * If your page triggers an ajax request, you can perform it manually. + * This action sends a POST ajax request with specified params. + * Additional params can be passed as array. + * + * Example: + * + * Imagine that by clicking checkbox you trigger ajax request which updates user settings. + * We emulate that click by running this ajax request manually. + * + * ``` php + * sendAjaxPostRequest('/updateSettings', array('notifications' => true)); // POST + * $I->sendAjaxGetRequest('/updateSettings', array('notifications' => true)); // GET + * + * ``` + * + * @param $uri + * @param $params + * @see \Codeception\Lib\InnerBrowser::sendAjaxPostRequest() + */ + public function sendAjaxPostRequest($uri, $params = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('sendAjaxPostRequest', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * If your page triggers an ajax request, you can perform it manually. + * This action sends an ajax request with specified method and params. + * + * Example: + * + * You need to perform an ajax request specifying the HTTP method. + * + * ``` php + * sendAjaxRequest('PUT', '/posts/7', array('title' => 'new title')); + * + * ``` + * + * @param $method + * @param $uri + * @param $params + * @see \Codeception\Lib\InnerBrowser::sendAjaxRequest() + */ + public function sendAjaxRequest($method, $uri, $params = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('sendAjaxRequest', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Finds and returns the text contents of the given element. + * If a fuzzy locator is used, the element is found using CSS, XPath, and by matching the full page source by regular expression. + * + * ``` php + * grabTextFrom('h1'); + * $heading = $I->grabTextFrom('descendant-or-self::h1'); + * $value = $I->grabTextFrom('~ + * ``` + * + * @param $cssOrXPathOrRegex + * + * @return mixed + * @see \Codeception\Lib\InnerBrowser::grabTextFrom() + */ + public function grabTextFrom($cssOrXPathOrRegex) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('grabTextFrom', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Grabs the value of the given attribute value from the given element. + * Fails if element is not found. + * + * ``` php + * grabAttributeFrom('#tooltip', 'title'); + * ?> + * ``` + * + * + * @param $cssOrXpath + * @param $attribute + * @internal param $element + * @return mixed + * @see \Codeception\Lib\InnerBrowser::grabAttributeFrom() + */ + public function grabAttributeFrom($cssOrXpath, $attribute) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('grabAttributeFrom', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * + * @see \Codeception\Lib\InnerBrowser::grabMultiple() + */ + public function grabMultiple($cssOrXpath, $attribute = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('grabMultiple', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * @param $field + * + * @return array|mixed|null|string + * @see \Codeception\Lib\InnerBrowser::grabValueFrom() + */ + public function grabValueFrom($field) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('grabValueFrom', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Sets a cookie with the given name and value. + * You can set additional cookie params like `domain`, `path`, `expire`, `secure` in array passed as last argument. + * + * ``` php + * setCookie('PHPSESSID', 'el4ukv0kqbvoirg7nkp4dncpk3'); + * ?> + * ``` + * + * @param $name + * @param $val + * @param array $params + * + * @return mixed + * @see \Codeception\Lib\InnerBrowser::setCookie() + */ + public function setCookie($name, $val, $params = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('setCookie', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Grabs a cookie value. + * You can set additional cookie params like `domain`, `path` in array passed as last argument. + * + * @param $cookie + * + * @param array $params + * @return mixed + * @see \Codeception\Lib\InnerBrowser::grabCookie() + */ + public function grabCookie($cookie, $params = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('grabCookie', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that a cookie with the given name is set. + * You can set additional cookie params like `domain`, `path` as array passed in last argument. + * + * ``` php + * seeCookie('PHPSESSID'); + * ?> + * ``` + * + * @param $cookie + * @param array $params + * @return mixed + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::seeCookie() + */ + public function canSeeCookie($cookie, $params = null) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCookie', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that a cookie with the given name is set. + * You can set additional cookie params like `domain`, `path` as array passed in last argument. + * + * ``` php + * seeCookie('PHPSESSID'); + * ?> + * ``` + * + * @param $cookie + * @param array $params + * @return mixed + * @see \Codeception\Lib\InnerBrowser::seeCookie() + */ + public function seeCookie($cookie, $params = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCookie', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that there isn't a cookie with the given name. + * You can set additional cookie params like `domain`, `path` as array passed in last argument. + * + * @param $cookie + * + * @param array $params + * @return mixed + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::dontSeeCookie() + */ + public function cantSeeCookie($cookie, $params = null) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeCookie', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that there isn't a cookie with the given name. + * You can set additional cookie params like `domain`, `path` as array passed in last argument. + * + * @param $cookie + * + * @param array $params + * @return mixed + * @see \Codeception\Lib\InnerBrowser::dontSeeCookie() + */ + public function dontSeeCookie($cookie, $params = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeCookie', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Unsets cookie with the given name. + * You can set additional cookie params like `domain`, `path` in array passed as last argument. + * + * @param $cookie + * + * @param array $params + * @return mixed + * @see \Codeception\Lib\InnerBrowser::resetCookie() + */ + public function resetCookie($name, $params = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('resetCookie', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the given element exists on the page and is visible. + * You can also specify expected attributes of this element. + * + * ``` php + * seeElement('.error'); + * $I->seeElement('//form/input[1]'); + * $I->seeElement('input', ['name' => 'login']); + * $I->seeElement('input', ['value' => '123456']); + * + * // strict locator in first arg, attributes in second + * $I->seeElement(['css' => 'form input'], ['name' => 'login']); + * ?> + * ``` + * + * @param $selector + * @param array $attributes + * @return + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::seeElement() + */ + public function canSeeElement($selector, $attributes = null) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeElement', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the given element exists on the page and is visible. + * You can also specify expected attributes of this element. + * + * ``` php + * seeElement('.error'); + * $I->seeElement('//form/input[1]'); + * $I->seeElement('input', ['name' => 'login']); + * $I->seeElement('input', ['value' => '123456']); + * + * // strict locator in first arg, attributes in second + * $I->seeElement(['css' => 'form input'], ['name' => 'login']); + * ?> + * ``` + * + * @param $selector + * @param array $attributes + * @return + * @see \Codeception\Lib\InnerBrowser::seeElement() + */ + public function seeElement($selector, $attributes = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeElement', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the given element is invisible or not present on the page. + * You can also specify expected attributes of this element. + * + * ``` php + * dontSeeElement('.error'); + * $I->dontSeeElement('//form/input[1]'); + * $I->dontSeeElement('input', ['name' => 'login']); + * $I->dontSeeElement('input', ['value' => '123456']); + * ?> + * ``` + * + * @param $selector + * @param array $attributes + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::dontSeeElement() + */ + public function cantSeeElement($selector, $attributes = null) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeElement', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the given element is invisible or not present on the page. + * You can also specify expected attributes of this element. + * + * ``` php + * dontSeeElement('.error'); + * $I->dontSeeElement('//form/input[1]'); + * $I->dontSeeElement('input', ['name' => 'login']); + * $I->dontSeeElement('input', ['value' => '123456']); + * ?> + * ``` + * + * @param $selector + * @param array $attributes + * @see \Codeception\Lib\InnerBrowser::dontSeeElement() + */ + public function dontSeeElement($selector, $attributes = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeElement', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that there are a certain number of elements matched by the given locator on the page. + * + * ``` php + * seeNumberOfElements('tr', 10); + * $I->seeNumberOfElements('tr', [0,10]); //between 0 and 10 elements + * ?> + * ``` + * @param $selector + * @param mixed $expected : + * - string: strict number + * - array: range of numbers [0,10] + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::seeNumberOfElements() + */ + public function canSeeNumberOfElements($selector, $expected) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeNumberOfElements', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that there are a certain number of elements matched by the given locator on the page. + * + * ``` php + * seeNumberOfElements('tr', 10); + * $I->seeNumberOfElements('tr', [0,10]); //between 0 and 10 elements + * ?> + * ``` + * @param $selector + * @param mixed $expected : + * - string: strict number + * - array: range of numbers [0,10] + * @see \Codeception\Lib\InnerBrowser::seeNumberOfElements() + */ + public function seeNumberOfElements($selector, $expected) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeNumberOfElements', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the given option is selected. + * + * ``` php + * seeOptionIsSelected('#form input[name=payment]', 'Visa'); + * ?> + * ``` + * + * @param $selector + * @param $optionText + * + * @return mixed + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::seeOptionIsSelected() + */ + public function canSeeOptionIsSelected($selector, $optionText) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeOptionIsSelected', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the given option is selected. + * + * ``` php + * seeOptionIsSelected('#form input[name=payment]', 'Visa'); + * ?> + * ``` + * + * @param $selector + * @param $optionText + * + * @return mixed + * @see \Codeception\Lib\InnerBrowser::seeOptionIsSelected() + */ + public function seeOptionIsSelected($selector, $optionText) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeOptionIsSelected', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the given option is not selected. + * + * ``` php + * dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); + * ?> + * ``` + * + * @param $selector + * @param $optionText + * + * @return mixed + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::dontSeeOptionIsSelected() + */ + public function cantSeeOptionIsSelected($selector, $optionText) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeOptionIsSelected', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the given option is not selected. + * + * ``` php + * dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); + * ?> + * ``` + * + * @param $selector + * @param $optionText + * + * @return mixed + * @see \Codeception\Lib\InnerBrowser::dontSeeOptionIsSelected() + */ + public function dontSeeOptionIsSelected($selector, $optionText) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeOptionIsSelected', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Asserts that current page has 404 response status code. + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::seePageNotFound() + */ + public function canSeePageNotFound() { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seePageNotFound', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Asserts that current page has 404 response status code. + * @see \Codeception\Lib\InnerBrowser::seePageNotFound() + */ + public function seePageNotFound() { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seePageNotFound', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that response code is equal to value provided. + * + * @param $code + * + * @return mixed + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::seeResponseCodeIs() + */ + public function canSeeResponseCodeIs($code) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeResponseCodeIs', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that response code is equal to value provided. + * + * @param $code + * + * @return mixed + * @see \Codeception\Lib\InnerBrowser::seeResponseCodeIs() + */ + public function seeResponseCodeIs($code) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeResponseCodeIs', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the page title contains the given string. + * + * ``` php + * seeInTitle('Blog - Post #1'); + * ?> + * ``` + * + * @param $title + * + * @return mixed + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::seeInTitle() + */ + public function canSeeInTitle($title) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInTitle', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the page title contains the given string. + * + * ``` php + * seeInTitle('Blog - Post #1'); + * ?> + * ``` + * + * @param $title + * + * @return mixed + * @see \Codeception\Lib\InnerBrowser::seeInTitle() + */ + public function seeInTitle($title) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInTitle', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the page title does not contain the given string. + * + * @param $title + * + * @return mixed + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::dontSeeInTitle() + */ + public function cantSeeInTitle($title) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInTitle', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the page title does not contain the given string. + * + * @param $title + * + * @return mixed + * @see \Codeception\Lib\InnerBrowser::dontSeeInTitle() + */ + public function dontSeeInTitle($title) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInTitle', func_get_args())); + } +} diff --git a/tests/_support/_generated/FunctionalTesterActions.php b/tests/_support/_generated/FunctionalTesterActions.php new file mode 100644 index 0000000000..a21488525a --- /dev/null +++ b/tests/_support/_generated/FunctionalTesterActions.php @@ -0,0 +1,350 @@ +getScenario()->runStep(new \Codeception\Step\Condition('amInPath', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Opens a file and stores it's content. + * + * Usage: + * + * ``` php + * openFile('composer.json'); + * $I->seeInThisFile('codeception/codeception'); + * ?> + * ``` + * + * @param $filename + * @see \Codeception\Module\Filesystem::openFile() + */ + public function openFile($filename) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('openFile', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Deletes a file + * + * ``` php + * deleteFile('composer.lock'); + * ?> + * ``` + * + * @param $filename + * @see \Codeception\Module\Filesystem::deleteFile() + */ + public function deleteFile($filename) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('deleteFile', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Deletes directory with all subdirectories + * + * ``` php + * deleteDir('vendor'); + * ?> + * ``` + * + * @param $dirname + * @see \Codeception\Module\Filesystem::deleteDir() + */ + public function deleteDir($dirname) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('deleteDir', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Copies directory with all contents + * + * ``` php + * copyDir('vendor','old_vendor'); + * ?> + * ``` + * + * @param $src + * @param $dst + * @see \Codeception\Module\Filesystem::copyDir() + */ + public function copyDir($src, $dst) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('copyDir', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks If opened file has `text` in it. + * + * Usage: + * + * ``` php + * openFile('composer.json'); + * $I->seeInThisFile('codeception/codeception'); + * ?> + * ``` + * + * @param $text + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Module\Filesystem::seeInThisFile() + */ + public function canSeeInThisFile($text) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInThisFile', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks If opened file has `text` in it. + * + * Usage: + * + * ``` php + * openFile('composer.json'); + * $I->seeInThisFile('codeception/codeception'); + * ?> + * ``` + * + * @param $text + * @see \Codeception\Module\Filesystem::seeInThisFile() + */ + public function seeInThisFile($text) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInThisFile', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks the strict matching of file contents. + * Unlike `seeInThisFile` will fail if file has something more than expected lines. + * Better to use with HEREDOC strings. + * Matching is done after removing "\r" chars from file content. + * + * ``` php + * openFile('process.pid'); + * $I->seeFileContentsEqual('3192'); + * ?> + * ``` + * + * @param $text + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Module\Filesystem::seeFileContentsEqual() + */ + public function canSeeFileContentsEqual($text) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeFileContentsEqual', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks the strict matching of file contents. + * Unlike `seeInThisFile` will fail if file has something more than expected lines. + * Better to use with HEREDOC strings. + * Matching is done after removing "\r" chars from file content. + * + * ``` php + * openFile('process.pid'); + * $I->seeFileContentsEqual('3192'); + * ?> + * ``` + * + * @param $text + * @see \Codeception\Module\Filesystem::seeFileContentsEqual() + */ + public function seeFileContentsEqual($text) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeFileContentsEqual', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks If opened file doesn't contain `text` in it + * + * ``` php + * openFile('composer.json'); + * $I->dontSeeInThisFile('codeception/codeception'); + * ?> + * ``` + * + * @param $text + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Module\Filesystem::dontSeeInThisFile() + */ + public function cantSeeInThisFile($text) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInThisFile', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks If opened file doesn't contain `text` in it + * + * ``` php + * openFile('composer.json'); + * $I->dontSeeInThisFile('codeception/codeception'); + * ?> + * ``` + * + * @param $text + * @see \Codeception\Module\Filesystem::dontSeeInThisFile() + */ + public function dontSeeInThisFile($text) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInThisFile', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Deletes a file + * @see \Codeception\Module\Filesystem::deleteThisFile() + */ + public function deleteThisFile() { + return $this->getScenario()->runStep(new \Codeception\Step\Action('deleteThisFile', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks if file exists in path. + * Opens a file when it's exists + * + * ``` php + * seeFileFound('UserModel.php','app/models'); + * ?> + * ``` + * + * @param $filename + * @param string $path + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Module\Filesystem::seeFileFound() + */ + public function canSeeFileFound($filename, $path = null) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeFileFound', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks if file exists in path. + * Opens a file when it's exists + * + * ``` php + * seeFileFound('UserModel.php','app/models'); + * ?> + * ``` + * + * @param $filename + * @param string $path + * @see \Codeception\Module\Filesystem::seeFileFound() + */ + public function seeFileFound($filename, $path = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeFileFound', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks if file does not exist in path + * + * @param $filename + * @param string $path + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Module\Filesystem::dontSeeFileFound() + */ + public function cantSeeFileFound($filename, $path = null) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeFileFound', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks if file does not exist in path + * + * @param $filename + * @param string $path + * @see \Codeception\Module\Filesystem::dontSeeFileFound() + */ + public function dontSeeFileFound($filename, $path = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeFileFound', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Erases directory contents + * + * ``` php + * cleanDir('logs'); + * ?> + * ``` + * + * @param $dirname + * @see \Codeception\Module\Filesystem::cleanDir() + */ + public function cleanDir($dirname) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('cleanDir', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Saves contents to file + * + * @param $filename + * @param $contents + * @see \Codeception\Module\Filesystem::writeToFile() + */ + public function writeToFile($filename, $contents) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('writeToFile', func_get_args())); + } +} diff --git a/tests/_support/_generated/UnitTesterActions.php b/tests/_support/_generated/UnitTesterActions.php new file mode 100644 index 0000000000..e9fcbf010b --- /dev/null +++ b/tests/_support/_generated/UnitTesterActions.php @@ -0,0 +1,348 @@ +getScenario()->runStep(new \Codeception\Step\Action('assertEquals', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that two variables are not equal + * + * @param $expected + * @param $actual + * @param string $message + * @see \Codeception\Module\Asserts::assertNotEquals() + */ + public function assertNotEquals($expected, $actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotEquals', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that two variables are same + * + * @param $expected + * @param $actual + * @param string $message + * + * @return mixed + * @see \Codeception\Module\Asserts::assertSame() + */ + public function assertSame($expected, $actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertSame', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that two variables are not same + * + * @param $expected + * @param $actual + * @param string $message + * @see \Codeception\Module\Asserts::assertNotSame() + */ + public function assertNotSame($expected, $actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotSame', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that actual is greater than expected + * + * @param $expected + * @param $actual + * @param string $message + * @see \Codeception\Module\Asserts::assertGreaterThan() + */ + public function assertGreaterThan($expected, $actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertGreaterThan', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * @deprecated + * @see \Codeception\Module\Asserts::assertGreaterThen() + */ + public function assertGreaterThen($expected, $actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertGreaterThen', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that actual is greater or equal than expected + * + * @param $expected + * @param $actual + * @param string $message + * @see \Codeception\Module\Asserts::assertGreaterThanOrEqual() + */ + public function assertGreaterThanOrEqual($expected, $actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertGreaterThanOrEqual', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * @deprecated + * @see \Codeception\Module\Asserts::assertGreaterThenOrEqual() + */ + public function assertGreaterThenOrEqual($expected, $actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertGreaterThenOrEqual', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that actual is less than expected + * + * @param $expected + * @param $actual + * @param string $message + * @see \Codeception\Module\Asserts::assertLessThan() + */ + public function assertLessThan($expected, $actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertLessThan', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that actual is less or equal than expected + * + * @param $expected + * @param $actual + * @param string $message + * @see \Codeception\Module\Asserts::assertLessThanOrEqual() + */ + public function assertLessThanOrEqual($expected, $actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertLessThanOrEqual', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that haystack contains needle + * + * @param $needle + * @param $haystack + * @param string $message + * @see \Codeception\Module\Asserts::assertContains() + */ + public function assertContains($needle, $haystack, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertContains', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that haystack doesn't contain needle. + * + * @param $needle + * @param $haystack + * @param string $message + * @see \Codeception\Module\Asserts::assertNotContains() + */ + public function assertNotContains($needle, $haystack, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotContains', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that string match with pattern + * + * @param string $pattern + * @param string $string + * @param string $message + * @see \Codeception\Module\Asserts::assertRegExp() + */ + public function assertRegExp($pattern, $string, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertRegExp', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that string not match with pattern + * + * @param string $pattern + * @param string $string + * @param string $message + * @see \Codeception\Module\Asserts::assertNotRegExp() + */ + public function assertNotRegExp($pattern, $string, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotRegExp', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that variable is empty. + * + * @param $actual + * @param string $message + * @see \Codeception\Module\Asserts::assertEmpty() + */ + public function assertEmpty($actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertEmpty', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that variable is not empty. + * + * @param $actual + * @param string $message + * @see \Codeception\Module\Asserts::assertNotEmpty() + */ + public function assertNotEmpty($actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotEmpty', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that variable is NULL + * + * @param $actual + * @param string $message + * @see \Codeception\Module\Asserts::assertNull() + */ + public function assertNull($actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNull', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that variable is not NULL + * + * @param $actual + * @param string $message + * @see \Codeception\Module\Asserts::assertNotNull() + */ + public function assertNotNull($actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotNull', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that condition is positive. + * + * @param $condition + * @param string $message + * @see \Codeception\Module\Asserts::assertTrue() + */ + public function assertTrue($condition, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertTrue', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that condition is negative. + * + * @param $condition + * @param string $message + * @see \Codeception\Module\Asserts::assertFalse() + */ + public function assertFalse($condition, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFalse', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks if file exists + * + * @param string $filename + * @param string $message + * @see \Codeception\Module\Asserts::assertFileExists() + */ + public function assertFileExists($filename, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFileExists', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks if file doesn't exist + * + * @param string $filename + * @param string $message + * @see \Codeception\Module\Asserts::assertFileNotExists() + */ + public function assertFileNotExists($filename, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFileNotExists', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Fails the test with message. + * + * @param $message + * @see \Codeception\Module\Asserts::fail() + */ + public function fail($message) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('fail', func_get_args())); + } +} From 20c35fd0bb0f4d7872261208cd8bd1be641b05f5 Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Tue, 20 Oct 2015 20:26:18 -0700 Subject: [PATCH 006/119] Okay, most migrations are kinda-sorta working now, but validations aren't --- ...7_04_212443_create_custom_fields_table.php | 9 ++++--- ...6_create_custom_field_custom_fieldset.php} | 12 +++------ ..._09_22_000104_create_custom_fieldsets.php} | 11 ++++---- ...09_22_003321_add_fieldset_id_to_assets.php | 10 ++++--- .../2015_09_22_003413_migrate_mac_address.php | 26 ++++++++++++++++--- app/models/CustomField.php | 24 ++++++++++++++--- app/models/CustomFieldset.php | 4 ++- app/models/Model.php | 6 ++--- 8 files changed, 70 insertions(+), 32 deletions(-) rename app/database/migrations/{2015_09_21_235926_create_custom_field_fieldset.php => 2015_09_21_235926_create_custom_field_custom_fieldset.php} (56%) rename app/database/migrations/{2015_09_22_000104_create_fieldset.php => 2015_09_22_000104_create_custom_fieldsets.php} (58%) diff --git a/app/database/migrations/2015_07_04_212443_create_custom_fields_table.php b/app/database/migrations/2015_07_04_212443_create_custom_fields_table.php index 05bf670adb..b2dbbebb8c 100644 --- a/app/database/migrations/2015_07_04_212443_create_custom_fields_table.php +++ b/app/database/migrations/2015_07_04_212443_create_custom_fields_table.php @@ -14,10 +14,11 @@ class CreateCustomFieldsTable extends Migration public function up() { Schema::create('custom_fields', function ($table) { - $table->string('name'); - $table->string('format'); - $table->string('element'); - $table->timestamps(); + $table->increments('id'); + $table->string('name'); + $table->string('format'); + $table->string('element'); + $table->timestamps(); }); } diff --git a/app/database/migrations/2015_09_21_235926_create_custom_field_fieldset.php b/app/database/migrations/2015_09_21_235926_create_custom_field_custom_fieldset.php similarity index 56% rename from app/database/migrations/2015_09_21_235926_create_custom_field_fieldset.php rename to app/database/migrations/2015_09_21_235926_create_custom_field_custom_fieldset.php index 186414dbbf..ef26b6f181 100644 --- a/app/database/migrations/2015_09_21_235926_create_custom_field_fieldset.php +++ b/app/database/migrations/2015_09_21_235926_create_custom_field_custom_fieldset.php @@ -3,7 +3,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; -class CreateCustomFieldFieldset extends Migration { +class CreateCustomFieldCustomFieldset extends Migration { /** * Run the migrations. @@ -12,10 +12,10 @@ class CreateCustomFieldFieldset extends Migration { */ public function up() { - Schema::table('custom_field_fieldset', function(Blueprint $table) + Schema::create('custom_field_custom_fieldset', function(Blueprint $table) { $table->integer('custom_field_id'); - $table->integer('fieldset_id'); + $table->integer('custom_fieldset_id'); $table->integer('order'); $table->boolean('required'); @@ -29,11 +29,7 @@ class CreateCustomFieldFieldset extends Migration { */ public function down() { - Schema::drop('custom_field_fieldset'); - // Schema::table('custom_field_fieldset', function(Blueprint $table) - // { - // // - // }); + Schema::drop('custom_field_custom_fieldsets'); } } diff --git a/app/database/migrations/2015_09_22_000104_create_fieldset.php b/app/database/migrations/2015_09_22_000104_create_custom_fieldsets.php similarity index 58% rename from app/database/migrations/2015_09_22_000104_create_fieldset.php rename to app/database/migrations/2015_09_22_000104_create_custom_fieldsets.php index 37eea586ee..766063d673 100644 --- a/app/database/migrations/2015_09_22_000104_create_fieldset.php +++ b/app/database/migrations/2015_09_22_000104_create_custom_fieldsets.php @@ -3,7 +3,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; -class CreateFieldset extends Migration { +class CreateCustomFieldsets extends Migration { /** * Run the migrations. @@ -12,8 +12,10 @@ class CreateFieldset extends Migration { */ public function up() { - Schema::table('fieldset', function(Blueprint $table) + Schema::create('custom_fieldsets', function(Blueprint $table) { + $table->increments('id'); + $table->string('name'); // }); } @@ -25,10 +27,7 @@ class CreateFieldset extends Migration { */ public function down() { - Schema::table('fieldset', function(Blueprint $table) - { - // - }); + Schema::drop('custom_fieldsets'); } } diff --git a/app/database/migrations/2015_09_22_003321_add_fieldset_id_to_assets.php b/app/database/migrations/2015_09_22_003321_add_fieldset_id_to_assets.php index 3f11b8b920..7771b30e0e 100644 --- a/app/database/migrations/2015_09_22_003321_add_fieldset_id_to_assets.php +++ b/app/database/migrations/2015_09_22_003321_add_fieldset_id_to_assets.php @@ -13,9 +13,9 @@ class AddFieldsetIdToAssets extends Migration { public function up() { Schema::table('models', function (Blueprint $table) { - $table->integer('fieldset_id'); - } - // + $table->integer('fieldset_id')->nullable(); + }); + } /** @@ -25,7 +25,9 @@ class AddFieldsetIdToAssets extends Migration { */ public function down() { - // + Schema::table('models',function (Blueprint $table) { + $table->dropColumn('fieldset_id'); + }); } } diff --git a/app/database/migrations/2015_09_22_003413_migrate_mac_address.php b/app/database/migrations/2015_09_22_003413_migrate_mac_address.php index 0c65d294f4..92f3f41d47 100644 --- a/app/database/migrations/2015_09_22_003413_migrate_mac_address.php +++ b/app/database/migrations/2015_09_22_003413_migrate_mac_address.php @@ -14,9 +14,23 @@ class MigrateMacAddress extends Migration { { // //create empty 'default' fieldset' - Fieldset::create({name: "Plain Asset"}); - $f2=Fieldset::create({name: "Asset with MAC Address"}); - $f2->fields()->create({name: "MAC Address",required: false, order: 1}); + //$f1=Fieldset::create([name => "Default Asset"]); + $f2=new CustomFieldset(['name' => "Asset with MAC Address"]); + if(!$f2->save()) { + throw new Exception("couldn't save customfieldset"); + } + $mac=new CustomField(['name' => "MAC Address",'format' =>'MAC','element'=>'text']); + if(!$mac->save()) { + throw new Exception("Mac ID: $macid"); + } + + $f2->fields()->save($mac,['required' => false, 'order' => 1]); + //$f2->push(); + + Model::where(["show_mac_address" => true])->update(["fieldset_id"=>$f2->id]); + Schema::table("models",function (Blueprint $table) { + $table->renameColumn('show_mac_address','deprecated_mac_address'); + }); } /** @@ -27,6 +41,12 @@ class MigrateMacAddress extends Migration { public function down() { // + $f=CustomFieldset::where(["name" => "Asset with MAC Address"])->first(); + $f->fields()->delete(); + $f->delete(); + Schema::table("models",function(Blueprint $table) { + $table->renameColumn("deprecated_mac_address","show_mac_address"); + }); } } diff --git a/app/models/CustomField.php b/app/models/CustomField.php index 4678ecbdcd..1ddc878bb3 100644 --- a/app/models/CustomField.php +++ b/app/models/CustomField.php @@ -2,6 +2,7 @@ class CustomField extends Elegant { + public $guarded=["id"]; public static $PredefinedFormats=[ "ALPHA" => "[a-zA-Z]*", "NUMERIC" => "[0-9]*", @@ -9,7 +10,22 @@ class CustomField extends Elegant "IP" => "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])" ]; - public static function saving($custom_field) { + public static $table_name="assets"; + + public static function name_to_db_name($name) + { + return preg_replace("/\s/","_",strtolower($name)); + } + + public static function creating($custom_field) { + if(in_array($custom_field->db_column_name(),Schema::getColumnListing(CustomField::$table_name))) { + //field already exists when making a new custom field; fail. + return false; + } + return db::exec("ALTER TABLE ".CustomField::$table_name." ADD COLUMN (".$custom_field->db_column_name()." TEXT)"); + } + + public static function updating($custom_field) { //print(" SAVING CALLBACK FIRING!!!!! "); if($custom_field->isDirty("name")) { //print("DIRTINESS DETECTED!"); @@ -21,9 +37,11 @@ class CustomField extends Elegant }*/ //print("Fields are: ".print_r($fields,true)); - if(in_array($custom_field->db_column_name(),Schema::getColumnListing('assets'))) { + if(in_array($custom_field->db_column_name(),Schema::getColumnListing(CustomField::$table_name))) { + //field already exists when renaming a custom field return false; } + return db::exec("UPDATE ".CustomField::$table_name." RENAME ".self::name_to_db_name($custom_field->get_original("name"))." TO ".$custom_field->db_column_name()); } return true; } @@ -57,7 +75,7 @@ class CustomField extends Elegant } public function db_column_name() { - return preg_replace("/\s/","_",strtolower($this->name)); + return self::name_to_db_name($this->name); } //mutators for 'format' attribute diff --git a/app/models/CustomFieldset.php b/app/models/CustomFieldset.php index 58afc69e5e..7cbd749404 100644 --- a/app/models/CustomFieldset.php +++ b/app/models/CustomFieldset.php @@ -1,8 +1,10 @@ belongsToMany('CustomField'); + return $this->belongsToMany('CustomField')->withPivot(["required","order"]); } //requiredness goes *here* diff --git a/app/models/Model.php b/app/models/Model.php index e3c694bef2..32695c38fb 100755 --- a/app/models/Model.php +++ b/app/models/Model.php @@ -45,9 +45,9 @@ class Model extends Elegant public function custom_fieldset() { - $foo=new CustomField(); - $foo2=new CustomFieldset(); - return $this->belongsTo('Fieldset','fieldset_id'); + // $foo=new CustomField(); + // $foo2=new CustomFieldset(); + return $this->belongsTo('custom_fieldset','fieldset_id'); } /** From 5890d265451d6bccf363d3034f8b9ed6cb15783c Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Thu, 22 Oct 2015 00:38:07 -0700 Subject: [PATCH 007/119] Terribly rough Custom Fields creation --- app/controllers/CustomFieldsController.php | 133 ++++++++++++++++++ app/controllers/admin/AssetsController.php | 17 ++- app/controllers/admin/ModelsController.php | 3 +- ...26_create_custom_field_custom_fieldset.php | 2 +- .../2015_09_22_003413_migrate_mac_address.php | 42 +++++- app/helpers.php | 11 ++ app/models/CustomField.php | 66 ++++----- app/models/CustomFieldset.php | 16 ++- app/models/Model.php | 6 +- app/routes.php | 7 + .../backend/custom_fields/create.blade.php | 6 + .../custom_fields/create_field.blade.php | 9 ++ .../backend/custom_fields/index.blade.php | 18 +++ .../backend/custom_fields/show.blade.php | 12 ++ app/views/backend/hardware/edit.blade.php | 17 ++- app/views/backend/hardware/index.blade.php | 6 +- app/views/backend/hardware/view.blade.php | 17 ++- app/views/backend/models/edit.blade.php | 4 +- 18 files changed, 330 insertions(+), 62 deletions(-) create mode 100644 app/controllers/CustomFieldsController.php create mode 100644 app/views/backend/custom_fields/create.blade.php create mode 100644 app/views/backend/custom_fields/create_field.blade.php create mode 100644 app/views/backend/custom_fields/index.blade.php create mode 100644 app/views/backend/custom_fields/show.blade.php diff --git a/app/controllers/CustomFieldsController.php b/app/controllers/CustomFieldsController.php new file mode 100644 index 0000000000..c56156ee37 --- /dev/null +++ b/app/controllers/CustomFieldsController.php @@ -0,0 +1,133 @@ +with("custom_fieldsets",CustomFieldset::all())->with("custom_fields",CustomField::all()); + } + + + /** + * Show the form for creating a new resource. + * + * @return Response + */ + public function getCreate() + { + // + return View::make("backend.custom_fields.create"); + } + + + /** + * Store a newly created resource in storage. + * + * @return Response + */ + public function postIndex() + { + // + $cfset=new CustomFieldset(["name" => Input::get("name")]); + $cfset->save(); + return Redirect::to("/custom_fieldsets/".$cfset->id); //redirect(["asdf" => "alskdjf"]); + + } + + public function postAssociate($id) + { + print "ID is: $id"; + $set=CustomFieldset::find($id); + $results=$set->fields()->attach(Input::get('field_id'),["required" => (Input::get('required') == "on"),"order" => Input::get('order')]); + //return "I assoced it. Results: $results"; + return Redirect::to("/custom_fieldsets/".$id); //redirect(["asdf" => "alskdjf"]); + } + + public function getCreateField() + { + return View::make("backend.custom_fields.create_field"); + } + + public function postCreateField() + { + $field=new CustomField(["name" => Input::get("name"),"element" => Input::get("element")]); + if(!in_array(Input::get('format'),["ALPHA","NUMERIC","MAC","IP"])) { + $field->format=Input::get("custom_format"); + } else { + $field->format=Input::get('format'); + } + $results=$field->save(); + //return "postCreateField: $results"; + if ($results) { + return Redirect::to("/custom_fieldsets/"); + } else { + return Redirect::to("/custom_fieldsets/create-field"); + } + } + + /** + * Display the specified resource. + * + * @param int $id + * @return Response + */ + public function missingMethod($parameters = array()) + { + $id=$parameters[0]; + $cfset=CustomFieldset::find($id); + + //print_r($parameters); + // + $maxid=0; + foreach($cfset->fields AS $field) { + if($field->pivot->order > $maxid) { + $maxid=$field->pivot->order; + } + } + return View::make("backend.custom_fields.show")->with("custom_fieldset",$cfset)->with("maxid",$maxid+1); + } + + + /** + * Show the form for editing the specified resource. + * + * @param int $id + * @return Response + */ + public function edit($id) + { + // + } + + + /** + * Update the specified resource in storage. + * + * @param int $id + * @return Response + */ + public function update($id) + { + // + } + + + /** + * Remove the specified resource from storage. + * + * @param int $id + * @return Response + */ + public function destroy($id) + { + // + } + + +} diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index 4c74d11718..ad516e3cf8 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -242,9 +242,20 @@ class AssetsController extends AdminController // Redirect to the asset management page with error return Redirect::to('hardware')->with('error', Lang::get('admin/hardware/message.does_not_exist')); } + + $input=Input::all(); + if($this->model->fieldset) + { + foreach($this->model->fieldset->fields AS $field) { + $input[$field->db_column_name()]=$input->fields[$field->db_column_name()]; + } + unset($input['fields']); + } //attempt to validate - $validator = Validator::make(Input::all(), $asset->validationRules($assetId)); + $validator = Validator::make($input, $asset->validationRules($assetId) + $this->fieldset->validation_rules()); + + $custom_errors=[]; if ($validator->fails()) { @@ -264,7 +275,7 @@ class AssetsController extends AdminController if (e(Input::get('warranty_months')) == '') { $asset->warranty_months = NULL; } else { - $asset->warranty_months = e(Input::get('warranty_months')); + $asset->warranty_months = e(Input::get('warranty_months')); } if (e(Input::get('purchase_cost')) == '') { @@ -1066,7 +1077,7 @@ class AssetsController extends AdminController public function getDatatable($status = null) { - $assets = Asset::with('model','assigneduser','assigneduser.userloc','assetstatus','defaultLoc','assetlog','model','model.category')->Hardware()->select(array('id', 'name','model_id','assigned_to','asset_tag','serial','status_id','purchase_date','deleted_at','rtd_location_id','notes','order_number','mac_address','warranty_months')); + $assets = Asset::with('model','assigneduser','assigneduser.userloc','assetstatus','defaultLoc','assetlog','model','model.category')->Hardware()->select(array('id', 'name','model_id','assigned_to','asset_tag','serial','status_id','purchase_date','deleted_at','rtd_location_id','notes','order_number','warranty_months')); switch ($status) { diff --git a/app/controllers/admin/ModelsController.php b/app/controllers/admin/ModelsController.php index efc4cc6534..3b7a96e6e3 100755 --- a/app/controllers/admin/ModelsController.php +++ b/app/controllers/admin/ModelsController.php @@ -236,7 +236,8 @@ class ModelsController extends AdminController $model->modelno = e(Input::get('modelno')); $model->manufacturer_id = e(Input::get('manufacturer_id')); $model->category_id = e(Input::get('category_id')); - $model->show_mac_address = e(Input::get('show_mac_address', '0')); + //$model->show_mac_address = e(Input::get('show_mac_address', '0')); + $model->fieldset_id = e(Input::get('custom_fieldset')); if (Input::file('image')) { $image = Input::file('image'); diff --git a/app/database/migrations/2015_09_21_235926_create_custom_field_custom_fieldset.php b/app/database/migrations/2015_09_21_235926_create_custom_field_custom_fieldset.php index ef26b6f181..e219f2ca86 100644 --- a/app/database/migrations/2015_09_21_235926_create_custom_field_custom_fieldset.php +++ b/app/database/migrations/2015_09_21_235926_create_custom_field_custom_fieldset.php @@ -29,7 +29,7 @@ class CreateCustomFieldCustomFieldset extends Migration { */ public function down() { - Schema::drop('custom_field_custom_fieldsets'); + Schema::drop('custom_field_custom_fieldset'); } } diff --git a/app/database/migrations/2015_09_22_003413_migrate_mac_address.php b/app/database/migrations/2015_09_22_003413_migrate_mac_address.php index 92f3f41d47..75a07e46fb 100644 --- a/app/database/migrations/2015_09_22_003413_migrate_mac_address.php +++ b/app/database/migrations/2015_09_22_003413_migrate_mac_address.php @@ -12,6 +12,9 @@ class MigrateMacAddress extends Migration { */ public function up() { + DB::getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string'); + + // //create empty 'default' fieldset' //$f1=Fieldset::create([name => "Default Asset"]); @@ -19,18 +22,41 @@ class MigrateMacAddress extends Migration { if(!$f2->save()) { throw new Exception("couldn't save customfieldset"); } - $mac=new CustomField(['name' => "MAC Address",'format' =>'MAC','element'=>'text']); - if(!$mac->save()) { - throw new Exception("Mac ID: $macid"); + $macid=DB::table('custom_fields')->insertGetId([ + 'name' => "MAC Address", + 'format' => CustomField::$PredefinedFormats['MAC'], + 'element'=>'text']); + if(!$macid) { + throw new Exception("Can't save MAC Custom field: $macid"); } - $f2->fields()->save($mac,['required' => false, 'order' => 1]); + $f2->fields()->attach($macid,['required' => false, 'order' => 1]); //$f2->push(); - Model::where(["show_mac_address" => true])->update(["fieldset_id"=>$f2->id]); - Schema::table("models",function (Blueprint $table) { + //up to *HERE* works just fine + print "THIS IS FINE!"; + // $ans2=Schema::table("assets",function (Blueprint $table) { + // $table->renameColumn('mac_address','_snipeit_mac_address'); + // }); + DB::statement("ALTER TABLE assets CHANGE mac_address _snipeit_mac_address varchar(255)"); + // print "NOTHING WORKS"; + // if(!$ans2) { + // throw new Exception("Couldn't rename mac_address collumn in Assets table"); + // } + $ans=Schema::table("models",function (Blueprint $table) { $table->renameColumn('show_mac_address','deprecated_mac_address'); }); + print "Does this even ahppen"; + // if(!$ans) { + // throw new Exception("couldn't rename show_mac_address column in Models table"); + // } + // $shit=Schema::table("assets",function (Blueprint $table) { + // $table->renmaeColmnu("fuck you you fucking piece of shit","die in a fucking fire you asshole"); + // }); + // print "seriously"; + // if(!$shit) { + // throw new Exception("something taht should've failed failed. Good."); + // } } /** @@ -47,6 +73,10 @@ class MigrateMacAddress extends Migration { Schema::table("models",function(Blueprint $table) { $table->renameColumn("deprecated_mac_address","show_mac_address"); }); + DB::statement("ALTER TABLE assets CHANGE _snipeit_mac_address mac_address varchar(255)"); + // Schema::table("assets",function (Blueprint $table) { + // $table->renameColumn('_snipeit_mac_address','mac_address'); + // }); } } diff --git a/app/helpers.php b/app/helpers.php index 257a098851..ab5d24d2b8 100755 --- a/app/helpers.php +++ b/app/helpers.php @@ -89,6 +89,17 @@ function usersList() { return $users_list; } +function customFieldsetList() { + $customfields=CustomFieldset::lists('name','id'); + return array('' => Lang::get('general.no_custom_field')) + $customfields; +} + +function predefined_formats() { + $keys=array_keys(CustomField::$PredefinedFormats); + $stuff=array_combine($keys,$keys); + return $stuff+["" => "Custom Format..."]; +} + function barcodeDimensions ($barcode_type = 'QRCODE') { if ($barcode_type == 'C128') { $size['height'] = '-1'; diff --git a/app/models/CustomField.php b/app/models/CustomField.php index 1ddc878bb3..e7816f67b2 100644 --- a/app/models/CustomField.php +++ b/app/models/CustomField.php @@ -14,36 +14,40 @@ class CustomField extends Elegant public static function name_to_db_name($name) { - return preg_replace("/\s/","_",strtolower($name)); + return "_snipeit_".preg_replace("/\s/","_",strtolower($name)); } - public static function creating($custom_field) { - if(in_array($custom_field->db_column_name(),Schema::getColumnListing(CustomField::$table_name))) { - //field already exists when making a new custom field; fail. - return false; - } - return db::exec("ALTER TABLE ".CustomField::$table_name." ADD COLUMN (".$custom_field->db_column_name()." TEXT)"); - } - - public static function updating($custom_field) { - //print(" SAVING CALLBACK FIRING!!!!! "); - if($custom_field->isDirty("name")) { - //print("DIRTINESS DETECTED!"); - //$fields=array_keys($custom_field->getAttributes()); - ; - //add timestamp fields, add id column - //array_push($fields,$custom_field->getKeyName()); - /*if($custom_field::timestamps) { - - }*/ - //print("Fields are: ".print_r($fields,true)); - if(in_array($custom_field->db_column_name(),Schema::getColumnListing(CustomField::$table_name))) { - //field already exists when renaming a custom field + public static function boot() + { + self::creating(function ($custom_field) { + + if(in_array($custom_field->db_column_name(),Schema::getColumnListing(DB::getTablePrefix().CustomField::$table_name))) { + //field already exists when making a new custom field; fail. return false; } - return db::exec("UPDATE ".CustomField::$table_name." RENAME ".self::name_to_db_name($custom_field->get_original("name"))." TO ".$custom_field->db_column_name()); - } - return true; + return DB::statement("ALTER TABLE ".DB::getTablePrefix().CustomField::$table_name." ADD COLUMN (".$custom_field->db_column_name()." TEXT)"); + }); + + self::updating(function ($custom_field) { + //print(" SAVING CALLBACK FIRING!!!!! "); + if($custom_field->isDirty("name")) { + //print("DIRTINESS DETECTED!"); + //$fields=array_keys($custom_field->getAttributes()); + //; + //add timestamp fields, add id column + //array_push($fields,$custom_field->getKeyName()); + /*if($custom_field::timestamps) { + + }*/ + //print("Fields are: ".print_r($fields,true)); + if(in_array($custom_field->db_column_name(),Schema::getColumnListing(CustomField::$table_name))) { + //field already exists when renaming a custom field + return false; + } + return DB::statement("UPDATE ".CustomField::$table_name." RENAME ".self::name_to_db_name($custom_field->get_original("name"))." TO ".$custom_field->db_column_name()); + } + return true; + }); } /*public static function boot() { @@ -56,13 +60,9 @@ class CustomField extends Elegant }*/ public function fieldset() { - return $this->belongsToMany('Fieldset'); //?!?!?!?!?!? + return $this->belongsToMany('CustomFieldset'); //?!?!?!?!?!? } - - public $rules=[ - 'name' => 'unique_column' - ]; - + //public function //need helper to go from regex->English @@ -89,7 +89,7 @@ class CustomField extends Elegant } public function setFormatAttribute($value) { - if(self::$PredefinedFormats[$value]) { + if(isset(self::$PredefinedFormats[$value])) { $this->attributes['format']=self::$PredefinedFormats[$value]; } else { $this->attributes['format']=$value; diff --git a/app/models/CustomFieldset.php b/app/models/CustomFieldset.php index 7cbd749404..c368ed8fe8 100644 --- a/app/models/CustomFieldset.php +++ b/app/models/CustomFieldset.php @@ -4,7 +4,21 @@ class CustomFieldset extends Elegant protected $guarded=["id"]; public $timestamps=false; public function fields() { - return $this->belongsToMany('CustomField')->withPivot(["required","order"]); + return $this->belongsToMany('CustomField')->withPivot(["required","order"])->orderBy("pivot_order"); + } + + public function validation_rules() + { + $rules=[]; + foreach($this->fields AS $field) { + $rule=[]; + if($field->pivot->required) { + $rule[]="required"; + } + array_push($rule,"regex",$field->format); + $rules[$field->db_column_name()]=$rule; + } + return $rules; } //requiredness goes *here* diff --git a/app/models/Model.php b/app/models/Model.php index 32695c38fb..039a771473 100755 --- a/app/models/Model.php +++ b/app/models/Model.php @@ -43,11 +43,9 @@ class Model extends Elegant return $this->belongsTo('Manufacturer','manufacturer_id'); } - public function custom_fieldset() + public function fieldset() { - // $foo=new CustomField(); - // $foo2=new CustomFieldset(); - return $this->belongsTo('custom_fieldset','fieldset_id'); + return $this->belongsTo('CustomFieldset','fieldset_id'); } /** diff --git a/app/routes.php b/app/routes.php index d69bce3ba6..d872f6e214 100755 --- a/app/routes.php +++ b/app/routes.php @@ -108,6 +108,13 @@ } ); } ); + + # Custom fieldset + //Route::get('/custom_fieldsets/{id}','CustomFieldsController@show'); + //Route::get('/custom_fieldsets/create','CustomFieldsController@getCreate'); + Route::post('/custom_fieldsets/{id}/associate','CustomFieldsController@postAssociate'); + Route::controller('/custom_fieldsets','CustomFieldsController' ); + /* |-------------------------------------------------------------------------- | Asset Routes diff --git a/app/views/backend/custom_fields/create.blade.php b/app/views/backend/custom_fields/create.blade.php new file mode 100644 index 0000000000..b1cb366c29 --- /dev/null +++ b/app/views/backend/custom_fields/create.blade.php @@ -0,0 +1,6 @@ + + + '/custom_fieldsets']) ?> + Name:
+ + diff --git a/app/views/backend/custom_fields/create_field.blade.php b/app/views/backend/custom_fields/create_field.blade.php new file mode 100644 index 0000000000..1f42eace24 --- /dev/null +++ b/app/views/backend/custom_fields/create_field.blade.php @@ -0,0 +1,9 @@ + + +{{ Form::open(["url" =>"/custom_fieldsets/create-field"])}} +Name: {{ Form::text("name")}}
+type: {{ Form::select("element",["text" => "Text Box"])}}
+format: {{ Form::select("format",predefined_formats(),"ALPHA") }} +Custom Format (if selected): {{ Form::text("custom_format") }}
+ +{{ Form::close() }} diff --git a/app/views/backend/custom_fields/index.blade.php b/app/views/backend/custom_fields/index.blade.php new file mode 100644 index 0000000000..c8bd7f66b9 --- /dev/null +++ b/app/views/backend/custom_fields/index.blade.php @@ -0,0 +1,18 @@ + + +

Fieldsets

+ + +New Fieldset
+

Custom Field Definitions

+
    + @foreach($custom_fields AS $field) +
  • {{{$field->name}}}, {{{$field->format}}}
  • + @endforeach +
+New Field diff --git a/app/views/backend/custom_fields/show.blade.php b/app/views/backend/custom_fields/show.blade.php new file mode 100644 index 0000000000..a3a65852cb --- /dev/null +++ b/app/views/backend/custom_fields/show.blade.php @@ -0,0 +1,12 @@ +

Fieldset

+{{{ $custom_fieldset->name }}} + +
    +@foreach($custom_fieldset->fields AS $field) +
  • {{$field->pivot->order}}) {{$field->name}}, {{$field->format}}, {{$field->pivot->required ? "REQUIRED" : "OPTIONAL"}}
  • +@endforeach +
+{{ Form::open(['url' => '/custom_fieldsets/'.$custom_fieldset->id.'/associate']) }} +{{ Form::checkbox("required","on") }}Required? +{{ Form::text("order",$maxid)}} +{{ Form::select("field_id",["" => "Add New Field to Fieldset"] + CustomField::lists("name","id"),"",["onchange" => "document.forms[0].submit()"]) }} diff --git a/app/views/backend/hardware/edit.blade.php b/app/views/backend/hardware/edit.blade.php index d313f3e418..0f972470a2 100755 --- a/app/views/backend/hardware/edit.blade.php +++ b/app/views/backend/hardware/edit.blade.php @@ -175,7 +175,7 @@ - + + + @if($asset->model->fieldset) +

Custom Fields

+ @foreach($asset->model->fieldset->fields AS $field) +
+ +
+ +
+
+ @endforeach + @endif diff --git a/app/views/backend/hardware/index.blade.php b/app/views/backend/hardware/index.blade.php index 831bd6cbc8..1daacb59bd 100755 --- a/app/views/backend/hardware/index.blade.php +++ b/app/views/backend/hardware/index.blade.php @@ -66,7 +66,7 @@ Lang::get('general.category'), Lang::get('admin/hardware/table.eol'), Lang::get('general.notes'), - Lang::get('admin/hardware/form.mac_address'), + "REMOVEME", Lang::get('admin/hardware/form.order'), Lang::get('admin/hardware/table.checkout_date'), Lang::get('admin/hardware/table.change'), @@ -89,8 +89,8 @@ ), 'sAjaxSource'=> route('api.hardware.list', array(''=>Input::get('status'),'order_number'=>Input::get('order_number'))), 'dom' =>'CT<"clear">lfrtip', - 'colVis'=> array('showAll'=>'Show All','restore'=>'Restore','exclude'=>array(0,13,14),'activate'=>'mouseover'), - 'columnDefs'=> array(array('visible'=>false,'targets'=>array(7,8,9)),array('orderable'=>false,'targets'=>array(0,13,14))), + 'colVis'=> array('showAll'=>'Show All','restore'=>'Restore','exclude'=>array(0,12,13),'activate'=>'mouseover'), + 'columnDefs'=> array(array('visible'=>false,'targets'=>array(7,8,9)),array('orderable'=>false,'targets'=>array(0,12,13))), 'order'=>array(array(1,'asc')), ) ) diff --git a/app/views/backend/hardware/view.blade.php b/app/views/backend/hardware/view.blade.php index f02ba9842b..5ace05266c 100755 --- a/app/views/backend/hardware/view.blade.php +++ b/app/views/backend/hardware/view.blade.php @@ -65,12 +65,6 @@ @endif - @if ($asset->mac_address!='') -
@lang('admin/hardware/form.mac_address'): - {{{ $asset->mac_address }}} -
- @endif - @if ($asset->model->manufacturer)
@lang('admin/hardware/form.manufacturer'): @@ -159,6 +153,17 @@
@endif + @if ($asset->model->fieldset->sortBy('custom_field_custom_fieldset.order')) +
+
FIELDSET: + {{{ $asset->model->fieldset->name }}}
+ @foreach($asset->model->fieldset->fields as $field) +
{{{ $field->name }}}: + {{{ $asset->{$field->db_column_name()} }}} +
+ @endforeach +
+ @endif diff --git a/app/views/backend/models/edit.blade.php b/app/views/backend/models/edit.blade.php index cc336759b2..47e2336bd9 100755 --- a/app/views/backend/models/edit.blade.php +++ b/app/views/backend/models/edit.blade.php @@ -110,8 +110,8 @@
From 0f6de6a477e71854af16e71c875f8bf972ea17ff Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Thu, 22 Oct 2015 01:06:35 -0700 Subject: [PATCH 008/119] Asset editing works. --- app/controllers/admin/AssetsController.php | 16 +++++++++++----- app/models/CustomFieldset.php | 2 +- app/views/backend/hardware/view.blade.php | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index ad516e3cf8..c55c5cf1fd 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -244,16 +244,22 @@ class AssetsController extends AdminController } $input=Input::all(); - if($this->model->fieldset) + // return "INPUT IS:
".print_r($input,true)."
"; + $rules=$asset->validationRules($assetId); + if($asset->model->fieldset) { - foreach($this->model->fieldset->fields AS $field) { - $input[$field->db_column_name()]=$input->fields[$field->db_column_name()]; + foreach($asset->model->fieldset->fields AS $field) { + $input[$field->db_column_name()]=$input['fields'][$field->db_column_name()]; + $asset->{$field->db_column_name()}=$input[$field->db_column_name()]; } + $rules+=$asset->model->fieldset->validation_rules(); unset($input['fields']); } + + //return "Rules:
".print_r($rules,true)."
"; //attempt to validate - $validator = Validator::make($input, $asset->validationRules($assetId) + $this->fieldset->validation_rules()); + $validator = Validator::make($input, $rules ); $custom_errors=[]; @@ -309,7 +315,7 @@ class AssetsController extends AdminController } $checkModel = Config::get('app.url').'/api/models/'.e(Input::get('model_id')).'/check'; - $asset->mac_address = ($checkModel == true) ? e(Input::get('mac_address')) : NULL; + //$asset->mac_address = ($checkModel == true) ? e(Input::get('mac_address')) : NULL; // Update the asset data $asset->name = e(Input::get('name')); diff --git a/app/models/CustomFieldset.php b/app/models/CustomFieldset.php index c368ed8fe8..7ddfd5a278 100644 --- a/app/models/CustomFieldset.php +++ b/app/models/CustomFieldset.php @@ -15,7 +15,7 @@ class CustomFieldset extends Elegant if($field->pivot->required) { $rule[]="required"; } - array_push($rule,"regex",$field->format); + array_push($rule,"regex:/".$field->attributes['format']."/"); $rules[$field->db_column_name()]=$rule; } return $rules; diff --git a/app/views/backend/hardware/view.blade.php b/app/views/backend/hardware/view.blade.php index 5ace05266c..71707ac047 100755 --- a/app/views/backend/hardware/view.blade.php +++ b/app/views/backend/hardware/view.blade.php @@ -153,7 +153,7 @@ @endif - @if ($asset->model->fieldset->sortBy('custom_field_custom_fieldset.order')) + @if ($asset->model->fieldset)
FIELDSET: {{{ $asset->model->fieldset->name }}}
From 63eca44789a12bf6172708385554f8a4c46a9721 Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Thu, 22 Oct 2015 03:33:27 -0700 Subject: [PATCH 009/119] Custom fields can be shown on the hardware list page. They can also be searched for. --- app/controllers/admin/AssetsController.php | 7 ++++++- app/models/Asset.php | 3 +++ app/views/backend/hardware/index.blade.php | 4 +++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index 87250ed1ff..5f953ff739 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -30,6 +30,7 @@ use Paginator; use Manufacturer; //for embedded-create use Artisan; use Symfony\Component\Console\Output\BufferedOutput; +use CustomField; class AssetsController extends AdminController @@ -1190,7 +1191,7 @@ class AssetsController extends AdminController } } - $rows[] = array( + $row = array( 'checkbox' =>'
', 'id' => $asset->id, 'name' => '
'.$asset->name.'', @@ -1207,6 +1208,10 @@ class AssetsController extends AdminController 'change' => ($inout) ? $inout : '', 'actions' => ($actions) ? $actions : '' ); + foreach(CustomField::all() AS $field) { + $row[$field->db_column_name()]=$asset->{$field->db_column_name()}; + } + $rows[]=$row; } $data = array('total'=>$assetCount, 'rows'=>$rows); diff --git a/app/models/Asset.php b/app/models/Asset.php index d08e657a69..649be617bb 100755 --- a/app/models/Asset.php +++ b/app/models/Asset.php @@ -625,6 +625,9 @@ class Asset extends Depreciable ->orWhere('order_number','LIKE','%'.$search.'%') ->orWhere('notes','LIKE','%'.$search.''); } + foreach(CustomField::all() AS $field) { + $query->orWhere($field->db_column_name(),'LIKE',"%$search%"); + } }); } diff --git a/app/views/backend/hardware/index.blade.php b/app/views/backend/hardware/index.blade.php index 9064dae602..d7f84ef71c 100755 --- a/app/views/backend/hardware/index.blade.php +++ b/app/views/backend/hardware/index.blade.php @@ -57,7 +57,6 @@ data-cookie-id-table="assetsTable"> -
@lang('general.id') {{Lang::get('admin/hardware/form.name')}} @@ -71,6 +70,9 @@ {{Lang::get('general.notes')}} {{Lang::get('admin/hardware/form.order')}} {{Lang::get('admin/hardware/table.checkout_date')}} + @foreach(CustomField::all() AS $field) + {{{$field->name}}} + @endforeach {{Lang::get('admin/hardware/table.change')}} {{Lang::get('table.actions')}} From a955d57c205e50b3fab7b7f18d96a314dd43a70a Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Thu, 22 Oct 2015 11:21:15 -0700 Subject: [PATCH 010/119] When edit blade is used for New Asset, need to account for no model being selected. --- app/views/backend/hardware/edit.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/backend/hardware/edit.blade.php b/app/views/backend/hardware/edit.blade.php index 0f972470a2..04aeb6fd8e 100755 --- a/app/views/backend/hardware/edit.blade.php +++ b/app/views/backend/hardware/edit.blade.php @@ -300,7 +300,7 @@ - @if($asset->model->fieldset) + @if($asset->model && $asset->model->fieldset)

Custom Fields

@foreach($asset->model->fieldset->fields AS $field)
From 5e1bec71f20309b62ad4917e7363447d2e1f7558 Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Thu, 12 Nov 2015 14:07:05 -0800 Subject: [PATCH 011/119] Start to move README over to emphasize running docker pull snipe/snipe-it --- docker/README.md | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/docker/README.md b/docker/README.md index 4dea45d41b..5e6d99b231 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,12 +1,23 @@ #### How to use the Snipe-IT docker image ##### +The easiest way, by far, is to just use the version we push to the docker hub: + +```sh +docker pull snipe/snipe-it +``` + +Then you have a functioning Snipe-IT container. Skip ahead to "How to get up and +running" to configure it and get it connected to your database. + +#### How to *Build* the Snipe-IT docker image #### + Build the snipeit image using the ```Dockerfile``` at the root directory of Snipe-IT by doing this: ```sh -docker build -t snipeit . +docker build -t snipe-it . ``` -Then you can use your newly built image as ```snipeit``` +Then you can use your newly built image as ```snipe-it``` ### How to get up and running ### @@ -42,36 +53,45 @@ SNIPEIT_TIMEZONE=UTC SNIPEIT_LOCALE=en SERVER_URL=https://myserver.com ``` -* First get a MySQL container running +* First get a MySQL container running. ```sh docker run --name snipe-mysql --env-file=my_env_file -d -p $(docker-machine ip b2d)::3306 mysql ``` +**WARNING:** Newer MySQL containers run strict-mode by default, and the initial +migrations and appliction setup will fail in strict mode. You need to disable it +first! + That should set you up with your database to use. (You can also specify environment variables on the command-line instead of the env-file, but that can get very clunky very quickly; see ```docker run --help``` for details) * If your Email solution requires its own container, start that container or service. Make sure to expose port 587 for mail submission, and use ```--link mail:...```. Now you can start your Snipe-IT container - ```sh -docker run -d -p $(docker-machine ip b2d)::80 --name="snipeit" --link snipe-mysql:mysql --env-file=my_env_file snipeit +docker run -d -p $(docker-machine ip b2d)::80 --name="snipeit" --link snipe-mysql:mysql --env-file=my_env_file snipe-it ``` If you have a separate container running for email, you will also want a ```--link``` setting for email as well. You can find out what port Snipe-IT is running on with: ```sh -docker port snipeit +docker port snipe-it ``` And finally, you can initialize the application and database like this: ```sh -docker exec -i -t snipeit php artisan app:install +docker exec -i -t snipe-it php artisan app:install ``` (Go ahead and answer the questions however you like. Type 'yes' when asked whether or not you want to run migrations.) +**WARNING:** Docker wants to treat containers as 'ephemeral' - but Snipe-IT is +expecting to be able to save uploaded images and files to the local filesystem. +Either make sure to back up your image, or mount a local directory to house +uploaded files at /var/www/blah/ + ~~#NOTE:~~ ~~You may have to run:~~ From 50170dd77457957186a9c0ea673abc8bf8587f12 Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Thu, 12 Nov 2015 20:05:39 -0800 Subject: [PATCH 012/119] Improve start script, add entrypoint script --- Dockerfile | 8 ++++---- docker/README.md | 6 +++--- docker/entrypoint.sh | 12 ++++++++++++ 3 files changed, 19 insertions(+), 7 deletions(-) create mode 100644 docker/entrypoint.sh diff --git a/Dockerfile b/Dockerfile index 7a53df1a53..fbd7ea5733 100644 --- a/Dockerfile +++ b/Dockerfile @@ -53,9 +53,6 @@ RUN cd /var/www/html;composer install ############### APPLICATION INSTALL/INIT ################# -RUN cd /var/www/html;MYSQL_PORT_3306_TCP_ADDR='' MYSQL_PORT_3306_TCP_PORT='' MYSQL_ENV_MYSQL_DATABASE='' \ -MYSQL_ENV_MYSQL_USER='' MYSQL_ENV_MYSQL_PASSWORD='' php artisan --env=production -n key:generate - #RUN php artisan app:install # too interactive! Try something else @@ -65,6 +62,9 @@ MYSQL_ENV_MYSQL_USER='' MYSQL_ENV_MYSQL_PASSWORD='' php artisan --env=production ##### START SERVER -CMD . /etc/apache2/envvars ;apache2 -DFOREGROUND +COPY docker/entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +CMD /entrypoint.sh EXPOSE 80 diff --git a/docker/README.md b/docker/README.md index 5e6d99b231..6306e94389 100644 --- a/docker/README.md +++ b/docker/README.md @@ -53,13 +53,13 @@ SNIPEIT_TIMEZONE=UTC SNIPEIT_LOCALE=en SERVER_URL=https://myserver.com ``` -* First get a MySQL container running. +* First get a MySQL container running. MySQL 5.6 or earlier are easiest. ```sh -docker run --name snipe-mysql --env-file=my_env_file -d -p $(docker-machine ip b2d)::3306 mysql +docker run --name snipe-mysql --env-file=my_env_file -d -p $(docker-machine ip b2d)::3306 mysql-56 ``` -**WARNING:** Newer MySQL containers run strict-mode by default, and the initial +**WARNING:** Newer MySQL containers (5.7 and later, or MariaDB) may run in strict-mode by default, and the initial migrations and appliction setup will fail in strict mode. You need to disable it first! diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh new file mode 100644 index 0000000000..b692cc2643 --- /dev/null +++ b/docker/entrypoint.sh @@ -0,0 +1,12 @@ +#!/bin/sh +cd /var/www/html + +# fix key if needed +if grep -q Change_this_key_or_snipe_will_get_ya app/config/production/app.php +then + MYSQL_PORT_3306_TCP_ADDR='' MYSQL_PORT_3306_TCP_PORT='' MYSQL_ENV_MYSQL_DATABASE='' \ + MYSQL_ENV_MYSQL_USER='' MYSQL_ENV_MYSQL_PASSWORD='' php artisan --env=production -n key:generate +fi + +. /etc/apache2/envvars +exec apache2 -DNO_DETACH < /dev/null From 3a99136f73ec5589c9b9e0bae29a16e6418f62a7 Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Thu, 12 Nov 2015 21:14:10 -0800 Subject: [PATCH 013/119] More documentation fixes --- docker/README.md | 57 ++++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 33 deletions(-) diff --git a/docker/README.md b/docker/README.md index 6306e94389..54887e6b86 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,6 +1,6 @@ #### How to use the Snipe-IT docker image ##### -The easiest way, by far, is to just use the version we push to the docker hub: +The easiest way, by far, is to just use the version we push to Docker Hub: ```sh docker pull snipe/snipe-it @@ -11,7 +11,8 @@ running" to configure it and get it connected to your database. #### How to *Build* the Snipe-IT docker image #### -Build the snipeit image using the ```Dockerfile``` at the root directory of Snipe-IT by doing this: +This is more if you're doing development on the Docker piece of Snipe-IT. +You can build the snipe-it image using the ```Dockerfile``` at the root directory of Snipe-IT by doing this: ```sh docker build -t snipe-it . @@ -52,16 +53,31 @@ MAIL_ENV_PASSWORD=your_email_password SNIPEIT_TIMEZONE=UTC SNIPEIT_LOCALE=en SERVER_URL=https://myserver.com + +# LDAP Parameters (or omit if not using LDAP) +# See ldap.php for more info +LDAP_URL=ldap://ldap.yourserver.com +LDAP_USERNAME=admin +LDAP_PASSWORD=adminpass +LDAP_BASEDN=dc=example,dc=com +LDAP_FILTER=&(cn=*) +LDAP_RESULT_USERNAME=username +LDAP_RESULT_LAST_NAME=sn +LDAP_RESULT_FIRST_NAME=gn +LDAP_RESULT_ACTIVE_FLAG=active +LDAP_RESULT_EMP_NUM=emp-num +LDAP_RESULT_EMAIL=email +LDAP_AUTHENTICATION_FILTER_QUERY="uid=" ``` * First get a MySQL container running. MySQL 5.6 or earlier are easiest. ```sh -docker run --name snipe-mysql --env-file=my_env_file -d -p $(docker-machine ip b2d)::3306 mysql-56 +docker run --name snipe-mysql --env-file=my_env_file -d -p $(docker-machine ip b2d)::3306 mysql:5.6 ``` **WARNING:** Newer MySQL containers (5.7 and later, or MariaDB) may run in strict-mode by default, and the initial -migrations and appliction setup will fail in strict mode. You need to disable it -first! +migrations and appliction setup will fail in strict mode. If you want to use one of those versions, you need to disable strict +mode first! That should set you up with your database to use. (You can also specify environment variables on the command-line instead of the env-file, but that can get very clunky very quickly; see ```docker run --help``` for details) @@ -76,48 +92,23 @@ If you have a separate container running for email, you will also want a ```--li You can find out what port Snipe-IT is running on with: ```sh -docker port snipe-it +docker port snipeit ``` And finally, you can initialize the application and database like this: ```sh -docker exec -i -t snipe-it php artisan app:install +docker exec -i -t snipeit php artisan app:install ``` (Go ahead and answer the questions however you like. Type 'yes' when asked whether or not you want to run migrations.) -**WARNING:** Docker wants to treat containers as 'ephemeral' - but Snipe-IT is -expecting to be able to save uploaded images and files to the local filesystem. -Either make sure to back up your image, or mount a local directory to house -uploaded files at /var/www/blah/ - -~~#NOTE:~~ - -~~You may have to run:~~ - -```sh -~~docker exec -i -t snipeit php artisan key:generate --env=production~~ -``` - -~~to get the production application key set correctly; I'm not yet sure why this is (I think it's a bug?)~~ - -# ~~If you want to seed~~ - -~~You can load out some initial data into the DB if you like by doing this:~~ - -```sh -~~docker -p $(boot2docker ip):8000:80 --link mysql:mysql php artisan db:seed~~ -``` - -~~This already happens~~ - ### For Development ### When you call ```docker run``` - make sure to mount your own snipe-it directory *over* the /var/www/html directory. Something like: ```sh -docker run -d -v /Path/To/My/snipe-it/checkout:/var/www/html -p $(boot2docker ip)::80 --name="snipeit" --link mysql:mysql snipeit +docker run -d -v /Path/To/My/snipe-it/checkout:/var/www/html -p $(docker-machine ip b2d)::80 --name="snipeit" --link mysql:mysql snipeit ``` Then your local changes to the code will be reflected. You will have to re-run ```composer install``` - From 6d365157e701d82144b9dca59ee627a3bb18b192 Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Thu, 12 Nov 2015 21:50:58 -0800 Subject: [PATCH 014/119] Changed to using Entrypoint instead of CMD for better start/stop --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index fbd7ea5733..83ea061f21 100644 --- a/Dockerfile +++ b/Dockerfile @@ -65,6 +65,6 @@ RUN cd /var/www/html;composer install COPY docker/entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh -CMD /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] EXPOSE 80 From a8e686cdf70afb13e23297ba0f65c6e0dab186c5 Mon Sep 17 00:00:00 2001 From: bmk Date: Wed, 18 Nov 2015 15:58:17 +0100 Subject: [PATCH 015/119] added SSL config for apache --- docker/001-default-ssl.conf | 145 ++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 docker/001-default-ssl.conf diff --git a/docker/001-default-ssl.conf b/docker/001-default-ssl.conf new file mode 100644 index 0000000000..ed3f60bfda --- /dev/null +++ b/docker/001-default-ssl.conf @@ -0,0 +1,145 @@ + + + ServerAdmin webmaster@localhost + + DocumentRoot "/var/www/html/public" + DirectoryIndex index.php index.html + + Options All +MultiViews -ExecCGI -Indexes + + DAV Off + + AllowOverride All + + + # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, + # error, crit, alert, emerg. + # It is also possible to configure the loglevel for particular + # modules, e.g. + #LogLevel info ssl:warn + + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + + # For most configuration files from conf-available/, which are + # enabled or disabled at a global level, it is possible to + # include a line for only one particular virtual host. For example the + # following line enables the CGI configuration for this host only + # after it has been globally disabled with "a2disconf". + #Include conf-available/serve-cgi-bin.conf + + # SSL Engine Switch: + # Enable/Disable SSL for this virtual host. + SSLEngine on + + # A self-signed (snakeoil) certificate can be created by installing + # the ssl-cert package. See + # /usr/share/doc/apache2/README.Debian.gz for more info. + # If both key and certificate are stored in the same file, only the + # SSLCertificateFile directive is needed. + #SSLCertificateFile /etc/ssl/private/ssl-cert-snakeoil.crt + SSLCertificateFile /etc/ssl/private/snipeit-ssl.crt + #SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key + SSLCertificateKeyFile /etc/ssl/private/snipeit-ssl.key + + # Server Certificate Chain: + # Point SSLCertificateChainFile at a file containing the + # concatenation of PEM encoded CA certificates which form the + # certificate chain for the server certificate. Alternatively + # the referenced file can be the same as SSLCertificateFile + # when the CA certificates are directly appended to the server + # certificate for convinience. + #SSLCertificateChainFile /etc/apache2/ssl.crt/server-ca.crt + SSLCertificateChainFile /etc/ssl/private/snipeit-ssl.crt + + # Certificate Authority (CA): + # Set the CA certificate verification path where to find CA + # certificates for client authentication or alternatively one + # huge file containing all of them (file must be PEM encoded) + # Note: Inside SSLCACertificatePath you need hash symlinks + # to point to the certificate files. Use the provided + # Makefile to update the hash symlinks after changes. + #SSLCACertificatePath /etc/ssl/certs/ + #SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt + + # Certificate Revocation Lists (CRL): + # Set the CA revocation path where to find CA CRLs for client + # authentication or alternatively one huge file containing all + # of them (file must be PEM encoded) + # Note: Inside SSLCARevocationPath you need hash symlinks + # to point to the certificate files. Use the provided + # Makefile to update the hash symlinks after changes. + #SSLCARevocationPath /etc/apache2/ssl.crl/ + #SSLCARevocationFile /etc/apache2/ssl.crl/ca-bundle.crl + + # Client Authentication (Type): + # Client certificate verification type and depth. Types are + # none, optional, require and optional_no_ca. Depth is a + # number which specifies how deeply to verify the certificate + # issuer chain before deciding the certificate is not valid. + #SSLVerifyClient require + #SSLVerifyDepth 10 + + # SSL Engine Options: + # Set various options for the SSL engine. + # o FakeBasicAuth: + # Translate the client X.509 into a Basic Authorisation. This means that + # the standard Auth/DBMAuth methods can be used for access control. The + # user name is the `one line' version of the client's X.509 certificate. + # Note that no password is obtained from the user. Every entry in the user + # file needs this password: `xxj31ZMTZzkVA'. + # o ExportCertData: + # This exports two additional environment variables: SSL_CLIENT_CERT and + # SSL_SERVER_CERT. These contain the PEM-encoded certificates of the + # server (always existing) and the client (only existing when client + # authentication is used). This can be used to import the certificates + # into CGI scripts. + # o StdEnvVars: + # This exports the standard SSL/TLS related `SSL_*' environment variables. + # Per default this exportation is switched off for performance reasons, + # because the extraction step is an expensive operation and is usually + # useless for serving static content. So one usually enables the + # exportation for CGI and SSI requests only. + # o OptRenegotiate: + # This enables optimized SSL connection renegotiation handling when SSL + # directives are used in per-directory context. + #SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire + + SSLOptions +StdEnvVars + + + SSLOptions +StdEnvVars + + + # SSL Protocol Adjustments: + # The safe and default but still SSL/TLS standard compliant shutdown + # approach is that mod_ssl sends the close notify alert but doesn't wait for + # the close notify alert from client. When you need a different shutdown + # approach you can use one of the following variables: + # o ssl-unclean-shutdown: + # This forces an unclean shutdown when the connection is closed, i.e. no + # SSL close notify alert is send or allowed to received. This violates + # the SSL/TLS standard but is needed for some brain-dead browsers. Use + # this when you receive I/O errors because of the standard approach where + # mod_ssl sends the close notify alert. + # o ssl-accurate-shutdown: + # This forces an accurate shutdown when the connection is closed, i.e. a + # SSL close notify alert is send and mod_ssl waits for the close notify + # alert of the client. This is 100% SSL/TLS standard compliant, but in + # practice often causes hanging connections with brain-dead browsers. Use + # this only for browsers where you know that their SSL implementation + # works correctly. + # Notice: Most problems of broken clients are also related to the HTTP + # keep-alive facility, so you usually additionally want to disable + # keep-alive for those clients, too. Use variable "nokeepalive" for this. + # Similarly, one has to force some clients to use HTTP/1.0 to workaround + # their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and + # "force-response-1.0" for this. + BrowserMatch "MSIE [2-6]" \ + nokeepalive ssl-unclean-shutdown \ + downgrade-1.0 force-response-1.0 + # MSIE 7 and newer should be able to use keepalive + BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown + + + From 31c4a63ec062212f5adfbc3c6584d0a3b02fe952 Mon Sep 17 00:00:00 2001 From: Bjarne K Date: Fri, 20 Nov 2015 11:55:57 +0100 Subject: [PATCH 016/119] Added copy for apache SSL file and commands to enable SSL in apache --- Dockerfile | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Dockerfile b/Dockerfile index 83ea061f21..935d45ebf7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,6 +27,13 @@ RUN echo export APACHE_RUN_GROUP=staff >> /etc/apache2/envvars COPY docker/000-default.conf /etc/apache2/sites-enabled/000-default.conf +#SSL +COPY docker/001-default-ssl.conf /etc/apache2/sites-enabled/001-default-ssl.conf +#COPY docker/001-default-ssl.conf /etc/apache2/sites-available/001-default-ssl.conf + +RUN a2enmod ssl +#RUN a2ensite 001-default-ssl.conf + COPY . /var/www/html RUN a2enmod rewrite @@ -68,3 +75,4 @@ RUN chmod +x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] EXPOSE 80 +EXPOSE 443 From e3ec2ae3ecdd358c64779d26b231a3b00bf5dea4 Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Wed, 25 Nov 2015 14:55:49 -0800 Subject: [PATCH 017/119] Style the drop-down for custom fieldset to match --- app/views/backend/models/edit.blade.php | 37 +++++++++++++------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/app/views/backend/models/edit.blade.php b/app/views/backend/models/edit.blade.php index 47e2336bd9..775be69cb2 100755 --- a/app/views/backend/models/edit.blade.php +++ b/app/views/backend/models/edit.blade.php @@ -52,17 +52,17 @@
-
- - -
- {{ Form::select('manufacturer_id', $manufacturer_list , Input::old('manufacturer_id', $model->manufacturer_id), array('class'=>'select2', 'style'=>'width:350px')) }} - {{ $errors->first('manufacturer_id', '
:message') }} -
-
+
+ + +
+ {{ Form::select('manufacturer_id', $manufacturer_list , Input::old('manufacturer_id', $model->manufacturer_id), array('class'=>'select2', 'style'=>'width:350px')) }} + {{ $errors->first('manufacturer_id', '
:message') }} +
+
- +
@@ -107,14 +107,15 @@
-
-
- -
-
+ +
+ +
+ {{ Form::select('custom_fieldset', customFieldsetList(),Input::old('custom_fieldset', $model->fieldset_id), array('class'=>'select2', 'style'=>'width:350px')) }} + {{ $errors->first('custom_fieldset', '
:message') }} + +
+
@if ($model->image) From 4508225d654d1f447b316447577b3c63f4545f24 Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Wed, 25 Nov 2015 15:16:20 -0800 Subject: [PATCH 018/119] Add default layout basic styling to custom fields --- app/views/backend/custom_fields/create.blade.php | 3 +++ app/views/backend/custom_fields/create_field.blade.php | 3 +++ app/views/backend/custom_fields/index.blade.php | 3 +++ app/views/backend/custom_fields/show.blade.php | 3 +++ app/views/backend/layouts/default.blade.php | 5 +++++ 5 files changed, 17 insertions(+) diff --git a/app/views/backend/custom_fields/create.blade.php b/app/views/backend/custom_fields/create.blade.php index b1cb366c29..286788c2d7 100644 --- a/app/views/backend/custom_fields/create.blade.php +++ b/app/views/backend/custom_fields/create.blade.php @@ -1,6 +1,9 @@ +@extends('backend/layouts/default') +@section('content') '/custom_fieldsets']) ?> Name:
+@stop diff --git a/app/views/backend/custom_fields/create_field.blade.php b/app/views/backend/custom_fields/create_field.blade.php index 1f42eace24..e60baf9bb1 100644 --- a/app/views/backend/custom_fields/create_field.blade.php +++ b/app/views/backend/custom_fields/create_field.blade.php @@ -1,3 +1,5 @@ +@extends('backend/layouts/default') +@section('content') {{ Form::open(["url" =>"/custom_fieldsets/create-field"])}} @@ -7,3 +9,4 @@ format: {{ Form::select("format",predefined_formats(),"ALPHA") }} Custom Format (if selected): {{ Form::text("custom_format") }}
{{ Form::close() }} +@stop diff --git a/app/views/backend/custom_fields/index.blade.php b/app/views/backend/custom_fields/index.blade.php index c8bd7f66b9..7e0c166ea1 100644 --- a/app/views/backend/custom_fields/index.blade.php +++ b/app/views/backend/custom_fields/index.blade.php @@ -1,3 +1,5 @@ +@extends('backend/layouts/default') +@section('content') @@ -16,3 +18,4 @@ @endforeach New Field +@stop diff --git a/app/views/backend/custom_fields/show.blade.php b/app/views/backend/custom_fields/show.blade.php index a3a65852cb..68a9eaea8e 100644 --- a/app/views/backend/custom_fields/show.blade.php +++ b/app/views/backend/custom_fields/show.blade.php @@ -1,3 +1,5 @@ +@extends('backend/layouts/default') +@section('content')

Fieldset

{{{ $custom_fieldset->name }}} @@ -10,3 +12,4 @@ {{ Form::checkbox("required","on") }}Required? {{ Form::text("order",$maxid)}} {{ Form::select("field_id",["" => "Add New Field to Fieldset"] + CustomField::lists("name","id"),"",["onchange" => "document.forms[0].submit()"]) }} +@stop diff --git a/app/views/backend/layouts/default.blade.php b/app/views/backend/layouts/default.blade.php index 4dccd58a8c..77494f97c5 100644 --- a/app/views/backend/layouts/default.blade.php +++ b/app/views/backend/layouts/default.blade.php @@ -249,6 +249,11 @@ @lang('admin/settings/general.backups') + + + Custom Fields? + +
  • From a212abee1d4d81a26db675ba3b3336ae572ccc89 Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Wed, 25 Nov 2015 15:30:06 -0800 Subject: [PATCH 019/119] Strip out stale comments --- .../2015_09_22_003413_migrate_mac_address.php | 30 ++----------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/app/database/migrations/2015_09_22_003413_migrate_mac_address.php b/app/database/migrations/2015_09_22_003413_migrate_mac_address.php index 75a07e46fb..f1bf411c93 100644 --- a/app/database/migrations/2015_09_22_003413_migrate_mac_address.php +++ b/app/database/migrations/2015_09_22_003413_migrate_mac_address.php @@ -14,10 +14,6 @@ class MigrateMacAddress extends Migration { { DB::getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string'); - - // - //create empty 'default' fieldset' - //$f1=Fieldset::create([name => "Default Asset"]); $f2=new CustomFieldset(['name' => "Asset with MAC Address"]); if(!$f2->save()) { throw new Exception("couldn't save customfieldset"); @@ -31,32 +27,13 @@ class MigrateMacAddress extends Migration { } $f2->fields()->attach($macid,['required' => false, 'order' => 1]); - //$f2->push(); Model::where(["show_mac_address" => true])->update(["fieldset_id"=>$f2->id]); - //up to *HERE* works just fine - print "THIS IS FINE!"; - // $ans2=Schema::table("assets",function (Blueprint $table) { - // $table->renameColumn('mac_address','_snipeit_mac_address'); - // }); + DB::statement("ALTER TABLE assets CHANGE mac_address _snipeit_mac_address varchar(255)"); - // print "NOTHING WORKS"; - // if(!$ans2) { - // throw new Exception("Couldn't rename mac_address collumn in Assets table"); - // } + $ans=Schema::table("models",function (Blueprint $table) { $table->renameColumn('show_mac_address','deprecated_mac_address'); }); - print "Does this even ahppen"; - // if(!$ans) { - // throw new Exception("couldn't rename show_mac_address column in Models table"); - // } - // $shit=Schema::table("assets",function (Blueprint $table) { - // $table->renmaeColmnu("fuck you you fucking piece of shit","die in a fucking fire you asshole"); - // }); - // print "seriously"; - // if(!$shit) { - // throw new Exception("something taht should've failed failed. Good."); - // } } /** @@ -74,9 +51,6 @@ class MigrateMacAddress extends Migration { $table->renameColumn("deprecated_mac_address","show_mac_address"); }); DB::statement("ALTER TABLE assets CHANGE _snipeit_mac_address mac_address varchar(255)"); - // Schema::table("assets",function (Blueprint $table) { - // $table->renameColumn('_snipeit_mac_address','mac_address'); - // }); } } From c6f8d3e6f29efc6694a2d972b2fd34e74ad73e8c Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Wed, 25 Nov 2015 15:40:58 -0800 Subject: [PATCH 020/119] A little bit of basic, terrible navigation for Custom Fields. --- app/models/CustomField.php | 1 + app/views/backend/custom_fields/create.blade.php | 1 + app/views/backend/custom_fields/create_field.blade.php | 3 ++- app/views/backend/custom_fields/show.blade.php | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/models/CustomField.php b/app/models/CustomField.php index e7816f67b2..caaf04880f 100644 --- a/app/models/CustomField.php +++ b/app/models/CustomField.php @@ -4,6 +4,7 @@ class CustomField extends Elegant { public $guarded=["id"]; public static $PredefinedFormats=[ + "ANY" => "", "ALPHA" => "[a-zA-Z]*", "NUMERIC" => "[0-9]*", "MAC" => "[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}", diff --git a/app/views/backend/custom_fields/create.blade.php b/app/views/backend/custom_fields/create.blade.php index 286788c2d7..d7cc1b83b9 100644 --- a/app/views/backend/custom_fields/create.blade.php +++ b/app/views/backend/custom_fields/create.blade.php @@ -6,4 +6,5 @@ Name:
    +
    Back to Custom Fieldset List @stop diff --git a/app/views/backend/custom_fields/create_field.blade.php b/app/views/backend/custom_fields/create_field.blade.php index e60baf9bb1..a04e0a1b19 100644 --- a/app/views/backend/custom_fields/create_field.blade.php +++ b/app/views/backend/custom_fields/create_field.blade.php @@ -5,8 +5,9 @@ {{ Form::open(["url" =>"/custom_fieldsets/create-field"])}} Name: {{ Form::text("name")}}
    type: {{ Form::select("element",["text" => "Text Box"])}}
    -format: {{ Form::select("format",predefined_formats(),"ALPHA") }} +format: {{ Form::select("format",predefined_formats(),"ANY") }} Custom Format (if selected): {{ Form::text("custom_format") }}
    {{ Form::close() }} +
    Back to Custom Fieldset List @stop diff --git a/app/views/backend/custom_fields/show.blade.php b/app/views/backend/custom_fields/show.blade.php index 68a9eaea8e..72cf6a7fbf 100644 --- a/app/views/backend/custom_fields/show.blade.php +++ b/app/views/backend/custom_fields/show.blade.php @@ -12,4 +12,5 @@ {{ Form::checkbox("required","on") }}Required? {{ Form::text("order",$maxid)}} {{ Form::select("field_id",["" => "Add New Field to Fieldset"] + CustomField::lists("name","id"),"",["onchange" => "document.forms[0].submit()"]) }} +
    Back to Custom Fieldset List @stop From 924f61fce980ccbe9141cb95869edfc269387d23 Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Wed, 25 Nov 2015 16:09:16 -0800 Subject: [PATCH 021/119] Cache custom field listing for assets, custom fields are sortable --- app/controllers/admin/AssetsController.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index b3aa4b2eb9..567fcb3d80 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -1218,7 +1218,7 @@ class AssetsController extends AdminController { - $assets = Asset::select('assets.*')->with('model','assigneduser','assigneduser.userloc','assetstatus','defaultLoc','assetlog','model','model.category','assetstatus','assetloc', 'company') + $assets = Asset::select('assets.*')->with('model','assigneduser','assigneduser.userloc','assetstatus','defaultLoc','assetlog','model','model.category','model.fieldset','assetstatus','assetloc', 'company') ->Hardware(); if (Input::has('search')) { @@ -1281,6 +1281,12 @@ class AssetsController extends AdminController 'location', 'image', ]; + + $all_custom_fields=CustomField::all(); //used as a 'cache' of custom fields throughout this page load + + foreach($all_custom_fields AS $field) { + $allowed_columns[]=$field->db_column_name(); + } $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'asset_tag'; @@ -1351,7 +1357,7 @@ class AssetsController extends AdminController 'actions' => ($actions) ? $actions : '', 'companyName' => is_null($asset->company) ? '' : e($asset->company->name) ); - foreach(CustomField::all() AS $field) { + foreach($all_custom_fields AS $field) { $row[$field->db_column_name()]=$asset->{$field->db_column_name()}; } $rows[]=$row; From c0e988b6b16ac7ee97cc3f6e3b67357dfe658d70 Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Wed, 25 Nov 2015 20:14:26 -0800 Subject: [PATCH 022/119] Basic validation on customFieldset --- app/controllers/CustomFieldsController.php | 10 +++++++--- app/models/CustomField.php | 4 ++++ app/models/CustomFieldset.php | 5 +++++ app/views/backend/custom_fields/create.blade.php | 3 +-- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/app/controllers/CustomFieldsController.php b/app/controllers/CustomFieldsController.php index c56156ee37..b7fb64b459 100644 --- a/app/controllers/CustomFieldsController.php +++ b/app/controllers/CustomFieldsController.php @@ -35,9 +35,13 @@ class CustomFieldsController extends \BaseController { { // $cfset=new CustomFieldset(["name" => Input::get("name")]); - $cfset->save(); - return Redirect::to("/custom_fieldsets/".$cfset->id); //redirect(["asdf" => "alskdjf"]); - + $validator=Validator::make(Input::all(),$cfset->rules); + if($validator->passes()) { + $cfset->save(); + return Redirect::to("/custom_fieldsets/".$cfset->id); //redirect(["asdf" => "alskdjf"]); + } else { + return Redirect::to("/custom_fieldsets/create")->withErrors($validator); + } } public function postAssociate($id) diff --git a/app/models/CustomField.php b/app/models/CustomField.php index caaf04880f..c74488dd91 100644 --- a/app/models/CustomField.php +++ b/app/models/CustomField.php @@ -11,6 +11,10 @@ class CustomField extends Elegant "IP" => "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])" ]; + public $rules=[ + "name" => "required|unique" + ]; + public static $table_name="assets"; public static function name_to_db_name($name) diff --git a/app/models/CustomFieldset.php b/app/models/CustomFieldset.php index 7ddfd5a278..e30266daf1 100644 --- a/app/models/CustomFieldset.php +++ b/app/models/CustomFieldset.php @@ -3,6 +3,11 @@ class CustomFieldset extends Elegant { protected $guarded=["id"]; public $timestamps=false; + + public $rules=[ + "name" => "required|unique:custom_fieldsets" + ]; + public function fields() { return $this->belongsToMany('CustomField')->withPivot(["required","order"])->orderBy("pivot_order"); } diff --git a/app/views/backend/custom_fields/create.blade.php b/app/views/backend/custom_fields/create.blade.php index d7cc1b83b9..0af7638adf 100644 --- a/app/views/backend/custom_fields/create.blade.php +++ b/app/views/backend/custom_fields/create.blade.php @@ -1,9 +1,8 @@ @extends('backend/layouts/default') @section('content') - '/custom_fieldsets']) ?> - Name:
    + Name: first('name'); ?>

    Back to Custom Fieldset List From 10086479b788fc2ff66d695f100c09f58c7bb488 Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Wed, 25 Nov 2015 20:38:22 -0800 Subject: [PATCH 023/119] Better erroring, return previous input on error. --- app/controllers/CustomFieldsController.php | 18 ++++++++++++------ app/models/CustomField.php | 2 +- .../backend/custom_fields/create.blade.php | 2 +- .../custom_fields/create_field.blade.php | 6 +++--- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/app/controllers/CustomFieldsController.php b/app/controllers/CustomFieldsController.php index b7fb64b459..dda99834ed 100644 --- a/app/controllers/CustomFieldsController.php +++ b/app/controllers/CustomFieldsController.php @@ -40,7 +40,7 @@ class CustomFieldsController extends \BaseController { $cfset->save(); return Redirect::to("/custom_fieldsets/".$cfset->id); //redirect(["asdf" => "alskdjf"]); } else { - return Redirect::to("/custom_fieldsets/create")->withErrors($validator); + return Redirect::back()->withInput()->withErrors($validator); } } @@ -66,12 +66,18 @@ class CustomFieldsController extends \BaseController { } else { $field->format=Input::get('format'); } - $results=$field->save(); - //return "postCreateField: $results"; - if ($results) { - return Redirect::to("/custom_fieldsets/"); + + $validator=Validator::make(Input::all(),$field->rules); + if($validator->passes()) { + $results=$field->save(); + //return "postCreateField: $results"; + if ($results) { + return Redirect::to("/custom_fieldsets/"); + } else { + return Redirect::back()->withInput()->withErrors(['message' => "Failed to save?"]); + } } else { - return Redirect::to("/custom_fieldsets/create-field"); + return Redirect::back()->withInput()->withErrors($validator); } } diff --git a/app/models/CustomField.php b/app/models/CustomField.php index c74488dd91..fd28b85540 100644 --- a/app/models/CustomField.php +++ b/app/models/CustomField.php @@ -12,7 +12,7 @@ class CustomField extends Elegant ]; public $rules=[ - "name" => "required|unique" + "name" => "required|unique:custom_fields" ]; public static $table_name="assets"; diff --git a/app/views/backend/custom_fields/create.blade.php b/app/views/backend/custom_fields/create.blade.php index 0af7638adf..c21c80ee6a 100644 --- a/app/views/backend/custom_fields/create.blade.php +++ b/app/views/backend/custom_fields/create.blade.php @@ -2,7 +2,7 @@ @section('content') '/custom_fieldsets']) ?> - Name: first('name'); ?>
    + Name: {{Form::text("name",Input::old('name'))}}first('name'); ?>

    Back to Custom Fieldset List diff --git a/app/views/backend/custom_fields/create_field.blade.php b/app/views/backend/custom_fields/create_field.blade.php index a04e0a1b19..df0ec7495f 100644 --- a/app/views/backend/custom_fields/create_field.blade.php +++ b/app/views/backend/custom_fields/create_field.blade.php @@ -3,9 +3,9 @@ {{ Form::open(["url" =>"/custom_fieldsets/create-field"])}} -Name: {{ Form::text("name")}}
    -type: {{ Form::select("element",["text" => "Text Box"])}}
    -format: {{ Form::select("format",predefined_formats(),"ANY") }} +Name: {{ Form::text("name")}}first('name'); ?>
    +type: {{ Form::select("element",["text" => "Text Box"])}}first('element'); ?>
    +format: {{ Form::select("format",predefined_formats(),"ANY") }}first('format'); ?> Custom Format (if selected): {{ Form::text("custom_format") }}
    {{ Form::close() }} From 6708911d5dcac9e50883a3494e1ec1eed90d4811 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 26 Nov 2015 13:33:01 -0800 Subject: [PATCH 024/119] Remove mac address (now custom field) --- app/controllers/admin/AssetsController.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index 567fcb3d80..2481e6e231 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -161,7 +161,6 @@ class AssetsController extends AdminController } $checkModel = Config::get('app.url').'/api/models/'.e(Input::get('model_id')).'/check'; - $asset->mac_address = ($checkModel == true) ? e(Input::get('mac_address')) : NULL; // Save the asset data $asset->name = e(Input::get('name')); @@ -269,7 +268,7 @@ class AssetsController extends AdminController else if (!Company::isCurrentUserHasAccess($asset)) { return Redirect::to('hardware')->with('error', Lang::get('general.insufficient_permissions')); } - + $input=Input::all(); // return "INPUT IS:
    ".print_r($input,true)."
    "; $rules=$asset->validationRules($assetId); @@ -282,12 +281,12 @@ class AssetsController extends AdminController $rules+=$asset->model->fieldset->validation_rules(); unset($input['fields']); } - + //return "Rules:
    ".print_r($rules,true)."
    "; //attempt to validate $validator = Validator::make($input, $rules ); - + $custom_errors=[]; if ($validator->fails()) @@ -1281,9 +1280,9 @@ class AssetsController extends AdminController 'location', 'image', ]; - + $all_custom_fields=CustomField::all(); //used as a 'cache' of custom fields throughout this page load - + foreach($all_custom_fields AS $field) { $allowed_columns[]=$field->db_column_name(); } From 1efb1f703832c3b1cb310d199c1660f30db67242 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 26 Nov 2015 13:42:13 -0800 Subject: [PATCH 025/119] Remove MAC address fields since they are now custom fields --- app/controllers/admin/AssetsController.php | 2 +- app/routes.php | 9 +----- app/views/backend/hardware/edit.blade.php | 35 ++-------------------- 3 files changed, 4 insertions(+), 42 deletions(-) diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index 2481e6e231..73f7b603be 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -859,7 +859,7 @@ class AssetsController extends AdminController $asset->asset_tag = ''; $asset->serial = ''; $asset->assigned_to = ''; - $asset->mac_address = ''; + return View::make('backend/hardware/edit') ->with('supplier_list',$supplier_list) ->with('model_list',$model_list) diff --git a/app/routes.php b/app/routes.php index 89382fa80c..ca2cb79309 100755 --- a/app/routes.php +++ b/app/routes.php @@ -115,13 +115,6 @@ Route::resource( '/', 'ModelsController' ); Route::get( 'list/{status?}', [ 'as' => 'api.models.list', 'uses' => 'ModelsController@getDatatable' ] ); - Route::get( '{modelId}/check', function ( $modelId ) { - - $model = Model::find( $modelId ); - - return $model->show_mac_address; - } ); - Route::get( '{modelID}/view', [ 'as' => 'api.models.view', 'uses' => 'ModelsController@getDataView' ] ); } ); @@ -140,7 +133,7 @@ } ); } ); - + # Custom fieldset //Route::get('/custom_fieldsets/{id}','CustomFieldsController@show'); //Route::get('/custom_fieldsets/create','CustomFieldsController@getCreate'); diff --git a/app/views/backend/hardware/edit.blade.php b/app/views/backend/hardware/edit.blade.php index d3169cb6c9..57dc4c76c9 100755 --- a/app/views/backend/hardware/edit.blade.php +++ b/app/views/backend/hardware/edit.blade.php @@ -187,14 +187,6 @@ - -
    - -
    - - {{ $errors->first('mac_address', '
    :message') }} -
    -
    @@ -318,7 +310,7 @@
    - + @if($asset->model && $asset->model->fieldset)

    Custom Fields

    @@ -369,30 +361,7 @@ - - + + - - + +