info@ektanjali.com +91 99276-99286

CakePHP 3.x User Management Premium Plugin Version 3.0.x

Plugin Bug Fixes & Migration

Version 3.0.0 Release Date: 1-Apr-2015

Bug Fixes and Improvement Table

From Version To Version Changes Date Links
3.0.0 3.0.0 8-Apr-2015  View
3.0.0 3.0.0 15-Apr-2015  View
3.0.0 3.0.0 25-May-2015  View
3.0.0 3.1.0 22-Sep-2015  View

Changes in Plugin Version- 3.0.0

Date: 8-Apr-2015

1. /plugins/Usermgmt/src/Model/Table/UserGroupsTable.php

Before
public function validationForAdd($validator) {
    $validator
        .....
        ->add('name', [
            'mustBeValid'=>[
                'rule'=>'alphaNumericDashUnderscore',
                'provider'=>'table',
                'message'=>__('Please enter a valid name'),
                'last'=>true
            ],
            .....
        ]);
    return $validator;
}
After Bug Fixes
public function validationForAdd($validator) {
    $validator
        .....
        ->add('name', [
            'mustBeValid'=>[
                'rule'=>'alphaNumericDashUnderscoreSpace',
                'provider'=>'table',
                'message'=>__('Please enter a valid name'),
                'last'=>true
            ],
            .....
        ]);
    return $validator;
}

Date: 15-Apr-2015

/plugins/Usermgmt/src/View/Helper/UserAuthHelper.php

Before
$this->Session->read();
After bug fixes
$this->request->session()->read();

Date: 25-May-2015

1. /plugins/Usermgmt/src/Model/Table/UsersTable.php

Before
public function authsomePersist($userId, $duration) {
    $token = md5(uniqid(mt_rand(), true));
    $loginTokenModel = TableRegistry::get('Usermgmt.LoginTokens');

    $loginToken = [];
    $loginToken['user_id'] = $userId;
    $loginToken['token'] = $token;
    $loginToken['duration'] = $duration;
    $loginToken['created'] = date('Y-m-d H:i:s');
    $loginToken['expires'] = date('Y-m-d H:i:s', strtotime($duration));

    $loginTokenEntity = $loginTokenModel->newEntity($loginToken);

    $loginTokenModel->deleteAll(['user_id'=>$userId]);
    $loginTokenModel->save($loginTokenEntity);
    return "${token}:${userId}";
}
After Bug Fixes
public function authsomePersist($userId, $duration) {
    $token = md5(uniqid(mt_rand(), true));
    $loginTokenModel = TableRegistry::get('Usermgmt.LoginTokens');
    
    $loginToken = $loginTokenModel->newEntity();
    $loginToken['user_id'] = $userId;
    $loginToken['token'] = $token;
    $loginToken['duration'] = $duration;
    $loginToken['created'] = date('Y-m-d H:i:s');
    $loginToken['expires'] = date('Y-m-d H:i:s', strtotime($duration));

    $loginTokenModel->deleteAll(['user_id'=>$userId]);
    $loginTokenModel->save($loginToken);
    return "${token}:${userId}";
}

2. /plugins/Usermgmt/src/Controller/UsersController.php

Before
public function online() {
    $this->loadModel('Usermgmt.UserActivities');
    $cond = [];
    $cond['UserActivities.last_action >'] = date('Y-m-d H:i:s', strtotime('-'.VIEW_ONLINE_USER_TIME.' minutes', time()));
    $cond['UserActivities.logout'] = 0;
    $this->paginate = ['limit'=>10, 'order'=>['UserActivities.last_action'=>'DESC'], 'conditions'=>$cond, 'contain'=>['Users']];
    $this->Search->applySearch($cond);
    $users = $this->paginate($this->UserActivities)->toArray();
    $this->set('users', $users);
    if($this->request->is('ajax')) {
        $this->layout = 'ajax';
        $this->render('/Element/online_users');
    }
}
After Bug Fixes
public function online() {
    $this->loadModel('Usermgmt.UserActivities');
    $cond = [];
    $cond['UserActivities.modified >'] = date('Y-m-d H:i:s', strtotime('-'.VIEW_ONLINE_USER_TIME.' minutes', time()));
    $cond['UserActivities.logout'] = 0;
    $this->paginate = ['limit'=>10, 'order'=>['UserActivities.last_action'=>'DESC'], 'conditions'=>$cond, 'contain'=>['Users']];
    $this->Search->applySearch($cond);
    $users = $this->paginate($this->UserActivities)->toArray();
    $this->set('users', $users);
    if($this->request->is('ajax')) {
        $this->layout = 'ajax';
        $this->render('/Element/online_users');
    }
}

3. /plugins/Usermgmt/src/Template/Users/view_user.ctp

Before
<tr>
    <td style="text-align:right"><strong><?php echo __('Group(s)');?>:</strong></td>
    <td><?php echo h($user['user_group_name']);?></td>
</tr>
After Bug Fixes
<tr>
    <td style="text-align:right"><strong><?php echo __('Group(s)');?>:</strong></td>
    <td><?php echo h($user['group_name']);?></td>
</tr>

 Plugin Version- 3.0.0 to 3.1.0

Date: 22-Sep-2015

Please keep backup of your code before replacing the files. Either you can replace existing files or do changes in existing code as per new changes.

You can download the old version 3.0.0 and make a difference with your application code using Kdiff3 software http://kdiff3.sourceforge.net/ and record your changes done in plugin files.

we have done lot of changes in 3.1.0 version. You need to migrate user management plugin version from 3.0.0 to 3.1.0 in following steps...

1. Run Sql changes in your existing database from plugins\Usermgmt\config\Schema\sql-changes-3.1.0.txt

2. Replace plugins\Usermgmt\config\bootstrap.php

