diff --git a/src/Controller/AppController.php b/src/Controller/AppController.php index ca9f89084..3c0dda80f 100644 --- a/src/Controller/AppController.php +++ b/src/Controller/AppController.php @@ -20,6 +20,7 @@ use Cake\Http\Client; use Cake\Routing\Router; use Cake\ORM\TableRegistry; use Cake\Core\Configure; +use Cake\I18n\Time; /** * Application Controller @@ -288,4 +289,14 @@ class AppController extends Controller $response = $this->response->withType('application/json'); return $response->withStringBody(json_encode($array)); } + + public function getStartEndForMonth($month, $year) + { + $timeString = $year . '-' . $month . '-01 00:00'; + $firstDay = new Time($timeString); + $lastDay = new Time($timeString); + $lastDay = $lastDay->addMonth(1); + return [$firstDay, $lastDay]; + } + } diff --git a/src/Controller/ElopageBuysController.php b/src/Controller/ElopageBuysController.php index 725700cd8..63e36cb7a 100644 --- a/src/Controller/ElopageBuysController.php +++ b/src/Controller/ElopageBuysController.php @@ -2,6 +2,11 @@ namespace App\Controller; use App\Controller\AppController; +use Cake\Datasource\ConnectionManager; +use Cake\I18n\Time; +//use Cake\I18n\Date; + +use Cake\ORM\TableRegistry; /** * ElopageBuys Controller @@ -20,12 +25,62 @@ class ElopageBuysController extends AppController public function index() { $this->paginate = [ - 'contain' => ['ElopageUsers', 'AffiliatePrograms', 'Publishers', 'Orders', 'Products'], + 'contain' => false, ]; $elopageBuys = $this->paginate($this->ElopageBuys); $this->set(compact('elopageBuys')); } + + public function statistics() + { + $this->viewBuilder()->setLayout('frontend_ripple'); + $connection = ConnectionManager::get('loginServer'); + $dates = $connection->execute('SELECT success_date FROM elopage_buys group by CAST(success_date as DATE)')->fetchAll('assoc'); + + $datesTree = []; + foreach($dates as $i => $date) { + + $date = new Time($date['success_date']); + if(!isset($datesTree[$date->year])) { + $datesTree[$date->year] = []; + } + if(!isset($datesTree[$date->year][$date->month])) { + $datesTree[$date->year][$date->month] = true; + } + } + //var_dump($datesTree); + + $now = Time::now(); + $lastDay = Time::now(); + $lastDay->day = 1; + $now->day = 1; + $lastDay->setTime(0,0,0,0); + $now->setTime(0,0,0,0); + // only for test + $now->month = 11; + $lastDay->month = 11; + $now->year = 2019; + $lastDay->year = 2019; +// var_dump($now); + + $lastDay = $lastDay->addMonth(1); + $sortDate = $this->getStartEndForMonth(11, 2019); + $elopageBuys = $this->ElopageBuys + ->find('all') + ->where(['success_date >=' => $sortDate[0], 'success_date <' => $sortDate[1]]); + $users = []; + foreach($elopageBuys as $elopageEntry) { + array_push($users, $elopageEntry->payer_email); + } + $unique_users = array_unique($users); + + $userTable = TableRegistry::getTableLocator()->get('Users'); + $users = $userTable->find('all') + ->where(['created >=' => $sortDate[0], 'created <' => $sortDate[1]]); + + $this->set(compact('elopageBuys', 'users')); + } /** * View method @@ -37,7 +92,7 @@ class ElopageBuysController extends AppController public function view($id = null) { $elopageBuy = $this->ElopageBuys->get($id, [ - 'contain' => ['ElopageUsers', 'AffiliatePrograms', 'Publishers', 'Orders', 'Products'], + 'contain' => false, ]); $this->set('elopageBuy', $elopageBuy); @@ -60,12 +115,8 @@ class ElopageBuysController extends AppController } $this->Flash->error(__('The elopage buy could not be saved. Please, try again.')); } - $elopageUsers = $this->ElopageBuys->ElopageUsers->find('list', ['limit' => 200]); - $affiliatePrograms = $this->ElopageBuys->AffiliatePrograms->find('list', ['limit' => 200]); - $publishers = $this->ElopageBuys->Publishers->find('list', ['limit' => 200]); - $orders = $this->ElopageBuys->Orders->find('list', ['limit' => 200]); - $products = $this->ElopageBuys->Products->find('list', ['limit' => 200]); - $this->set(compact('elopageBuy', 'elopageUsers', 'affiliatePrograms', 'publishers', 'orders', 'products')); + + $this->set(compact('elopageBuy')); } /** @@ -78,7 +129,7 @@ class ElopageBuysController extends AppController public function edit($id = null) { $elopageBuy = $this->ElopageBuys->get($id, [ - 'contain' => [], + 'contain' => false, ]); if ($this->request->is(['patch', 'post', 'put'])) { $elopageBuy = $this->ElopageBuys->patchEntity($elopageBuy, $this->request->getData()); @@ -89,12 +140,7 @@ class ElopageBuysController extends AppController } $this->Flash->error(__('The elopage buy could not be saved. Please, try again.')); } - $elopageUsers = $this->ElopageBuys->ElopageUsers->find('list', ['limit' => 200]); - $affiliatePrograms = $this->ElopageBuys->AffiliatePrograms->find('list', ['limit' => 200]); - $publishers = $this->ElopageBuys->Publishers->find('list', ['limit' => 200]); - $orders = $this->ElopageBuys->Orders->find('list', ['limit' => 200]); - $products = $this->ElopageBuys->Products->find('list', ['limit' => 200]); - $this->set(compact('elopageBuy', 'elopageUsers', 'affiliatePrograms', 'publishers', 'orders', 'products')); + $this->set(compact('elopageBuy')); } /** diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php new file mode 100644 index 000000000..f7918c54a --- /dev/null +++ b/src/Controller/UsersController.php @@ -0,0 +1,127 @@ +paginate($this->Users); + + $this->set(compact('users')); + } + + public function statistics() + { + $this->viewBuilder()->setLayout('frontend_ripple'); + $users = $this->Users->find('all')->select(['id']); + + //$newUsersThisMonth + $now = new Time(); + $sortDate = $this->getStartEndForMonth($now->month, $now->year); + $newUsersThisMonth = $this->Users->find('all') + ->select(['id']) + ->where(['created >=' => $sortDate[0], 'created <' => $sortDate[1]]); + $lastMonth = new Time(); + $lastMonth = $lastMonth->subMonth(1); + $prevSortDate = $this->getStartEndForMonth($lastMonth->month, $lastMonth->year); + $newUsersLastMonth = $this->Users->find('all') + ->select(['id']) + ->where(['created >=' => $prevSortDate[0], 'created <' => $prevSortDate[1]]); + $this->set(compact('users', 'newUsersThisMonth', 'newUsersLastMonth')); + } + + /** + * View method + * + * @param string|null $id User id. + * @return \Cake\Http\Response|null + * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found. + */ + public function view($id = null) + { + $user = $this->Users->get($id, [ + 'contain' => ['EmailOptIn', 'UserBackups', 'UserRoles'], + ]); + + $this->set('user', $user); + } + + /** + * Add method + * + * @return \Cake\Http\Response|null Redirects on successful add, renders view otherwise. + */ + public function add() + { + $user = $this->Users->newEntity(); + if ($this->request->is('post')) { + $user = $this->Users->patchEntity($user, $this->request->getData()); + if ($this->Users->save($user)) { + $this->Flash->success(__('The user has been saved.')); + + return $this->redirect(['action' => 'index']); + } + $this->Flash->error(__('The user could not be saved. Please, try again.')); + } + $this->set(compact('user')); + } + + /** + * Edit method + * + * @param string|null $id User id. + * @return \Cake\Http\Response|null Redirects on successful edit, renders view otherwise. + * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found. + */ + public function edit($id = null) + { + $user = $this->Users->get($id, [ + 'contain' => [], + ]); + if ($this->request->is(['patch', 'post', 'put'])) { + $user = $this->Users->patchEntity($user, $this->request->getData()); + if ($this->Users->save($user)) { + $this->Flash->success(__('The user has been saved.')); + + return $this->redirect(['action' => 'index']); + } + $this->Flash->error(__('The user could not be saved. Please, try again.')); + } + $this->set(compact('user')); + } + + /** + * Delete method + * + * @param string|null $id User id. + * @return \Cake\Http\Response|null Redirects to index. + * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found. + */ + public function delete($id = null) + { + $this->request->allowMethod(['post', 'delete']); + $user = $this->Users->get($id); + if ($this->Users->delete($user)) { + $this->Flash->success(__('The user has been deleted.')); + } else { + $this->Flash->error(__('The user could not be deleted. Please, try again.')); + } + + return $this->redirect(['action' => 'index']); + } +} diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php new file mode 100644 index 000000000..352371471 --- /dev/null +++ b/src/Model/Entity/User.php @@ -0,0 +1,58 @@ + true, + 'first_name' => true, + 'last_name' => true, + 'password' => true, + 'pubkey' => true, + 'privkey' => true, + 'created' => true, + 'email_checked' => true, + 'language' => true, + 'email_opt_in' => true, + 'user_backups' => true, + 'user_roles' => true, + ]; + + /** + * Fields that are excluded from JSON versions of the entity. + * + * @var array + */ + protected $_hidden = [ + 'password', + ]; +} diff --git a/src/Model/Table/ElopageBuysTable.php b/src/Model/Table/ElopageBuysTable.php index 065bb636f..a5279d920 100644 --- a/src/Model/Table/ElopageBuysTable.php +++ b/src/Model/Table/ElopageBuysTable.php @@ -37,30 +37,11 @@ class ElopageBuysTable extends Table parent::initialize($config); $this->setTable('elopage_buys'); - $this->setDisplayField('id'); + $this->setDisplayField('payer_email'); $this->setPrimaryKey('id'); - $this->belongsTo('ElopageUsers', [ - 'foreignKey' => 'elopage_user_id', - 'joinType' => 'INNER', - ]); - $this->belongsTo('AffiliatePrograms', [ - 'foreignKey' => 'affiliate_program_id', - 'joinType' => 'INNER', - ]); - $this->belongsTo('Publishers', [ - 'foreignKey' => 'publisher_id', - 'joinType' => 'INNER', - ]); - $this->belongsTo('Orders', [ - 'foreignKey' => 'order_id', - 'joinType' => 'INNER', - ]); - $this->belongsTo('Products', [ - 'foreignKey' => 'product_id', - 'joinType' => 'INNER', - ]); } + /** * Default validation rules. @@ -119,11 +100,6 @@ class ElopageBuysTable extends Table */ public function buildRules(RulesChecker $rules) { - $rules->add($rules->existsIn(['elopage_user_id'], 'ElopageUsers')); - $rules->add($rules->existsIn(['affiliate_program_id'], 'AffiliatePrograms')); - $rules->add($rules->existsIn(['publisher_id'], 'Publishers')); - $rules->add($rules->existsIn(['order_id'], 'Orders')); - $rules->add($rules->existsIn(['product_id'], 'Products')); return $rules; } diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php new file mode 100644 index 000000000..0e99ba521 --- /dev/null +++ b/src/Model/Table/UsersTable.php @@ -0,0 +1,130 @@ +setTable('users'); + $this->setDisplayField('id'); + $this->setPrimaryKey('id'); + + $this->addBehavior('Timestamp'); + + $this->hasMany('EmailOptIn', [ + 'foreignKey' => 'user_id', + ]); + $this->hasMany('UserBackups', [ + 'foreignKey' => 'user_id', + ]); + $this->hasMany('UserRoles', [ + 'foreignKey' => 'user_id', + ]); + } + + /** + * Default validation rules. + * + * @param \Cake\Validation\Validator $validator Validator instance. + * @return \Cake\Validation\Validator + */ + public function validationDefault(Validator $validator) + { + $validator + ->integer('id') + ->allowEmptyString('id', null, 'create'); + + $validator + ->email('email') + ->requirePresence('email', 'create') + ->notEmptyString('email') + ->add('email', 'unique', ['rule' => 'validateUnique', 'provider' => 'table']); + + $validator + ->scalar('first_name') + ->maxLength('first_name', 150) + ->requirePresence('first_name', 'create') + ->notEmptyString('first_name'); + + $validator + ->scalar('last_name') + ->maxLength('last_name', 255) + ->allowEmptyString('last_name'); + + $validator + ->requirePresence('password', 'create') + ->notEmptyString('password'); + + $validator + ->allowEmptyString('pubkey'); + + $validator + ->allowEmptyString('privkey'); + + $validator + ->boolean('email_checked') + ->notEmptyString('email_checked'); + + $validator + ->scalar('language') + ->maxLength('language', 4) + ->notEmptyString('language'); + + return $validator; + } + + /** + * Returns a rules checker object that will be used for validating + * application integrity. + * + * @param \Cake\ORM\RulesChecker $rules The rules object to be modified. + * @return \Cake\ORM\RulesChecker + */ + public function buildRules(RulesChecker $rules) + { + $rules->add($rules->isUnique(['email'])); + + return $rules; + } + + /** + * Returns the database connection name to use by default. + * + * @return string + */ + public static function defaultConnectionName() + { + return 'loginServer'; + } +} diff --git a/src/Template/ElopageBuys/statistics.ctp b/src/Template/ElopageBuys/statistics.ctp new file mode 100644 index 000000000..3ac6cf7f6 --- /dev/null +++ b/src/Template/ElopageBuys/statistics.ctp @@ -0,0 +1,35 @@ +toArray()); +/*foreach($elopageBuys as $entry) { + echo $entry->success_date . "
"; +} + * + */ +/*foreach($users as $user) { + //var_dump($user); + echo $user->created; + echo "
"; +}*/ +?> +
+
+
+
+
+
+
+

