- Added 'Newsletters' model and wrote tests

- Fixed some formatting in unit tests
Closes #68
This commit is contained in:
Vlad
2015-08-14 13:31:45 +00:00
parent 3b00e453a5
commit 78b5791a46
10 changed files with 450 additions and 195 deletions

View File

@@ -1,122 +1,122 @@
<?php <?php
class RoboFile extends \Robo\Tasks { class RoboFile extends \Robo\Tasks {
function install() { function install() {
$this->_exec('./composer.phar install'); $this->_exec('./composer.phar install');
$this->_exec('npm install'); $this->_exec('npm install');
} }
function update() { function update() {
$this->say(getenv('WP_TEST_URL')); $this->say(getenv('WP_TEST_URL'));
$this->_exec('./composer.phar update'); $this->_exec('./composer.phar update');
$this->_exec('npm update'); $this->_exec('npm update');
} }
function watch() { function watch() {
$css_files = array( $css_files = array(
'assets/css/src/admin.styl', 'assets/css/src/admin.styl',
'assets/css/src/rtl.styl' 'assets/css/src/rtl.styl'
); );
$js_files = glob('assets/js/src/*.js'); $js_files = glob('assets/js/src/*.js');
$this->taskWatch() $this->taskWatch()
->monitor($js_files, function() { ->monitor($js_files, function() {
$this->compileJavascript(); $this->compileJavascript();
}) })
->monitor($css_files, function() use($css_files) { ->monitor($css_files, function() use($css_files) {
$this->compileStyles($css_files); $this->compileStyles($css_files);
}) })
->run(); ->run();
} }
function compileJavascript() { function compileJavascript() {
$this->_exec('./node_modules/webpack/bin/webpack.js'); $this->_exec('./node_modules/webpack/bin/webpack.js');
} }
protected function compileStyles($files = array()) { protected function compileStyles($files = array()) {
if(empty($files)) { return; } if(empty($files)) { return; }
$this->_exec(join(' ', array( $this->_exec(join(' ', array(
'./node_modules/stylus/bin/stylus', './node_modules/stylus/bin/stylus',
'-u nib', '-u nib',
'-w', '-w',
join(' ', $files), join(' ', $files),
'-o assets/css/' '-o assets/css/'
))); )));
} }
function makepot() { function makepot() {
$this->_exec('grunt makepot'. $this->_exec('grunt makepot'.
' --gruntfile '.__DIR__.'/tasks/makepot/makepot.js'. ' --gruntfile '.__DIR__.'/tasks/makepot/makepot.js'.
' --base_path '.__DIR__ ' --base_path '.__DIR__
); );
} }
function pushpot() { function pushpot() {
$this->_exec('grunt pushpot'. $this->_exec('grunt pushpot'.
' --gruntfile '.__DIR__.'/tasks/makepot/makepot.js'. ' --gruntfile '.__DIR__.'/tasks/makepot/makepot.js'.
' --base_path '.__DIR__ ' --base_path '.__DIR__
); );
} }
function testUnit($singleUnit = null) { function testUnit($singleUnit = null) {
$this->loadEnv(); $this->loadEnv();
$this->_exec('vendor/bin/codecept build'); $this->_exec('vendor/bin/codecept build');
$this->_exec('vendor/bin/codecept run unit ' . (($singleUnit) ? $singleUnit : '')); $this->_exec('vendor/bin/codecept run unit ' . (($singleUnit) ? $singleUnit : ''));
} }
function testAcceptance() { function testAcceptance() {
$this->loadEnv(); $this->loadEnv();
$this->_exec('vendor/bin/codecept build'); $this->_exec('vendor/bin/codecept build');
$this $this
->taskExec('phantomjs --webdriver=4444') ->taskExec('phantomjs --webdriver=4444')
->background() ->background()
->run(); ->run();
sleep(2); sleep(2);
$this->_exec('vendor/bin/codecept run acceptance'); $this->_exec('vendor/bin/codecept run acceptance');
} }
function testJavascript() { function testJavascript() {
$this->compileJavascript(); $this->compileJavascript();
$this->_exec(join(' ', array( $this->_exec(join(' ', array(
'./node_modules/mocha/bin/mocha', './node_modules/mocha/bin/mocha',
'-r tests/javascript/mochaTestHelper.js', '-r tests/javascript/mochaTestHelper.js',
'tests/javascript/testBundles/**/*.js' 'tests/javascript/testBundles/**/*.js'
))); )));
} }
function testAll() { function testAll() {
$this->loadEnv(); $this->loadEnv();
$this->_exec('vendor/bin/codecept build'); $this->_exec('vendor/bin/codecept build');
$this $this
->taskexec('phantomjs --webdriver=4444') ->taskexec('phantomjs --webdriver=4444')
->background() ->background()
->run(); ->run();
sleep(2); sleep(2);
$this->_exec('vendor/bin/codecept run'); $this->_exec('vendor/bin/codecept run');
} }
function testDebug() { function testDebug() {
$this->_exec('vendor/bin/codecept build'); $this->_exec('vendor/bin/codecept build');
$this->loadEnv(); $this->loadEnv();
$this->_exec('vendor/bin/codecept run unit --debug'); $this->_exec('vendor/bin/codecept run unit --debug');
} }
protected function loadEnv() { protected function loadEnv() {
$dotenv = new Dotenv\Dotenv(__DIR__); $dotenv = new Dotenv\Dotenv(__DIR__);
$dotenv->load(); $dotenv->load();
$this $this
->taskWriteToFile('tests/acceptance.suite.yml') ->taskWriteToFile('tests/acceptance.suite.yml')
->textFromFile('tests/acceptance.suite.src') ->textFromFile('tests/acceptance.suite.src')
->run(); ->run();
$this $this
->taskReplaceInFile('tests/acceptance.suite.yml') ->taskReplaceInFile('tests/acceptance.suite.yml')
->regex("/url.*/") ->regex("/url.*/")
->to('url: ' . "'" . getenv('WP_TEST_URL'). "'") ->to('url: ' . "'" . getenv('WP_TEST_URL'). "'")
->run(); ->run();
} }
} }

