#StackBounty: #java #mvc #database #spring Meme (title with picture) exchanger

Bounty: 150

Project structure without code:
project structure without code

Packages:

packages

Classes in packages:

first part
second part

In ConfigConstants I store path to folder, where I save pictures. Also in WebConstants I store URL of Servlet.
Here is mySQL script for creating db:

drop database meme_exchanger;
CREATE SCHEMA `meme_exchanger` DEFAULT CHARACTER SET utf8 ;

use meme_exchanger;

create table users(
    id int auto_increment primary key,
    name varchar(30) not null unique,
    password varchar(20) not null,
    access_level_id int references access_levels.id,
    creation_date date not null
);

create table users_banned(
    id int auto_increment primary key,
    user_id int references users.id,
    _from date not null,
    _to date not null,
    removed boolean default false,
    removed_date date default null
);

create table access_levels(
    id int auto_increment primary key,
    name varchar(20) not null
);

create table posts(
    id int auto_increment primary key,
    title varchar(100),
    user_id int references users.id,
    publish_date date not null,
    picture_name varchar(50) not null
);

create table posts_banned(
    id int auto_increment primary key,
    post_id int references posts.id,
    _from date not null,
    _to date not null,
    removed boolean default false,
    removed_date date default null
);

create table post_likes(
    id int auto_increment primary key,
    post_id int references posts.id,
    user_id int references users.id,
    date date not null
);

create table post_comments(
    id int auto_increment primary key,
    post_id int references posts.id,
    user_id int references users.id,
    text varchar(500) not null,
    date date not null
);

create table post_comments_banned(
    id int auto_increment primary key,
    comment_id int references post_comments.id,
    _from date not null,
    _to date not null,
    removed boolean default false,
    removed_date date default null
);


create table user_ip_adresses(
    id int auto_increment primary key,
    user_id int references users.id,
    name varchar(15)
);

create table user_id_adresses_banned(
    id int auto_increment primary key,
    ip_adress_id int references user_ip_addresses.id,
    _from date not null,
    _to date not null,
    removed boolean default false,
    removed_date date default null
);

and creating admin account:

insert into access_levels
(name)
VALUES
    ('CommonUser'),
    ('Admin');
    
insert into users
(name, password, access_level_id, creation_date)
VALUES
    ('root', '123321a', 2, curdate());

To see code on GitHub.

It is my first project on Spring MVC(used Tomcat 7.0) and I think I did many design and coding mistakes. Help me to find them, please.


Get this bounty!!!

#StackBounty: #php #mvc PHP OOP MVC structure

Bounty: 50

I am quite new to the MVC concept. I already know how to program object-orientated from other languages like C++ or Java. I have implemented a little login system for test purpose.
I am not sure if my implementation is the best way to follow MVC. Any feedback is welcome.

The class ControllerUser is instantiated in a file called init.php. The $controllerUser variable is therefore accessible on every page. I am also not sure if this is the best way. Can somebody also explain to me when to use the view class and which functions should it have? I know that it should render/output the page and the data… does this mean that it should print the logout/login form?

This is my database class in which the connection is established. All models will inherit from this class.

class.database.php

class Database {
    protected $pdo;

    public function connect() {
        $datahost =  'localhost';
        $datauser =  'root';   
        $datapass =  'PASSWORD'; 
        $database =  'DATABASE';
        try {
            $options = [ PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ];
            $this->pdo = new PDO('mysql:host='.$datahost.';dbname='.$database.'', $datauser, $datapass, $options);
        } catch (PDOException $e) {
            print "Mysql Connection failed: " . $e->getMessage();
            die();
        }
    }

    public function disconnect() {
        $this->pdo = NULL;
    }
}

Everything will have an own model, controller and view, when necessary. In this case it is the user.

User controller:
controller.user.php

<?php
class ControllerUser {
    private $model;

    function __construct($datatable) {
        $this->model = new ModelUser($datatable);
    }