3. Replace plugins\Usermgmt\config\routes.php

4. Replace plugins\Usermgmt\src\Auth\PermissionAuthenticate.php

5. Replace plugins\Usermgmt\src\Auth\PermissionAuthorize.php

6. Replace plugins\Usermgmt\src\Controller\Component\ControllerListComponent.php

7. Replace plugins\Usermgmt\src\Controller\Component\SearchComponent.php

8. Open plugins\Usermgmt\src\Controller\Component\UserAuthComponent.php

remove
use Usermgmt\Auth\PermissionAuthenticate;
from line no 35 approx

add
use Cake\Auth\BasicAuthenticate;
use Cake\Utility\Security;
on line no 36 approx

Go to line no 72 approx
replace
$this->controller->Auth->config('loginAction', [
    'controller'=>'Users',
    'action'=>'login',
    'plugin'=>'Usermgmt'
]);

with

$this->controller->Auth->config('loginAction', [
    'controller'=>'Users',
    'action'=>'login',
    'plugin'=>'Usermgmt',
    'prefix'=>false
]);

Go to line no 167 approx
add
$this->session->delete('Auth.badLoginCount');
after $this->controller->Auth->setUser($user);

Go to checkPassword function and replace code with

public function checkPassword($password, $dbpassword, $options=[]) {
        if(!isset($options['passwordHasher'])) {
            $options['passwordHasher'] = 'Default';
        }
        $passwordHasher = [];
        if(!empty($options)) {
            if(strtolower($options['passwordHasher']) == 'ump2' && !empty($options['salt'])) {
                //CakePHP 2.x old password compatibility
                if(strlen($options['salt']) == 32) {
                    //CakePHP 2.x user management plugin version upto 2.2.1 version
                    return $dbpassword === md5(md5($password).md5($options['salt']));
                } else {
                    //CakePHP 2.x user management plugin version greater than 2.2.1 version
                    $options['salt'] = base64_decode($options['salt']).Security::salt();
                    return $dbpassword === Security::hash($password, 'sha256', $options['salt']);
                }
            } else {
                //CakePHP 2.x old password compatibility (which are not using our CakePHP 2.x user management plugin)
                $passwordHasher['passwordHasher']['className'] = $options['passwordHasher'];
            }
            if(isset($options['hashType'])) {
                $passwordHasher['passwordHasher']['hashType'] = $options['hashType'];
            }
        }
        $hasher = (new BasicAuthenticate($this->registry, $passwordHasher))->passwordHasher();
        return $hasher->check($password, $dbpassword);
    }

Go to getLastLoginTime function
replace
return date($format, strtotime($last_login));
with
return $last_login->format($format);

9. Replace plugins\Usermgmt\src\Controller\Component\UserConnectComponent.php

10. Replace plugins\Usermgmt\src\Controller\AutocompleteController.php

11. Add plugins\Usermgmt\src\Controller\CronJobsController.php

12. Add plugins\Usermgmt\src\Controller\ScheduledEmailsController.php

13. Add plugins\Usermgmt\src\Controller\SettingOptionsController.php

14. Open plugins\Usermgmt\src\Controller\StaticPagesController.php

Go to beforeFilter function

Add

$this->loadModel('Usermgmt.StaticPages');

after parent::beforeFilter($event);

Go to index function
Replace $this->layout = 'ajax'; with $this->viewBuilder()->layout('ajax');

15. Open plugins\Usermgmt\src\Controller\UserContactsController.php

Replace public $searchFields variable with

public $searchFields = [
        'index'=>[
            'Usermgmt.UserContacts'=>[
                'UserContacts'=>[
                    'type'=>'text',
                    'label'=>'Search',
                    'tagline'=>'Search by name, phone, email, requirement, message',
                    'condition'=>'multiple',
                    'searchFields'=>['UserContacts.name', 'UserContacts.phone', 'UserContacts.email', 'UserContacts.requirement', 'UserContacts.reply_message'],
                    'inputOptions'=>['style'=>'width:300px;']
                ]
            ]
        ]
    ];

Go to beforeFilter function

Add

$this->loadModel('Usermgmt.UserContacts');

after parent::beforeFilter($event);

Go to index function
Replace $this->layout = 'ajax'; with $this->viewBuilder()->layout('ajax');

Go to contactUs function
Replace 'recaptcha_response_field' with 'g-recaptcha-response'

Go to line no 250 approx
replace
$this->Flash->success('Contact Reply has been sent successfully');
with
$this->Flash->success(__('Contact Reply has been sent successfully'));

replace
$this->Flash->error('We could not send Reply Email');
with
$this->Flash->error(__('We could not send Reply Email'));

Go to line no 265 approx
replace
date('d M Y', strtotime($userContact['created']))
with
$userContact['created']->format('d M Y')

replace
date('h:i A', strtotime($userContact['created']))
with
$userContact['created']->format('h:i A')

16. Open plugins\Usermgmt\src\Controller\UserEmailsController.php

Add use Cake\I18n\Time;

Go to beforeFilter function

Add

$this->loadModel('Usermgmt.UserEmails');

after parent::beforeFilter($event);

Go to index function
Replace $this->layout = 'ajax'; with $this->viewBuilder()->layout('ajax');

Go to line 143 approx
Add

if(!empty($this->request->data['UserEmails']['schedule_date'])) {
            $this->request->data['UserEmails']['schedule_date'] = new Time($this->request->data['UserEmails']['schedule_date']);
        }

before $userEmailEntity = $this->UserEmails->newEntity($this->request->data, ['validate'=>'forSend']); line

Go to line no 232 approx
replace
$sent = $this->sendAndSaveUserEmail($data, $users);
if($sent) {
    $this->request->session()->delete('send_email_data');
    $this->redirect(['action'=>'index']);
} else {
    $this->redirect(['action'=>'send']);
}