133
RoboFile.php.orig Normal file
View File

@@ -0,0 +1,133 @@
<?php
class RoboFile extends \Robo\Tasks {
function install() {
$this->_exec('./composer.phar install');
$this->_exec('npm install');
}
function update() {
$this->say(getenv('WP_TEST_URL'));
$this->_exec('./composer.phar update');
$this->_exec('npm update');
}
function watch() {
$css_files = array(
'assets/css/src/admin.styl',
'assets/css/src/rtl.styl'
);
<<<<<<< HEAD
$command = array(
'./node_modules/stylus/bin/stylus -u',
' nib -w' . join(' ', $files) . ' -o assets/css/'
);
$this->_exec(join(' ', $command));
=======
$js_files = glob('assets/js/src/*.js');
$this->taskWatch()
->monitor($js_files, function() {
$this->compileJavascript();
})
->monitor($css_files, function() use($css_files) {
$this->compileStyles($css_files);
})
->run();
}
function compileJavascript() {
$this->_exec('./node_modules/webpack/bin/webpack.js');
}
protected function compileStyles($files = array()) {
if(empty($files)) { return; }
$this->_exec(join(' ', array(
'./node_modules/stylus/bin/stylus',
'-u nib',
'-w',
join(' ', $files),
'-o assets/css/'
)));
>>>>>>> origin/master
}
function makepot() {
$this->_exec('grunt makepot' . ' --gruntfile '
. __DIR__ . '/tasks/makepot/makepot.js'
. ' --base_path ' . __DIR__);
}
function pushpot() {
$this->_exec('grunt pushpot' . ' --gruntfile '
. __DIR__ . '/tasks/makepot/makepot.js'
. ' --base_path ' . __DIR__);
}
function testUnit() {
$this->loadEnv();
$this->_exec('vendor/bin/codecept build');
$this->_exec('vendor/bin/codecept run unit');
}
function testUnitSingle($unit = null) {
if (!$unit) {
throw new Exception("Your need to specify what you want to test (e.g.: test:unit-single models/SubscriberCest)");
}
$this->loadEnv();
$this->_exec('vendor/bin/codecept build');
$this->_exec('vendor/bin/codecept run unit ' . $unit);
}
function testAcceptance() {
$this->loadEnv();
$this->_exec('vendor/bin/codecept build');
$this->taskExec('phantomjs --webdriver=4444')
->background()
->run();
sleep(2);
$this->_exec('vendor/bin/codecept run acceptance');
}
function testJavascript() {
$this->compileJavascript();
$this->_exec(join(' ', array(
'./node_modules/mocha/bin/mocha',
'-r tests/javascript/mochaTestHelper.js',
'tests/javascript/testBundles/**/*.js'
)));
}
function testAll() {
$this->loadEnv();
$this->_exec('vendor/bin/codecept build');
$this->taskexec('phantomjs --webdriver=4444')
->background()
->run();
sleep(2);
$this->_exec('vendor/bin/codecept run');
}
function testDebug() {
$this->_exec('vendor/bin/codecept build');
$this->loadEnv();
$this->_exec('vendor/bin/codecept run unit --debug');
}
protected function loadEnv() {
$dotenv = new Dotenv\Dotenv(__DIR__);
$dotenv->load();
$this->taskWriteToFile('tests/acceptance.suite.yml')
->textFromFile('tests/acceptance.suite.src')
->run();
$this->taskReplaceInFile('tests/acceptance.suite.yml')
->regex("/url.*/")
->to('url: ' . "'" . getenv('WP_TEST_URL') . "'")
->run();
}
}