    public function login($email, $password) {
        $user = $this->model->getByEmail($email);
        if($user && password_verify($password,$user['password'])) {
            if($user['status']==1) {
                if($user['verified']==1) {
                    $_SESSION['id'] = $user['id'];
                    $this->model->updateIP($user['id']);
                    return true;
                }
                else {
                    throw new Exception('Not verified!');
                }
            }
            else {
                throw new Exception('Your account is locked. Contact a staff member.');
            }
        }
        else {
            throw new Exception('Email or password wrong!');
        }
    }

    public function logout() {
        if($this->isLoggedIn()) {
            session_destroy();
            unset($_SESSION['id']);
            return true;
        }
    }

    public function isLoggedIn() {
        if(isset($_SESSION['id'])) {
            $status = $this->model->getById($_SESSION['id'])['status'];
            if($status==1) {
                return true;
            }
            else {
                throw new Exception('Your account is locked. Contact a staff member.');
            }
        }
    }
}
?>

User model:
model.user.php

<?php
class ModelUser extends Database {

    private $datatable;

    function __construct($datatable) {
        $this->connect();
        $this->datatable = $datatable;
    }

    public function getByEmail($email) {
        $stmt = $this->pdo->prepare("SELECT * FROM ". $this->datatable ." WHERE email = :email");
        $result = $stmt->execute(['email' => $email]);
        return $stmt->fetch();
    }

    public function getById($id) {
        $stmt = $this->pdo->prepare("SELECT * FROM ". $this->datatable ." WHERE id = :id");
        $result = $stmt->execute(['id' => $id]);
        return $stmt->fetch();
    }

    public function updateIP($id) {
        $statement = $this->pdo->prepare("UPDATE ". $this->datatable ." SET ip = :ip WHERE id = :id");
        return $statement->execute(['ip' => $_SERVER['REMOTE_ADDR'], 'id' => $id]);
    }

    function __destruct() {
        $this->disconnect();
    }
}
?>

User view… I am not sure what could be inside of view…
The function there is only for test purpose:
view.user.php

<?php
class ViewUser {
    public function printUserInformation($data) {
        foreach($data as $key => $value){
            echo $key.': '.$value.'<br>';
        }
    }
}
?>

Everything comes to use on the login page:
login.php

<?php 
if(isset($_GET['login'])) {
    $viewUser = new ViewUser(); //test
    $modelUser = new ModelUser("users"); //test
    try {
        $controllerUser->login($_POST['email'], $_POST['password']);
        $viewUser->printUserInformation($modelUser->getById($_SESSION['id'])); //just a test
    }
    catch(Exception $e) {
        echo $e->getMessage();
    }
}

if(isset($_GET['logout'])) {
    $controllerUser->logout();
}

if(!$controllerUser->isLoggedIn()) { 
?>
<form class="login-form" action="?login=1" method="post">
<input type="email" size="40" maxlength="250" name="email" placeholder="Email address" required>
<input type="password" size="40"  maxlength="250" name="password" placeholder="Password" required>
<button type="submit" value="Login" class="button style1">login</button>
<input type="checkbox" id="stayloggedin" name="stay_loggedin"><label for="stay_loggedin" >stay logged in</label>
</form>
<?php }
else {
?>
<form class="logout" action="?logout=1" method="POST" style="display: inline-block;">
    <button type="submit" name="logout">logout</button>
</form>
<?php }
?>


Get this bounty!!!

#StackBounty: #php #mvc #codeigniter PHP Edit Volunteer Group Form

Bounty: 50

I have a PHP CodeIgniter website that collects volunteer registrations. One thing I have noticed is that the controllers are getting really big. The controllers have many methods, and each method is fairly long. I believe this could be a code smell, and I would like some help and advice on how to refactor the code.