with
if(!empty($data['schedule_date'])) {
    $scheduled = $this->saveScheduledEmails($data, $users);
    if($scheduled) {
        $this->request->session()->delete('send_email_data');
        $this->redirect(['controller'=>'ScheduledEmails', 'action'=>'index']);
    } else {
        $this->redirect(['action'=>'send']);
    }
} else {
    $sent = $this->sendAndSaveUserEmail($data, $users);
    if($sent) {
        $this->request->session()->delete('send_email_data');
        $this->redirect(['action'=>'index']);
    } else {
        $this->redirect(['action'=>'send']);
    }
}

Go to line no 261 approx

Add

if(!empty($userEmailEntity['schedule_date'])) {
    $userEmailEntity['schedule_date'] = $userEmailEntity['schedule_date']->format('Y-m-d H:i:s');
}

after $userEmailEntity = $this->request->session()->read('send_email_data');

Go to line no 431 approx
replace
$this->Flash->success('All Emails have been sent successfully');
with
$this->Flash->success(__('All Emails have been sent successfully'));

replace
$this->Flash->success('Out of '.$totalEmails.' Emails only '.$totalSentEmails.' Emails have been sent successfully');
with
$this->Flash->success(__('Out of {0) Emails only {1} Emails have been sent successfully', [$totalEmails, $totalSentEmails]));

replace
$this->Flash->error('There is problem in sending emails, please try again');
with
$this->Flash->error(__('There is problem in sending emails, please try again'));

replace
$this->Flash->error('These is some problem in saving data, please try again');
with
$this->Flash->error(__('These is some problem in saving data, please try again'));

Go to line no 445 approx
Add following function

private function saveScheduledEmails($data, $users) {
    $data['scheduled_by'] = $this->UserAuth->getUserId();
    if(!empty($data['user_group_id'])) {
        sort($data['user_group_id']);
        $data['user_group_id'] = implode(',', $data['user_group_id']);
    }
    $data['message'] = $data['modified_message'];
    $this->loadModel('Usermgmt.ScheduledEmails');
    if($this->ScheduledEmails->save($data, ['validate'=>false])) {
        $scheduledEmails = [];
        $this->loadModel('Usermgmt.ScheduledEmailRecipients');
        foreach($users as $user) {
            if(!isset($scheduledEmails[$user['email']])) {
                $scheduledEmailRecipient = $this->ScheduledEmailRecipients->newEntity();
                $scheduledEmailRecipient['scheduled_email_id'] = $data['id'];
                $scheduledEmailRecipient['user_id'] = $user['id'];
                $scheduledEmailRecipient['email_address'] = $user['email'];
                $this->ScheduledEmailRecipients->save($scheduledEmailRecipient, ['validate'=>false]);
                $scheduledEmails[$user['email']] = $user['email'];
            }
        }
        $this->Flash->success(__('Email has been scheduled successfully'));
        return true;
    } else {
        $this->Flash->error(__('These is some problem in saving data, please try again'));
        return false;
    }
}

17. Open plugins\Usermgmt\src\Controller\UserEmailSignaturesController.php

Go to beforeFilter function

Add

$this->loadModel('Usermgmt.UserEmailSignatures');

after parent::beforeFilter($event);

Go to index function
Replace $this->layout = 'ajax'; with $this->viewBuilder()->layout('ajax');

18. Open plugins\Usermgmt\src\Controller\UserEmailTemplatesController.php

Go to beforeFilter function

Add

$this->loadModel('Usermgmt.UserEmailTemplates');

after parent::beforeFilter($event);

Go to index function
Replace $this->layout = 'ajax'; with $this->viewBuilder()->layout('ajax');

19. Replace plugins\Usermgmt\src\Controller\UserGroupPermissionsController.php

20. Open plugins\Usermgmt\src\Controller\UserGroupsController.php

Go to beforeFilter function

Add

$this->loadModel('Usermgmt.UserGroups');

after parent::beforeFilter($event);

Go to index function
Replace $this->layout = 'ajax'; with $this->viewBuilder()->layout('ajax');

21. Open plugins\Usermgmt\src\Controller\UsermgmtAppController.php

replace public $components = ['Security']; with public $components = ['Security', 'Csrf'];

22. Open plugins\Usermgmt\src\Controller\UsersController.php

add use Cake\I18n\Time;

Go to beforeFilter function

Add

$this->loadModel('Usermgmt.Users');

after parent::beforeFilter($event);

Go to index function
remove 'searchFilter'=>true from $this->paginate variable
Replace $this->layout = 'ajax'; with $this->viewBuilder()->layout('ajax');

Go to online function
Replace $this->layout = 'ajax'; with $this->viewBuilder()->layout('ajax');

Go to addUser function
remove ucwords function from first_name and last_name, this does not work with all languages

Go to editUser Function
Add

if(!empty($this->request->data['Users']['bday'])) {
    $userEntity['bday'] = new Time($this->request->data['Users']['bday']);
}