count()?>

+ + 12.01% +
+
+
+
+
+
\ No newline at end of file diff --git a/src/Template/Users/add.ctp b/src/Template/Users/add.ctp new file mode 100644 index 000000000..3b2b23c02 --- /dev/null +++ b/src/Template/Users/add.ctp @@ -0,0 +1,28 @@ + + +
+ Form->create($user) ?> +
+ + Form->control('email'); + echo $this->Form->control('first_name'); + echo $this->Form->control('last_name'); + echo $this->Form->control('password'); + echo $this->Form->control('email_checked'); + echo $this->Form->control('language'); + ?> +
+ Form->button(__('Submit')) ?> + Form->end() ?> +
diff --git a/src/Template/Users/edit.ctp b/src/Template/Users/edit.ctp new file mode 100644 index 000000000..8595ed620 --- /dev/null +++ b/src/Template/Users/edit.ctp @@ -0,0 +1,34 @@ + + +
+ Form->create($user) ?> +
+ + Form->control('email'); + echo $this->Form->control('first_name'); + echo $this->Form->control('last_name'); + echo $this->Form->control('password'); + echo $this->Form->control('email_checked'); + echo $this->Form->control('language'); + ?> +
+ Form->button(__('Submit')) ?> + Form->end() ?> +
diff --git a/src/Template/Users/index.ctp b/src/Template/Users/index.ctp new file mode 100644 index 000000000..983dd1c1e --- /dev/null +++ b/src/Template/Users/index.ctp @@ -0,0 +1,59 @@ + + +
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Paginator->sort('id') ?>Paginator->sort('email') ?>Paginator->sort('first_name') ?>Paginator->sort('last_name') ?>Paginator->sort('password') ?>Paginator->sort('created') ?>Paginator->sort('email_checked') ?>Paginator->sort('language') ?>
Number->format($user->id) ?>email) ?>first_name) ?>last_name) ?>Number->format($user->password) ?>created) ?>email_checked) ?>language) ?> + Html->link(__('View'), ['action' => 'view', $user->id]) ?> + Html->link(__('Edit'), ['action' => 'edit', $user->id]) ?> + Form->postLink(__('Delete'), ['action' => 'delete', $user->id], ['confirm' => __('Are you sure you want to delete # {0}?', $user->id)]) ?> +
+
+ +