The website is in production and too big to post all the code. I will pick a sample page to post here so you can get an idea. I’m looking for broad feedback on how to improve the organization of the code. For example:

  • Idea 1 – Should I move some of this code to a new layer between the controller and the model? I’ve seen this recommended in some places. I believe it’s called a domain layer.
  • Idea 2 – Should I break this entire method (and other big methods) off into their own classes? Since I’m using CodeIgniter, I guess these would be library classes?
  • Idea 3 – Should I make more use of private methods within the giant controller class? Won’t shrink the size of the controller, but might make some of the code more readable. Or maybe not, since I’d be scrolling all over the page to find code, instead of just reading it linearly.
  • Idea 4 – Should I try to move more code into the models? My models are a similar size to the controllers.
  • Idea 5 – The code works and I (the only developer) can read it just fine. Should I just leave it alone? YAGNI? Keep complexity down?
  • I have a lot of controller methods that start out with form validation code. What is the best way to handle that?
  • Bonus question: What are good ways to test a website? I currently use iMacros browser plugin and run scripts that simulate typing, mouse clicks, submitting forms, clicking links, etc. I have heard of unit testing but am not sure where to start with that. Is it worth it to write a bunch of unit tests?
  • Other ideas/feedback?

Screenshot

enter image description here

Code