before
if($this->Users->save($userEntity, ['validate'=>false])) {

replace
$userEntity['bday'] = date('Y-m-d', strtotime($userEntity['bday']));
with
$userEntity['bday'] = $userEntity['bday']->format('Y-m-d');

Go to addMultipleUsers function
Add

if(!empty($row['bday'])) {
    $this->request->data['Users'][$key]['bday'] = new Time($row['bday']);
}

before
if(isset($row['usercheck']) && $row['usercheck']) {

Go to login function
Replace 'recaptcha_response_field' with 'g-recaptcha-response'

Go to add_social_user function
remove ucwords function from first_name and last_name, this does not work with all languages

replace
$this->request->session()->write('Auth.SocialChangePassword', true);
with
if(CHANGE_PASSWORD_ON_SOCIAL_REGISTRATION) {
    $this->request->session()->write('Auth.SocialChangePassword', true);
}

Go to login_facebook function
replace
$this->layout = NULL;
with
$this->viewBuilder()->layout('');

Go to login_twitter function
replace
$this->layout = NULL;
with
$this->viewBuilder()->layout('');

Go to login_linkedin function
replace
$this->layout = NULL;
with
$this->viewBuilder()->layout('');

Go to login_foursquare function
replace
$this->layout = NULL;
with
$this->viewBuilder()->layout('');

Go to login_gmail function
replace
$this->layout = NULL;
with
$this->viewBuilder()->layout('');

Go to login_yahoo function
replace
$this->layout = NULL;
with
$this->viewBuilder()->layout('');

Go to register function
Replace 'recaptcha_response_field' with 'g-recaptcha-response'
remove ucwords function from first_name and last_name, this does not work with all languages

Go to editProfile function
Add

if(!ALLOW_CHANGE_USERNAME && !empty($userEntity['username'])) {
    unset($this->request->data['Users']['username']);
}

after
$this->loadModel('Usermgmt.UserDetails');

remove
if(!ALLOW_CHANGE_USERNAME) {
    unset($userEntity['username']);
}

Add
if(!empty($this->request->data['Users']['bday'])) {
    $userEntity['bday'] = new Time($this->request->data['Users']['bday']);
}

before
$this->Users->save($userEntity, ['validate'=>false]);

replace
$userEntity['bday'] = date('Y-m-d', strtotime($userEntity['bday']));
with
$userEntity['bday'] = $userEntity['bday']->format('Y-m-d');

Go to forgotPassword function
Replace 'recaptcha_response_field' with 'g-recaptcha-response'

Go to emailVerification function
Replace 'recaptcha_response_field' with 'g-recaptcha-response'

23. Replace plugins\Usermgmt\src\Controller\UserSettingsController.php

24. Add plugins\Usermgmt\src\Model\Entity\SettingOption.php

25. Add plugins\Usermgmt\src\Model\Entity\UserSettingOption.php

26. Add plugins\Usermgmt\src\Model\Table\ScheduledEmailRecipientsTable.php

27. Add plugins\Usermgmt\src\Model\Table\ScheduledEmailsTable.php

28. Add plugins\Usermgmt\src\Model\Table\SettingOptionsTable.php

29. Open plugins\Usermgmt\src\Model\Table\UserContactsTable.php

Go to validationForContact function
replace 'Please enter captcha words' with 'Please select I\'m not a robot'
replace 'Please enter correct words' with 'Prove you are not a robot'
replace 'message'=>'Please enter valid email' with 'message'=>__('Please enter valid email')

30. replace plugins\Usermgmt\src\Model\Table\UserEmailSignaturesTable.php

31. replace plugins\Usermgmt\src\Model\Table\UserEmailsTable.php

32. replace plugins\Usermgmt\src\Model\Table\UserEmailTemplatesTable.php

33. replace plugins\Usermgmt\src\Model\Table\UserGroupsTable.php

34. Open plugins\Usermgmt\src\Model\Table\UsermgmtAppTable.php

go to recaptchaValidate function and replace function code with

public function recaptchaValidate($value, $context) {
    require_once(USERMGMT_PATH.DS.'vendor'.DS.'recaptcha'.DS.'src'.DS.'autoload.php');
    $recaptcha = new \ReCaptcha\ReCaptcha(PRIVATE_KEY_FROM_RECAPTCHA);
    $resp = $recaptcha->verify($value);
    if($resp->isSuccess()) {
        return true;
    } else {
        $errors = $resp->getErrorCodes();
        return true;
    }
}

35. Add plugins\Usermgmt\src\Model\Table\UserSettingOptionsTable.php

36. Replace plugins\Usermgmt\src\Model\Table\UserSettingsTable.php

37. Open plugins\Usermgmt\src\Model\Table\UserSocialsTable.php

replace
$this->hasOne('Usermgmt.Users');
with
$this->belongsTo('Usermgmt.Users');

38. Open plugins\Usermgmt\src\Model\Table\UsersTable.php

Go to validationForLogin function
replace 'Please enter captcha words' with 'Please select I\'m not a robot'
replace 'Please enter correct words' with 'Prove you are not a robot'

Go to validationForRegister function
replace 'Please enter captcha words' with 'Please select I\'m not a robot'
replace 'Please enter correct words' with 'Prove you are not a robot'
replace 'message'=>'Please enter valid email' with 'message'=>__('Please enter valid email')

Go to validationForAddUser function
replace 'message'=>'Please enter valid email' with 'message'=>__('Please enter valid email')

Go to validationForEditUser function
replace 'message'=>'Please enter valid email' with 'message'=>__('Please enter valid email')

Go to validationForEditProfile function
replace 'message'=>'Please enter valid email' with 'message'=>__('Please enter valid email')

Go to validationForForgotPassword function
replace 'Please enter captcha words' with 'Please select I\'m not a robot'
replace 'Please enter correct words' with 'Prove you are not a robot'

Go to validationForEmailVerification function
replace 'Please enter captcha words' with 'Please select I\'m not a robot'
replace 'Please enter correct words' with 'Prove you are not a robot'

Go to validationForMultipleUsers function
replace 'message'=>'Please enter valid email' with 'message'=>__('Please enter valid email')

Go to isBanned function and replace function code with

public function isBanned($value, $context=null) {
    if(strtolower($value) != 'admin') {
        $bannedUsernames = array_map('trim', explode(',', strtolower(BANNED_USERNAMES)));
        if(!empty($bannedUsernames)) {
            if(isset($context['data']['id'])) {
                $oldUsername = $this->getUsernameById($context['data']['id']);
            }
            if(!isset($oldUsername) || $oldUsername != $value) {
                if(in_array(strtolower($value), $bannedUsernames)) {
                    return false;
                }
            }
        }
        $usernameTmp = strtolower(str_replace(' ', '', ucwords(str_replace('_', ' ', $value))));
        $list = $this->getAllControllerAndPluginName();
        if(isset($list['Controller'][$usernameTmp])) {
            return false;
        }
        if(isset($list['Plugin'][$usernameTmp])) {
            return false;
        }
        $customRoutes = Router::routes();
        $usernameTmp = '/'.strtolower($value);
        foreach($customRoutes as $customRoute) {
            if(strpos(strtolower($customRoute->template), $usernameTmp) !== false) {
                return false;
            }
        }
    }
    return true;
}

39. Open plugins\Usermgmt\src\Template\Element\all_contacts.ctp

replace date('d-M-Y', strtotime($row['created'])) with $row['created']->format('d-M-Y')

Add btn-sm class in Action button dropdown like following

echo "<button class='btn btn-primary btn-sm dropdown-toggle' data-toggle='dropdown'>".__('Action')." <span class='caret'></span></button>";

40. Open plugins\Usermgmt\src\Template\Element\all_email_signatures.ctp

replace date('d-M-Y', strtotime($row['created'])) with $row['created']->format('d-M-Y')

Add btn-sm class in Action button dropdown like following

echo "<button class='btn btn-primary btn-sm dropdown-toggle' data-toggle='dropdown'>".__('Action')." <span class='caret'></span></button>";

41. Open plugins\Usermgmt\src\Template\Element\all_email_templates.ctp

replace date('d-M-Y', strtotime($row['created'])) with $row['created']->format('d-M-Y')

Add btn-sm class in Action button dropdown like following

echo "<button class='btn btn-primary btn-sm dropdown-toggle' data-toggle='dropdown'>".__('Action')." <span class='caret'></span></button>";

42. Open plugins\Usermgmt\src\Template\Element\all_emails.ctp

replace date('d-M-Y', strtotime($row['created'])) with $row['created']->format('d-M-Y')

Add btn-sm class in Action button dropdown like following

echo "<button class='btn btn-primary btn-sm dropdown-toggle' data-toggle='dropdown'>".__('Action')." <span class='caret'></span></button>";

43. Add plugins\Usermgmt\src\Template\Element\all_scheduled_emails.ctp

44. Add plugins\Usermgmt\src\Template\Element\all_setting_options.ctp

45. replace plugins\Usermgmt\src\Template\Element\all_settings.ctp

46. Open plugins\Usermgmt\src\Template\Element\all_static_pages.ctp

replace date('d-M-Y', strtotime($row['created'])) with $row['created']->format('d-M-Y')

Add btn-sm class in Action button dropdown like following

echo "<button class='btn btn-primary btn-sm dropdown-toggle' data-toggle='dropdown'>".__('Action')." <span class='caret'></span></button>";

47. Open plugins\Usermgmt\src\Template\Element\all_user_groups.ctp

replace date('d-M-Y', strtotime($row['created'])) with $row['created']->format('d-M-Y')

Add btn-sm class in Action button dropdown like following

echo "<button class='btn btn-primary btn-sm dropdown-toggle' data-toggle='dropdown'>".__('Action')." <span class='caret'></span></button>";

48. Open plugins\Usermgmt\src\Template\Element\all_users.ctp

replace date('d-M-Y', strtotime($row['created'])) with $row['created']->format('d-M-Y')

Add btn-sm class in Action button dropdown like following

echo "<button class='btn btn-primary btn-sm dropdown-toggle' data-toggle='dropdown'>".__('Action')." <span class='caret'></span></button>";

49. Open plugins\Usermgmt\src\Template\Element\contact_us.ctp

remove

$this->Form->unlockField('recaptcha_challenge_field');
$this->Form->unlockField('recaptcha_response_field');

50. Open plugins\Usermgmt\src\Template\Element\dashboard.ctp

Add following code after View Sent Emails link

if($this->UserAuth->HP('ScheduledEmails', 'index', 'Usermgmt')) {
    echo "<li class='".(($actionUrl=='ScheduledEmails/index') ? $activeClass : $inactiveClass)."'>".$this->Html->link(__('Scheduled Mails'), ['controller'=>'ScheduledEmails', 'action'=>'index', 'plugin'=>'Usermgmt'])."</li>";
}

51. replace plugins\Usermgmt\src\Template\Element\message.ctp

52. Add plugins\Usermgmt\src\Template\Element\message_notification.ctp

53. Open plugins\Usermgmt\src\Template\Element\online_users.ctp

Add btn-sm class in Action button dropdown like following

echo "<button class='btn btn-primary btn-sm dropdown-toggle' data-toggle='dropdown'>".__('Action')." <span class='caret'></span></button>";

54. Open plugins\Usermgmt\src\Template\Element\paginator.ctp

Add

if(window.history.pushState) {
    window.history.pushState({},"", url);
}

after $($updateDivId).html(data);

55. Open plugins\Usermgmt\src\Template\Element\search_form.ctp

Add

$('#searchClearId').val(0);
if(window.history.pushState) {
    window.history.pushState({},"", "<?php echo $targetUrl;?>");
}

after $("#<?php echo $options['updateDivId'];?>").html(data);

replace __($search_options['label']) with $search_options['label']

replace usermgmt/autocomplete/fetch with usermgmt/Autocomplete/fetch

56. Add plugins\Usermgmt\src\Template\ScheduledEmails folder and it's files

57. Add plugins\Usermgmt\src\Template\SettingOptions folder and it's files

58. Open plugins\Usermgmt\src\Template\StaticPages\add.ctp and plugins\Usermgmt\src\Template\StaticPages\edit.ctp

replace

<?php echo $this->Tinymce->textarea('StaticPages.page_content', ['type'=>'textarea', 'label'=>false, 'div'=>false, 'style'=>'height:800px', 'class'=>'form-control'], ['language'=>'en'], 'umcode'); ?>

with

<?php    if(strtoupper(DEFAULT_HTML_EDITOR) == 'TINYMCE') {
    echo $this->Tinymce->textarea('StaticPages.page_content', ['type'=>'textarea', 'label'=>false, 'div'=>false, 'style'=>'height:800px', 'class'=>'form-control'], ['language'=>'en'], 'umcode');
} else if(strtoupper(DEFAULT_HTML_EDITOR) == 'CKEDITOR') {
    echo $this->Ckeditor->textarea('StaticPages.page_content', ['type'=>'textarea', 'label'=>false, 'div'=>false, 'style'=>'height:800px', 'class'=>'form-control'], ['language'=>'en', 'uiColor'=>'#14B8C4'], 'full');
}?>

59. Open plugins\Usermgmt\src\Template\StaticPages\view.ctp

replace date('d-M-Y h:i A', strtotime($staticPage['created'])) with $staticPage['created']->format('d-M-Y h:i A')

replace date('d-M-Y h:i A', strtotime($staticPage['modified'])) with $staticPage['modified']->format('d-M-Y h:i A')

60. Open plugins\Usermgmt\src\Template\UserContacts\send_reply.ctp

replace

<?php echo $this->Ckeditor->textarea('UserEmails.message', ['type'=>'textarea', 'label'=>false, 'div'=>false, 'style'=>'height:400px', 'class'=>'form-control'], ['language'=>'en', 'uiColor'=>'#14B8C4'], 'full');?>

with

<?php    if(strtoupper(DEFAULT_HTML_EDITOR) == 'TINYMCE') {
    echo $this->Tinymce->textarea('UserEmails.message', ['type'=>'textarea', 'label'=>false, 'div'=>false, 'style'=>'height:400px', 'class'=>'form-control'], ['language'=>'en'], 'umcode');
} else if(strtoupper(DEFAULT_HTML_EDITOR) == 'CKEDITOR') {
    echo $this->Ckeditor->textarea('UserEmails.message', ['type'=>'textarea', 'label'=>false, 'div'=>false, 'style'=>'height:400px', 'class'=>'form-control'], ['language'=>'en', 'uiColor'=>'#14B8C4'], 'full');
}?>

61. Open plugins\Usermgmt\src\Template\UserEmails\index.ctp

Add

<span class="panel-title-right">
    <?php echo $this->Html->link(__('Scheduled Emails', true), ['controller'=>'ScheduledEmails', 'action'=>'index'], ['class'=>'btn btn-default']); ?>
</span>

after Send Email link

62. replace plugins\Usermgmt\src\Template\UserEmails\send.ctp

63. replace plugins\Usermgmt\src\Template\UserEmails\send_confirm.ctp

64. Open plugins\Usermgmt\src\Template\UserEmails\send_to_user.ctp

replace

<?php echo $this->Ckeditor->textarea('UserEmails.message', ['type'=>'textarea', 'label'=>false, 'div'=>false, 'style'=>'height:400px', 'class'=>'form-control'], ['language'=>'en', 'uiColor'=>'#14B8C4'], 'full'); ?>

with

<?php    if(strtoupper(DEFAULT_HTML_EDITOR) == 'TINYMCE') {
    echo $this->Tinymce->textarea('UserEmails.message', ['type'=>'textarea', 'label'=>false, 'div'=>false, 'style'=>'height:400px', 'class'=>'form-control'], ['language'=>'en'], 'umcode');
} else if(strtoupper(DEFAULT_HTML_EDITOR) == 'CKEDITOR') {
    echo $this->Ckeditor->textarea('UserEmails.message', ['type'=>'textarea', 'label'=>false, 'div'=>false, 'style'=>'height:400px', 'class'=>'form-control'], ['language'=>'en', 'uiColor'=>'#14B8C4'], 'full');
}?> 

65. replace plugins\Usermgmt\src\Template\UserEmails\send_to_user_confirm.ctp

66. Open plugins\Usermgmt\src\Template\UserEmailSignatures\add.ctp and plugins\Usermgmt\src\Template\UserEmailSignatures\edit.ctp

replace

<?php echo $this->Ckeditor->textarea('UserEmailSignatures.signature', ['type'=>'textarea', 'label'=>false, 'div'=>false, 'class'=>'form-control'], ['language'=>'en', 'uiColor'=>'#14B8C4'], 'standard'); ?>

with

<?php    if(strtoupper(DEFAULT_HTML_EDITOR) == 'TINYMCE') {
    echo $this->Tinymce->textarea('UserEmailSignatures.signature', ['type'=>'textarea', 'label'=>false, 'div'=>false, 'class'=>'form-control'], ['language'=>'en'], 'umcode');
} else if(strtoupper(DEFAULT_HTML_EDITOR) == 'CKEDITOR') {
    echo $this->Ckeditor->textarea('UserEmailSignatures.signature', ['type'=>'textarea', 'label'=>false, 'div'=>false, 'class'=>'form-control'], ['language'=>'en', 'uiColor'=>'#14B8C4'], 'full');
}?> 

67. Open plugins\Usermgmt\src\Template\UserEmailTemplates\add.ctp and plugins\Usermgmt\src\Template\UserEmailTemplates\edit.ctp

replace

<?php echo $this->Ckeditor->textarea('UserEmailTemplates.header', ['type'=>'textarea', 'label'=>false, 'div'=>false, 'class'=>'form-control'], ['language'=>'en', 'uiColor'=>'#14B8C4'], 'standard'); ?>

with

<?php    if(strtoupper(DEFAULT_HTML_EDITOR) == 'TINYMCE') {
    echo $this->Tinymce->textarea('UserEmailTemplates.header', ['type'=>'textarea', 'label'=>false, 'div'=>false, 'class'=>'form-control'], ['language'=>'en'], 'umcode');
} else if(strtoupper(DEFAULT_HTML_EDITOR) == 'CKEDITOR') {
    echo $this->Ckeditor->textarea('UserEmailTemplates.header', ['type'=>'textarea', 'label'=>false, 'div'=>false, 'class'=>'form-control'], ['language'=>'en', 'uiColor'=>'#14B8C4'], 'full');
}?>

replace

<?php echo $this->Ckeditor->textarea('UserEmailTemplates.footer', ['type'=>'textarea', 'label'=>false, 'div'=>false, 'class'=>'form-control'], ['language'=>'en', 'uiColor'=>'#14B8C4'], 'standard'); ?>

with

<?php    if(strtoupper(DEFAULT_HTML_EDITOR) == 'TINYMCE') {
    echo $this->Tinymce->textarea('UserEmailTemplates.footer', ['type'=>'textarea', 'label'=>false, 'div'=>false, 'class'=>'form-control'], ['language'=>'en'], 'umcode');
} else if(strtoupper(DEFAULT_HTML_EDITOR) == 'CKEDITOR') {
    echo $this->Ckeditor->textarea('UserEmailTemplates.footer', ['type'=>'textarea', 'label'=>false, 'div'=>false, 'class'=>'form-control'], ['language'=>'en', 'uiColor'=>'#14B8C4'], 'full');
}?>

68. Replace plugins\Usermgmt\src\Template\UserGroupPermissions\permission_group_matrix.ctp

69. Replace plugins\Usermgmt\src\Template\UserGroupPermissions\permission_sub_group_matrix.ctp

70. Add plugins\Usermgmt\src\Template\UserGroupPermissions\print_permission_changes.ctp

71. Open plugins\Usermgmt\src\Template\Users\dashboard.ctp

Add

if($this->UserAuth->HP('ScheduledEmails', 'index', 'Usermgmt')) {
    echo $this->Html->link(__('Scheduled Mails'), ['controller'=>'ScheduledEmails', 'action'=>'index', 'plugin'=>'Usermgmt'], ['class'=>'btn btn-default um-btn']);
}

after View Sent Mails link

72. Open plugins\Usermgmt\src\Template\Users\edit_profile.ctp

replace

<?php $changeUserName = (ALLOW_CHANGE_USERNAME) ? false : true; ?>

with

<?php $changeUserName = (ALLOW_CHANGE_USERNAME || empty($userEntity['username'])) ? false : true; ?>

73. Open plugins\Usermgmt\src\Template\Users\email_verification.ctp

remove

$this->Form->unlockField('recaptcha_challenge_field');
$this->Form->unlockField('recaptcha_response_field');

74. Open plugins\Usermgmt\src\Template\Users\forgot_password.ctp

remove

$this->Form->unlockField('recaptcha_challenge_field');
$this->Form->unlockField('recaptcha_response_field');

75. Open plugins\Usermgmt\src\Template\Users\login.ctp

remove

$this->Form->unlockField('recaptcha_challenge_field');
$this->Form->unlockField('recaptcha_response_field');

76. Open plugins\Usermgmt\src\Template\Users\myprofile.ctp

replace date('d-M-Y',strtotime($user['bday'])) with $user['bday']->format('d-M-Y')

replace date('d-M-Y', strtotime($user['created'])) with $user['created']->format('d-M-Y')

77. Open plugins\Usermgmt\src\Template\Users\register.ctp

remove

$this->Form->unlockField('recaptcha_challenge_field');
$this->Form->unlockField('recaptcha_response_field');

remove <?php if(count($userGroups) > 2) { ?> condition from Group field

78. Open plugins\Usermgmt\src\Template\Users\view_user.ctp

replace date('d-M-Y',strtotime($user['bday'])) with $user['bday']->format('d-M-Y')

replace date('d-M-Y', strtotime($user['created'])) with $user['created']->format('d-M-Y')

replace date('d-M-Y', strtotime($user['last_login'])) with $user['last_login']->format('d-M-Y')

79. Add plugins\Usermgmt\src\Template\UserSettings\add_setting.ctp

80. replace plugins\Usermgmt\src\Template\UserSettings\edit_setting.ctp

81. replace plugins\Usermgmt\src\Template\UserSettings\index.ctp

82. replace plugins\Usermgmt\src\View\Helper\CkeditorHelper.php

83. replace plugins\Usermgmt\src\View\Helper\TinymceHelper.php

84. Open plugins\Usermgmt\src\View\Helper\UserAuthHelper.php

replace public $helpers = ['Session']; with public $helpers = ['Session', 'Html', 'Form'];

Add
public $recaptcha_script = false;
after
public $view;

replace return date($format, strtotime($last_login)); with return $last_login->format($format);

replace showCaptcha function code with following

public function showCaptcha($error=null) {
    $this->Form->unlockField('g-recaptcha-response');
    if(!$this->recaptcha_script) {
        $this->recaptcha_script = true;
        $this->Html->script('https://www.google.com/recaptcha/api.js', array('block'=>true));
    }
    $code = '<div class="g-recaptcha" data-sitekey="'.PUBLIC_KEY_FROM_RECAPTCHA.'"></div>';
    $errorMsg = '';
    if(!empty($error)) {
        $errorMsg = "<div class='error-message'>".$error."</div>";
    }
    return $code.$errorMsg;
}

replace HP function code with following

public function HP($controller=null, $action='index', $plugin=null, $prefix=null) {
    if($this->needToCheckPermission()) {
        if(empty($this->permissions)) {
            $this->permissions = $this->view->requestAction('/usermgmt/UserGroupPermissions/getPermissions');
        }
        if($controller) {
            $access = Inflector::camelize($controller).'/'.$action;
            if($plugin) {
                $access = $plugin.'/'.$access;
            }
            if($prefix) {
                $access = strtolower(Inflector::camelize($prefix)).'/'.$access;
            }
            $access = strtolower($access);
            if(is_array($this->permissions) && in_array($access, $this->permissions)) {
                return true;
            }
            return false;
        } else {
            echo "Missing Argument 1";
            return false;
        }
    } else {
        return true;
    }
}

85. Replace panel classes in following files

replace "um-panel" with "panel panel-primary"
replace "um-panel-header" with "panel-heading"
replace "um-panel-title" with "panel-title"
replace "um-panel-title-right" with "panel-title-right"
replace btn-primary with "btn-default" in panel-title and panel-title-right links
replace "um-panel-content" with "panel-body"

files are

plugins\Usermgmt\src\Template\StaticPages\add.ctp
plugins\Usermgmt\src\Template\StaticPages\edit.ctp
plugins\Usermgmt\src\Template\StaticPages\index.ctp
plugins\Usermgmt\src\Template\StaticPages\preview.ctp
plugins\Usermgmt\src\Template\StaticPages\view.ctp
plugins\Usermgmt\src\Template\UserContacts\contact_us.ctp
plugins\Usermgmt\src\Template\UserContacts\index.ctp
plugins\Usermgmt\src\Template\UserContacts\send_reply.ctp
plugins\Usermgmt\src\Template\UserContacts\send_reply_confirm.ctp
plugins\Usermgmt\src\Template\UserEmails\index.ctp
plugins\Usermgmt\src\Template\UserEmails\send.ctp
plugins\Usermgmt\src\Template\UserEmails\send_confirm.ctp
plugins\Usermgmt\src\Template\UserEmails\send_to_user.ctp
plugins\Usermgmt\src\Template\UserEmails\send_to_user_confirm.ctp
plugins\Usermgmt\src\Template\UserEmails\view.ctp
plugins\Usermgmt\src\Template\UserEmailSignatures\add.ctp
plugins\Usermgmt\src\Template\UserEmailSignatures\edit.ctp
plugins\Usermgmt\src\Template\UserEmailSignatures\index.ctp
plugins\Usermgmt\src\Template\UserEmailTemplates\add.ctp
plugins\Usermgmt\src\Template\UserEmailTemplates\edit.ctp
plugins\Usermgmt\src\Template\UserEmailTemplates\index.ctp
plugins\Usermgmt\src\Template\UserGroups\add.ctp
plugins\Usermgmt\src\Template\UserGroups\edit.ctp
plugins\Usermgmt\src\Template\UserGroups\index.ctp
plugins\Usermgmt\src\Template\Users\access_denied.ctp
plugins\Usermgmt\src\Template\Users\activate_password.ctp
plugins\Usermgmt\src\Template\Users\add_multiple_users.ctp
plugins\Usermgmt\src\Template\Users\add_user.ctp
plugins\Usermgmt\src\Template\Users\change_password.ctp
plugins\Usermgmt\src\Template\Users\change_user_password.ctp
plugins\Usermgmt\src\Template\Users\dashboard.ctp
plugins\Usermgmt\src\Template\Users\edit_profile.ctp
plugins\Usermgmt\src\Template\Users\edit_user.ctp
plugins\Usermgmt\src\Template\Users\email_verification.ctp
plugins\Usermgmt\src\Template\Users\forgot_password.ctp
plugins\Usermgmt\src\Template\Users\index.ctp
plugins\Usermgmt\src\Template\Users\login.ctp
plugins\Usermgmt\src\Template\Users\myprofile.ctp
plugins\Usermgmt\src\Template\Users\online.ctp
plugins\Usermgmt\src\Template\Users\register.ctp
plugins\Usermgmt\src\Template\Users\upload_csv.ctp
plugins\Usermgmt\src\Template\Users\view_user.ctp
plugins\Usermgmt\src\Template\Users\view_user_permissions.ctp
plugins\Usermgmt\src\Template\UserSettings\cakelog.ctp

86. Add row div and adjust offset class in following files

plugins\Usermgmt\src\Template\Users\activate_password.ctp
plugins\Usermgmt\src\Template\Users\email_verification.ctp
plugins\Usermgmt\src\Template\Users\forgot_password.ctp
plugins\Usermgmt\src\Template\Users\login.ctp

87. replace all vendor folder and files in plugins\Usermgmt\vendor

Create a new google recaptcha application and update Secret and Site key in admin settings

Link https://www.google.com/recaptcha/admin

88. Open plugins\Usermgmt\webroot\css\umstyle.css

remove following css

.center {

table td .btn-group .btn {

#recaptcha_area, #recaptcha_table {

.um-form-row .checkbox input[type="checkbox"] {

add following css

#editSettingForm .radioValue .radio label {
    display:block;
}
.setting-options {
    list-style: none;
    padding: 0;
    margin:0;
}
.setting-options:after {
    clear:both;
    content:' ';
    display:block;
}
.setting-options li {
    float: left;
    margin-bottom: 10px;
    margin-right: 15px;
}
.setting-options li label {
    font-weight: normal;
}
.setting-options li label input {
    margin-right: 5px;
    margin-top: 0;
}
.panel-title-right {
    float:right;
    color:#ffffff;
    margin-left: 10px;
}
.panel-default .panel-title-right {
    color: #333;
}
.panel-title-right .btn {
    border-radius: 3px;
    font-size: 12px;
    padding: 5px 10px;
    margin-top: -2px;
}
.panel-title-right a {
    color:#ffffff;
}
.panel-title-right a.btn-default {
    color: #333;
}

89. Open plugins\Usermgmt\webroot\js\umscript.js

replace $('.messageHolder').remove(); with $(this).closest('.messageHolder').remove();