View File

@@ -1,15 +1,16 @@
<?php <?php
namespace MailPoet\Config; namespace MailPoet\Config;
use MailPoet\Models; use MailPoet\Models;
if(!defined('ABSPATH')) exit; if (!defined('ABSPATH')) exit;
class Initializer { class Initializer {
public function __construct($params = array( public function __construct($params = array(
'file' => '', 'file' => '',
'version' => '1.0.0' 'version' => '1.0.0'
)) { )) {
Env::init($params['file'], $params['version']); Env::init($params['file'], $params['version']);
} }
function init() { function init() {
@@ -27,9 +28,11 @@ class Initializer {
$subscribers = Env::$db_prefix . 'subscribers'; $subscribers = Env::$db_prefix . 'subscribers';
$settings = Env::$db_prefix . 'settings'; $settings = Env::$db_prefix . 'settings';
$newsletters = Env::$db_prefix . 'newsletters';
define('MP_SUBSCRIBERS_TABLE', $subscribers); define('MP_SUBSCRIBERS_TABLE', $subscribers);
define('MP_SETTINGS_TABLE', $settings); define('MP_SETTINGS_TABLE', $settings);
define('MP_NEWSLETTERS_TABLE', $newsletters);
} }
function setupActivator() { function setupActivator() {

View File

@@ -1,8 +1,7 @@
<?php <?php
namespace MailPoet\Config; namespace MailPoet\Config;
use \MailPoet\Config\Env;
if(!defined('ABSPATH')) exit; if (!defined('ABSPATH')) exit;
require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
@@ -12,15 +11,16 @@ class Migrator {
$this->charset = Env::$db_charset; $this->charset = Env::$db_charset;
$this->models = array( $this->models = array(
'subscribers', 'subscribers',
'settings' 'settings',
'newsletters'
); );
} }
function up() { function up() {
global $wpdb; global $wpdb;
$_this = $this; $_this = $this;
$migrate = function($model) use ($_this) { $migrate = function ($model) use ($_this) {
dbDelta($_this->$model()); dbDelta($_this->$model());
}; };
@@ -30,7 +30,7 @@ class Migrator {
function down() { function down() {
global $wpdb; global $wpdb;
$drop_table = function($model) { $drop_table = function ($model) {
$table = $this->prefix . $model; $table = $this->prefix . $model;
$wpdb->query("DROP TABLE {$table}"); $wpdb->query("DROP TABLE {$table}");
}; };
@@ -65,13 +65,25 @@ class Migrator {
return $this->sqlify(__FUNCTION__, $attributes); return $this->sqlify(__FUNCTION__, $attributes);
} }
function newsletters() {
$attributes = array(
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
'subject varchar(250) NOT NULL,',
'body longtext,',
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
'PRIMARY KEY (id)'
);
return $this->sqlify(__FUNCTION__, $attributes);
}
private function sqlify($model, $attributes) { private function sqlify($model, $attributes) {
$table = $this->prefix . $model; $table = $this->prefix . $model;
$sql = array(); $sql = array();
$sql[] = "CREATE TABLE " . $table . " ("; $sql[] = "CREATE TABLE " . $table . " (";
$sql = array_merge($sql, $attributes); $sql = array_merge($sql, $attributes);
$sql[] = ") " . $this->charset . ";"; $sql[] = ") " . $this->charset . ";";
return implode("\n", $sql); return implode("\n", $sql);
} }

17
lib/Models/Newsletter.php Normal file
View File

@@ -0,0 +1,17 @@
<?php
namespace MailPoet\Models;
if (!defined('ABSPATH')) exit;
class Newsletter extends Model {
public static $_table = MP_NEWSLETTERS_TABLE;
function __construct() {
$this->addValidations('subject', array(
'required' => "subject_is_blank"
));
$this->addValidations('body', array(
'required' => "body_is_blank"
));
}
}

View File

@@ -1,43 +1,43 @@
{ {
"private": true, "private": true,
"scripts": { "scripts": {
"install": "napa" "install": "napa"
}, },
"napa": { "napa": {
"sticky-kit": "leafo/sticky-kit.git", "sticky-kit": "leafo/sticky-kit.git",
"jquery-validation-engine": "posabsolute/jQuery-Validation-Engine.git", "jquery-validation-engine": "posabsolute/jQuery-Validation-Engine.git",
"interact.js": "taye/interact.js.git" "interact.js": "taye/interact.js.git"
}, },
"dependencies": { "dependencies": {
"backbone": "1.2.0", "backbone": "1.2.0",
"backbone.marionette": "2.4.2", "backbone.marionette": "2.4.2",
"backbone.radio": "0.9.0", "backbone.radio": "0.9.0",
"backbone.supermodel": "1.2.0", "backbone.supermodel": "1.2.0",
"c3": "~0.4.10", "c3": "~0.4.10",
"codemirror": "^5.5.0", "codemirror": "^5.5.0",
"d3": "~3.5.5", "d3": "~3.5.5",
"handlebars": "3.0.3", "handlebars": "3.0.3",
"html2canvas": "latest", "html2canvas": "latest",
"moment": "^2.10.3", "moment": "^2.10.3",
"papaparse": "4.1.1", "papaparse": "4.1.1",
"select2": "3.5.1", "select2": "3.5.1",
"spectrum-colorpicker": "^1.6.2", "spectrum-colorpicker": "^1.6.2",
"tinymce": "4.1.10", "tinymce": "4.1.10",
"underscore": "1.8.3", "underscore": "1.8.3",
"napa": "^1.2.0" "napa": "^1.2.0"
}, },
"devDependencies": { "devDependencies": {
"chai": "2.2.0", "chai": "2.2.0",
"chai-jq": "0.0.8", "chai-jq": "0.0.8",
"grunt": "^0.4.5", "grunt": "^0.4.5",
"jquery": "2.1.4", "jquery": "2.1.4",
"jsdom": "3.1.2", "jsdom": "3.1.2",
"mocha": "2.2.1", "mocha": "2.2.1",
"nib": "latest", "nib": "latest",
"sinon": "1.14.1", "sinon": "1.14.1",
"sinon-chai": "2.7.0", "sinon-chai": "2.7.0",
"stylus": "latest", "stylus": "latest",
"swag": "~0.7.0", "swag": "~0.7.0",
"webpack": "1.11.0" "webpack": "1.11.0"
} }
} }

View File

@@ -7,11 +7,12 @@ require_once(getenv('WP_TEST_PATH') . '/wp-load.php');
$console->writeln('Cleaning up database...'); $console->writeln('Cleaning up database...');
$models = array( $models = array(
"Subscriber", "Subscriber",
"Setting" "Setting",
"Newsletter"
); );
$destroy = function ($model) { $destroy = function ($model) {
Model::factory("\MailPoet\Models\\" . $model) Model::factory("\MailPoet\Models\\" . $model)
->delete_many(); ->delete_many();
}; };
array_map($destroy, $models); array_map($destroy, $models);

View File

@@ -0,0 +1,75 @@
<?php
use MailPoet\Models\Newsletter;
class NewsletterCest {
function _before() {
$this->before_time = time();
$this->data = array(
'subject' => 'My First Newsletter',
'body' => 'a verrryyyyy long body :)'
);
$newsletter = Newsletter::create();
$newsletter->hydrate($this->data);
$newsletter->save();
}
function itCanBeCreated() {
$newsletter = Newsletter::where('subject', $this->data['subject'])
->findOne();
expect($newsletter->id)->notNull();
}
function subjectShouldValidate() {
$conflict_newsletter = Newsletter::create();
$conflict_newsletter->validateField('subject', '');
expect($conflict_newsletter->getValidationErrors()[0])->equals('subject_is_blank');
}
function bodyShouldValidate() {
$conflict_newsletter = Newsletter::create();
$conflict_newsletter->validateField('body', '');
expect($conflict_newsletter->getValidationErrors()[0])->equals('body_is_blank');
}
function itHasACreatedAtOnCreation() {
$newsletter = Newsletter::where('subject', $this->data['subject'])
->findOne();
$time_difference = strtotime($newsletter->created_at) >= $this->before_time;
expect($time_difference)->equals(true);
}
function itHasAnUpdatedAtOnCreation() {
$newsletter = Newsletter::where('subject', $this->data['subject'])
->findOne();
$time_difference = strtotime($newsletter->updated_at) >= $this->before_time;
expect($time_difference)->equals(true);
}
function itKeepsTheCreatedAtOnUpdate() {
$newsletter = Newsletter::where('subject', $this->data['subject'])
->findOne();
$old_created_at = $newsletter->created_at;
$newsletter->subject = $this->data['subject'];
$newsletter->save();
expect($old_created_at)->equals($newsletter->created_at);
}
function itUpdatesTheUpdatedAtOnUpdate() {
$newsletter = Newsletter::where('subject', $this->data['subject'])
->findOne();
$update_time = time();
$newsletter->subject = $this->data['subject'];
$newsletter->save();
$time_difference = strtotime($newsletter->updated_at) >= $update_time;
expect($time_difference)->equals(true);
}
function _after() {
$newsletter = Newsletter::where('subject', $this->data['subject'])
->findOne()
->delete();
}
}

View File

@@ -2,7 +2,7 @@
use MailPoet\Models\Setting; use MailPoet\Models\Setting;
class SettingCest { class SettingCest {
function _before() { function _before() {
$this->before_time = time(); $this->before_time = time();
$this->data = array( $this->data = array(
@@ -16,7 +16,8 @@ class SettingCest {
} }
function itCanBeCreated() { function itCanBeCreated() {
$setting = Setting::where('name', $this->data['name'])->findOne(); $setting = Setting::where('name', $this->data['name'])
->findOne();
expect($setting->id)->notNull(); expect($setting->id)->notNull();
} }
@@ -49,19 +50,22 @@ class SettingCest {
} }
function itHasACreatedAtOnCreation() { function itHasACreatedAtOnCreation() {
$setting = Setting::where('name', 'sending_method')->findOne(); $setting = Setting::where('name', $this->data['name'])
->findOne();
$time_difference = strtotime($setting->created_at) >= $this->before_time; $time_difference = strtotime($setting->created_at) >= $this->before_time;
expect($time_difference)->equals(true); expect($time_difference)->equals(true);
} }
function itHasAnUpdatedAtOnCreation() { function itHasAnUpdatedAtOnCreation() {
$setting = Setting::where('name', 'sending_method')->findOne(); $setting = Setting::where('name', $this->data['name'])
->findOne();
$time_difference = strtotime($setting->updated_at) >= $this->before_time; $time_difference = strtotime($setting->updated_at) >= $this->before_time;
expect($time_difference)->equals(true); expect($time_difference)->equals(true);
} }
function itKeepsTheCreatedAtOnUpdate() { function itKeepsTheCreatedAtOnUpdate() {
$setting = Setting::where('name', 'sending_method')->findOne(); $setting = Setting::where('name', $this->data['name'])
->findOne();
$old_created_at = $setting->created_at; $old_created_at = $setting->created_at;
$setting->value = 'http_api'; $setting->value = 'http_api';
$setting->save(); $setting->save();
@@ -69,15 +73,18 @@ class SettingCest {
} }
function itUpdatesTheUpdatedAtOnUpdate() { function itUpdatesTheUpdatedAtOnUpdate() {
$setting = Setting::where('name', 'sending_method')->findOne(); $setting = Setting::where('name', $this->data['name'])
->findOne();
$update_time = time(); $update_time = time();
$setting->value = 'http_api'; $setting->value = 'http_api';
$setting->save(); $setting->save();
$time_difference = strtotime($setting->updated_at) >= $update_time; $time_difference = strtotime($setting->updated_at) >= $update_time;
expect($time_difference)->equals(true); expect($time_difference)->equals(true);
} }
function _after() { function _after() {
$setting = Setting::where('name', $this->data['name'])->findOne()->delete(); $setting = Setting::where('name', $this->data['name'])
->findOne()
->delete();
} }
} }

View File

@@ -17,22 +17,26 @@ class SubscriberCest {
} }
function itCanBeCreated() { function itCanBeCreated() {
$subscriber = Subscriber::where('email', $this->data['email'])->findOne(); $subscriber = Subscriber::where('email', $this->data['email'])
->findOne();
expect($subscriber->id)->notNull(); expect($subscriber->id)->notNull();
} }
function itHasAFirstName() { function itHasAFirstName() {
$subscriber = Subscriber::where('email', $this->data['email'])->findOne(); $subscriber = Subscriber::where('email', $this->data['email'])
->findOne();
expect($subscriber->first_name)->equals($this->data['first_name']); expect($subscriber->first_name)->equals($this->data['first_name']);
} }
function itHasALastName() { function itHasALastName() {
$subscriber = Subscriber::where('email', $this->data['email'])->findOne(); $subscriber = Subscriber::where('email', $this->data['email'])
->findOne();
expect($subscriber->last_name)->equals($this->data['last_name']); expect($subscriber->last_name)->equals($this->data['last_name']);
} }
function itHasAnEmail() { function itHasAnEmail() {
$subscriber = Subscriber::where('email', $this->data['email'])->findOne(); $subscriber = Subscriber::where('email', $this->data['email'])
->findOne();
expect($subscriber->email)->equals($this->data['email']); expect($subscriber->email)->equals($this->data['email']);
} }
@@ -81,21 +85,21 @@ class SubscriberCest {
function itHasACreatedAtOnCreation() { function itHasACreatedAtOnCreation() {
$subscriber = Subscriber::where('email', $this->data['email']) $subscriber = Subscriber::where('email', $this->data['email'])
->findOne(); ->findOne();
$time_difference = strtotime($subscriber->created_at) >= $this->before_time; $time_difference = strtotime($subscriber->created_at) >= $this->before_time;
expect($time_difference)->equals(true); expect($time_difference)->equals(true);
} }
function itHasAnUpdatedAtOnCreation() { function itHasAnUpdatedAtOnCreation() {
$subscriber = Subscriber::where('email', $this->data['email']) $subscriber = Subscriber::where('email', $this->data['email'])
->findOne(); ->findOne();
$time_difference = strtotime($subscriber->updated_at) >= $this->before_time; $time_difference = strtotime($subscriber->updated_at) >= $this->before_time;
expect($time_difference)->equals(true); expect($time_difference)->equals(true);
} }
function itKeepsTheCreatedAtOnUpdate() { function itKeepsTheCreatedAtOnUpdate() {
$subscriber = Subscriber::where('email', $this->data['email']) $subscriber = Subscriber::where('email', $this->data['email'])
->findOne(); ->findOne();
$old_created_at = $subscriber->created_at; $old_created_at = $subscriber->created_at;
@@ -106,7 +110,8 @@ class SubscriberCest {
} }
function itUpdatesTheUpdatedAtOnUpdate() { function itUpdatesTheUpdatedAtOnUpdate() {
$subscriber = Subscriber::where('email', $this->data['email'])->findOne(); $subscriber = Subscriber::where('email', $this->data['email'])
->findOne();
$update_time = time(); $update_time = time();
$subscriber->first_name = 'New Name'; $subscriber->first_name = 'New Name';
@@ -118,7 +123,9 @@ class SubscriberCest {
} }
function _after() { function _after() {
$subscriber = Subscriber::where('email', $this->data['email'])->findOne()->delete(); $subscriber = Subscriber::where('email', $this->data['email'])
->findOne()
->delete();
} }
} }