public function edit_group($group_id_and_text = NULL)
{
    $this->data = set_page_title('Edit Group', $this->data);

    $this->data = $this->_get_group_data_or_throw_error_page($group_id_and_text, $this->data, '/managers/edit_group/');

    $this->data['list_of_shifts'] = $this->shift_model->get_race_shifts_with_enrolled_plus_groups_fields($this->data['race']['race_id']);

    $this->data['list_of_group_shifts'] = $this->group_shift_model->get_group_shifts_for_group($this->data['group']['group_id']);

    // output format is $shift_id => $number_promised
    $this->data['list_of_group_shifts_as_list'] = $this->group_shift_model->get_group_shifts_as_list($this->data['group']['group_id'], $this->data['race']['race_id']);

    $this->data['list_of_shifts_to_highlight'] = highlight_shifts_that_need_more_groups($this->data['list_of_shifts']);

    $this->data['list_of_volunteers_with_shifts'] = $this->volunteer_shift_model->get_volunteers_by_race_and_group($this->data['race']['race_id'], $this->data['group']['group_id']);

    $this->data['list_of_volunteers_without_shifts'] = $this->volunteer_shift_model->get_volunteers_with_no_shifts_filter_by_group($this->data['race']['race_id'], $this->data['group']['group_id']);

    $this->data['list_of_volunteers'] = array_merge($this->data['list_of_volunteers_with_shifts'], $this->data['list_of_volunteers_without_shifts']);

    $this->form_validation->set_rules('group_name', 'Group Name', 'trim|required|max_length[200]');

    $this->form_validation->set_rules('shift_id[]', 'Volunteer Shift', 'trim|valid_volunteer_group_shift_for_admin[' . $this->data['race']['race_id'] . ']');

    $this->form_validation->set_rules('group_notes', 'Group Notes', 'trim|max_length[1000]');
    $this->form_validation->set_rules('group_send_reminder_emails', 'Reminder Emails', 'trim|required|in_list[0,1]');
    $this->form_validation->set_rules('fix_shifts', 'Fix Volunteer Shifts', 'trim|in_list[1]');
    $this->form_validation->set_rules('email_group_leader', 'Email Group Leader', 'trim|in_list[1]');
    $this->form_validation->set_rules('delete_group', 'Delete Group', 'trim|in_list[1]');
    $this->form_validation->set_rules('delete_group_members', 'Delete Group Members', 'trim|in_list[1]');
    $this->form_validation->set_rules('group_firm', 'Mark As Firm', 'trim|in_list[1]');

    // Note: SQL WHERE is case insensitive, which is good in this case
    $this->data['group_for_duplicate_check'] = $this->group_model->get_group_by_race_and_group_name(
        $this->data['race']['race_id'],
        $this->input->post('group_name')
    );

    if ($this->form_validation->run() === FALSE)
    {
        load_page_with_event_nav('managers/edit_group', $this->data);
    }
    elseif ( $this->data['group_for_duplicate_check'] && $this->data['group_for_duplicate_check']['group_id'] != $this->data['group']['group_id'] )
    {
        add_message('error', 'A group with this name already exists. <a href="/managers/edit_group/' . $this->data['group_for_duplicate_check']['group_uri'] . '">Click here</a> to view and edit the existing group.');

        load_page_with_event_nav('managers/edit_group', $this->data);
    }
    else
    {
        $group_leader_volunteer_id = $this->data['group']['group_leader_volunteer_id'];

        // Putting delete_group_members before delete_group so that the soft deleted volunteers keep their group_id. Will be helpful if I have to undo the soft delete.
        if ( $this->input->post('delete_group_members') )
        {
            $volunteer_ids = $this->data['list_of_volunteers'];

            if ( $volunteer_ids ) {         
                $volunteer_ids = sql_make_list_from_sql_result_array($volunteer_ids, 'volunteer_id');

                $volunteer_ids = mv_eliminate_duplicates($volunteer_ids);

                $this->volunteer_model->soft_delete_volunteer($volunteer_ids);

                add_message('success', '"' . html_escape($this->data['group']['group_name']) . '"'s group members were successfully deleted from the group AND the volunteer database.');
            }
        }

        if ( $this->input->post('delete_group') )
        {
            $this->group_model->soft_delete_groups($this->data['group']['group_id']);

            // If group_leader_volunteer_id got deleted because the volunteer got soft deleted, AND the group is getting deleted, restore the group_leader_volunteer_id so that email_list can display deleted group leaders.
            $this->group_model->set_group_leader($this->data['group']['group_id'], $group_leader_volunteer_id);

            add_message('success', '"' . html_escape($this->data['group']['group_name']) . '" was successfully deleted.');
        }
        else
        {
            $this->group_model->edit_group($this->data);

            // refresh some variables needed down here
            $this->data['group'] = $this->group_model->get_group_by_id($this->data['group']['group_id']);

            $this->data['volunteer'] = $this->volunteer_model->get_volunteer_by_id($this->data['group']['group_leader_volunteer_id']);

            $this->data['list_of_group_shifts'] = $this->group_shift_model->get_group_shifts_for_group($this->data['group']['group_id']);

            $shifts_to_compare = $this->data['list_of_group_shifts_as_list'];

            /*
                PHP's array compare is extremely loose.
                1) It compares array contents, not references.
                2) It compares across types. For example, 0 and '0' are seen as the same thing.
                3) The order of the array keys doesn't matter, so we don't need to sort them.
            */
            if ( $this->input->post('shift_id') != $shifts_to_compare )
            {
                $this->group_shift_model->hard_delete_groups_shifts($this->data['group']['group_id']);

                foreach ( $_POST['shift_id'] as $shift_id => $value )
                {
                    if ( $value != 0 )
                    {
                        $this->group_shift_model->add_shift(
                            $this->data['group']['group_id'],
                            $shift_id,
                            $value,
                            $this->data
                        );
                    }
                }
            }

            // refresh again
            $this->data['list_of_group_shifts'] = $this->group_shift_model->get_group_shifts_for_group($this->data['group']['group_id']);

            $list_of_group_shifts = sql_make_list_from_sql_result_array($this->data['list_of_group_shifts'], 'shift_id');

            // Make sure the group leader is enrolled in all the group's shifts. This is important so that the group leader receives the volunteer instructions for each of this group's shifts.
            if ( $this->data['volunteer'] )
            {
                foreach ( $list_of_group_shifts as $key => $shift_id )
                {
                    $shift = $this->volunteer_shift_model->get_shift_by_volunteer_id_and_shift_id($this->data['volunteer']['volunteer_id'], $shift_id);

                    if ( ! $shift )
                    {
                        $this->volunteer_shift_model->add_shift(
                            $this->data['volunteer']['volunteer_id'],
                            $shift_id,
                            $this->data['auth']['manager']['manager_id']
                        );
                    }
                }
            }

            add_message('success', '"<a href="/managers/edit_group/' . $this->data['group']['group_uri'] . '">' . html_escape($this->data['group']['group_name']) . '</a>" was successfully edited.');

            if ( $this->input->post('fix_shifts') == 1 )
            {
                // ****** FIX_SHIFTS_REMOVE ******
                foreach ( $this->data['list_of_volunteers_with_shifts'] as $key => $volunteer_shift )
                {
                    if ( !in_array($volunteer_shift['shift_id'], $list_of_group_shifts) )
                    {
                        $this->volunteer_shift_model->hard_delete_one_volunteer_one_shift($volunteer_shift['volunteer_id'], $volunteer_shift['shift_id']);
                    }
                }

                // ****** FIX_SHIFTS_ADD ******
                $this->data['list_of_volunteers_not_joined_with_volunteer_shifts'] = $this->volunteer_model->get_volunteers_by_race_and_group($this->data['race']['race_id'], $this->data['group']['group_id']);

                $this->data['list_of_volunteer_shifts_for_this_race'] = $this->volunteer_shift_model->get_volunteers_by_race_order_by_name($this->data['race']['race_id']);

                foreach ( $this->data['list_of_volunteers_not_joined_with_volunteer_shifts'] as $key => $volunteer )
                {
                    foreach ( $list_of_group_shifts as $key => $shift_id )
                    {
                        $shift_already_exists = sql_search_result_array_contains_key1_value1_key2_value2(
                            $this->data['list_of_volunteer_shifts_for_this_race'],
                            'volunteer_id',
                            $volunteer['volunteer_id'],
                            'shift_id',
                            $shift_id
                        );

                        if ( ! $shift_already_exists )
                        {
                            $this->volunteer_shift_model->add_shift(
                                $volunteer['volunteer_id'],
                                $shift_id,
                                $this->data['auth']['manager']['manager_id']
                            );
                        }
                    }
                }

                $this->group_shift_model->fix_more_enrolled_vols_than_estimated_vols($this->data['group']['group_id']);
            }

            if ( $this->input->post('email_group_leader') == 1 )
            {
                // return true for non-NULL, non-zero
                if ( $this->data['group']['group_leader_volunteer_id'] )
                {
                    $this->data['list_of_this_groups_shifts'] = $this->shift_model->get_group_shifts($this->data['group']['group_id']);

                    send_group_confirmation_email($this->data, $this->data['volunteer']['volunteer_email']);

                    add_message('success', 'Also, we e-mailed the group leader a group confirmation e-mail.');
                }
                else
                {
                    add_message('error', 'You requested that we send a confirmation e-mail, but we were unable to because a volunteer group leader was not provided.');
                }
            }
        }

        $this->shift_model->recalculate_shift_stats($this->data['race']['race_id']);

        redirect_and_die('/managers/group_report/' . $this->data['race']['race_uri']);
    }
}


Get this bounty!!!

#StackBounty: #magento-1.9 #api #soap-api-v2 #time #mvc Soap API – How to get request by Limit 10 based on pagination?

Bounty: 50

I am getting products list using catalogProductList, its taking too long time to return the values(see screenshot) actually my products count is 24K, how can i run by using limit 10 and if i click page 2 then only load next 10 (Now load everything then only print the value).

Now my design look like,

enter image description here

Code :

$proxy = new SoapClient('www.abc.com/api/v2_soap/?wsdl=1');
        $sessionId = $proxy->login((object)array('username' => 'abc', 'apiKey' => 'abc123'));
        $result = $proxy->catalogProductList((object)array('sessionId' => $sessionId->result, 'filters' => null));      
        return $result->result();

Note : https://datatables.net/examples/styling/bootstrap4

How to run API soap v2 as limit 10, and should be next 10 load when i click page 2?


Get this bounty!!!