Paginator->counter(['format' => __('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')]) ?>

+
+
diff --git a/src/Template/Users/statistics.ctp b/src/Template/Users/statistics.ctp new file mode 100644 index 000000000..c1f1088d5 --- /dev/null +++ b/src/Template/Users/statistics.ctp @@ -0,0 +1,59 @@ +assign('title', __('Benutzer Statistiken')); + +//mdi mdi-account-multiple-plus +//$newUserPercent = (1 - (b / a)) * 100 +$newUserPercent = 0; +$percentColor = 'text-secondary'; +if($users->count() > 0 && $newUsersLastMonth->count()) { + $newUserPercent = round((1 - ($users->count() / $newUsersLastMonth->count())) * 100.0, 2); + if($newUserPercent > 0 ) { + $percentColor = 'text-primary'; + } else if($newUserPercent < 0) { + $percentColor = 'text-warning'; + } +} +?> +
+
+
+
+
+
+
+

count()?>

+
 
+ +   + +
+
+
+
+
+
+
+

count() ?>

+ + + + + 0) : ?> + + + % + +
+
+
+
+
+
+Html->script(['core', 'vendor.addons']); ?> \ No newline at end of file diff --git a/src/Template/Users/view.ctp b/src/Template/Users/view.ctp new file mode 100644 index 000000000..009108887 --- /dev/null +++ b/src/Template/Users/view.ctp @@ -0,0 +1,52 @@ + + +
+

id) ?>

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
email) ?>
first_name) ?>
last_name) ?>
language) ?>
Number->format($user->id) ?>
Number->format($user->password) ?>
created) ?>
email_checked ? __('Yes') : __('No'); ?>
+