<?php

class UfilesController extends AppController {

 	var $name = 'Ufiles';
    var $helpers = array('Html', 'Form', 'FileUpload.FileUpload');
    var $components = array('FileUpload.FileUpload', 'RequestHandler');
    var $uses = array('Ufile', 'Keyword');


    function beforeFilter() {
        parent::beforeFilter();
		
        # some settings for the automatic upload handling
        # change the upload dir when we actually are uploading something
        if ($this->action == 'upload' && ! empty($this->data)) {
            $person = $this->Session->read('Auth.Person');
            $this->FileUpload->uploadDir(Configure::read('FileUpload.uploadDir') . $person['name'] . $person['id']);
        }
        else {
            $this->FileUpload->uploadDir(Configure::read('FileUpload.uploadDir'));
        }
        $this->FileUpload->forceWebroot(false);
        $this->FileUpload->fileModel(null);
        $this->FileUpload->allowedTypes(array('*'));
    }
	
   function upload() {
        if (! empty($this->data)) {
            # first add the newly entered kw's
            $new_kw_ids = $this->__add_keywords($this->data['Ufile']['new_keywords']);
            # add the new kw_id's to the KwKw array
            if (empty($this->data['Keyword']['Keyword'])) {
                $this->data['Keyword']['Keyword'] = array();
            }
            $this->data['Keyword']['Keyword'] = array_unique(array_merge($this->data['Keyword']['Keyword'], $new_kw_ids)); # add unique check in case someone added a new existing keyword and selected it as well
            # add the user id of the logged in user
            $person = $this->Session->read('Auth.Person');
            $this->data['Ufile']['person_id'] = $person['id'];
            if ($this->Ufile->validates($this->data)) {
                if ($this->FileUpload->success) {
                    $success = true;
                    foreach ($this->FileUpload->uploadedFiles as $uploaded_file) {
                        if ($uploaded_file['name'] && ! $uploaded_file['error']) {
                            $this->Ufile->create();
                            $this->data['Ufile']['name'] = $uploaded_file['name'];

                            if (! $this->Ufile->save($this->data)) {
                                $success = false;
                                $this->Session->setFlash(
                                    __('One or more files could not be saved.', true) .
                                   ' ' . $this->FileUpload->showErrors()
                                );
                                break;
                            }
                        }
                    }
                    if ($success) {
                        $this->redirect(array('action' => 'index'));
                    }
                }
                else {
                    $this->Session->setFlash('ERROR: ' . $this->FileUpload->showErrors());
                }
            }
        }
        # http://forums.mysql.com/read.php?10,225465,225545#msg-225545
        $keywords  = $this->Ufile->Keyword->find('list', array('order' => array('cast(name as char)' => 'ASC', 'binary name' => 'DESC')));
        $this->set(compact('keywords'));
    }

    function __add_keywords($kw) {
        $keywords = explode(',', $kw);
        $keywords = array_map('trim', $keywords);

        $saved = true;
        $keyword_ids = array();
        foreach ($keywords as $keyword) {
            if (empty($keyword)) continue;
            # look up the keyword in case it exists already
            $first_match = $this->Keyword->find('first', array('conditions' => array('name' => $keyword)));
            if (empty($first_match)) {
                $this->Keyword->locale = str_replace('-', '_', Configure::read('Config.language'));
                $this->Keyword->create();
                if (! $this->Keyword->save(array('Keyword' => array('name' => $keyword)))) {
                    $saved = false;
                    continue;
                }
                $keyword_ids[] = $this->Keyword->id;
            }
            else {
                $keyword_ids[] = $first_match['Keyword']['id'];
            }
        }

        return $keyword_ids;
    }

    /**
     * post-to-get search: post the search question, and redirect to a results page with the question asked in the querystring
     */
    function search() {
        unset($this->Ufile->validate['submitter']); # remove a specific validtion rule only for this action
        unset($this->Ufile->validate['name']); # remove a specific validtion rule only for this action
        
        if ($this->data) {
            # do some whitelisting
            $whitelist = array('person_id', 'name', 'description', 'invalid', 'file_type');
            $passed_values = array();
            foreach ($this->data['Ufile'] as $key => $values) {
                if (in_array($key, $whitelist)) {
					if (is_array($values)) {
						$value_array = array();
						foreach ($values as $value) {
							$value_array[] = $value;
						}
						$passed_values[$key] = implode(',', $value_array);
					} else {
						$passed_values[$key] = $values;
					}
                }
            }

            # handle the keywords
            $keywords = $this->Ufile->Keyword->find('list', array('conditions' => array('Keyword.id' => $this->data['Keyword']['Keyword'])));
            if (! empty($keywords)) {
                $passed_values['keyword'] = implode(';', $keywords);
            }
            if (! empty($passed_values)) {
                $this->redirect(array_merge(array('action' => 'results'), $passed_values));
            }
        }
        else {
			$fileTypeOptions = array('other' => 'other', 'raw' => 'raw', 'corrected' => 'corrected');
            $keywords = $this->Ufile->Keyword->find('list');
			$file_type = $this->Ufile->find('all', array('fields' => array('Ufile.file_type')));
            $person = $this->Ufile->Person->find('all', array('fields' => array('Person.id', 'Person.name'))); # get all people
            $people = Set::combine($person, '{n}.Person.id', '{n}.Person.name');
            $this->set(compact('keywords', 'people', 'fileTypeOptions'));
        }
    }

    function results() {
	
		$person = $this->Session->read('Auth.Person');
		$ufiles = $this->Ufile->query("SELECT DISTINCT uf.id FROM ufiles uf INNER JOIN projectpeople pp ON uf.person_id = pp.person_id WHERE uf.file_type = 'other' OR ((uf.file_type = 'raw' OR uf.file_type = 'corrected') AND (uf.id IN (SELECT ufile_id FROM testobjects tob INNER JOIN projectpeople pp ON tob.project_id = pp.project_id WHERE pp.person_id = " . $person['id'] . ") OR uf.id IN (SELECT ufile_raw_id FROM testobjects tob INNER JOIN projectpeople pp ON tob.project_id = pp.project_id  INNER JOIN projects p ON pp.project_id = p.id WHERE pp.person_id = " . $person['id'] . " OR DATE_ADD(p.end_date, INTERVAL p.waiting_period YEAR) < NOW())))");
		
		$available_ufile_ids = Set::extract('/uf/id', $ufiles);
	
        # TODO whitelist params
        # is actually not that necessary: any not correct conditions will result in a faulty query with no results.
        # CakePHP already handles SQL-injection anyway.
        $keywords = @$this->params['named']['keyword'];
        unset($this->params['named']['keyword']);
		
		if (!empty($this->params['named']['file_type'])){
			$file_types = explode(',', $this->params['named']['file_type']);
			unset($this->params['named']['file_type']);
			$this->params['named']['file_type'] = $file_types;
		}
        $conditions = $this->params['named'];
			
        $this->params['named']['keyword']     = $keywords;
		unset($conditions['page']);
		
        $keyword_ids = $this->Ufile->Keyword->find('list', array(
            'fields' => array('id', 'id'),
            'conditions' => array('name' => array_unique(explode(';', $keywords)))
        ));
        if (!empty($keyword_ids)) {
            #$conditions = array('Ufilekeyword.keyword_id' => array_unique($keyword_ids));
			$conditions['Ufilekeyword.keyword_id'] = array_unique($keyword_ids);
        }
		
		$conditions['Ufile.id'] = array_unique($available_ufile_ids);
		
        # this query will not get all the keywords for the files selected, so only use this to get the ufile_id

        $this->Ufile->bindModel(array('hasOne' => array('Ufilekeyword')), false);
        $ufile_ids = $this->Ufile->find('all', array(
            'contain' => array('Ufilekeyword'),
            'conditions' => $conditions,
        ));
        $ufile_ids = Set::extract('/Ufile/id', $ufile_ids);
		
        $this->paginate['Ufile'] = array(
            'contain' => array('Keyword', 'Person'),
            'conditions' => array('Ufile.id' => array_unique($ufile_ids)),
        );
        $this->set('ufiles', $this->paginate('Ufile'));
    }

    function invalidate($id = null) {
        if (!$this->RequestHandler->isAjax()) { # if no AJAX, it might be just a crawler
            $this->redirect('/', 500);
        }
        if (!$id) {
            $this->Session->setFlash(__('Invalid file', true));
            $this->redirect(array('action' => 'index'));
        }
        $ufile = $this->Ufile->read(null, $id);
        $ufile['Ufile']['invalid'] = $ufile['Ufile']['invalid'] == 1 ? 0 : 1;
        if ($this->Ufile->save($ufile)) {
        } else {
            $this->redirect('/', 500);
        }
    }
	function index() {
		$person = $this->Session->read('Auth.Person');
		$ufiles = $this->Ufile->query("SELECT DISTINCT uf.id FROM ufiles uf INNER JOIN projectpeople pp ON uf.person_id = pp.person_id WHERE uf.file_type = 'other' OR ((uf.file_type = 'raw' OR uf.file_type = 'corrected') AND (uf.id IN (SELECT ufile_id FROM testobjects tob INNER JOIN projectpeople pp ON tob.project_id = pp.project_id WHERE pp.person_id = " . $person['id'] . ") OR uf.id IN (SELECT ufile_raw_id FROM testobjects tob INNER JOIN projectpeople pp ON tob.project_id = pp.project_id INNER JOIN projects p ON pp.project_id = p.id WHERE pp.person_id = " . $person['id'] . " OR DATE_ADD(p.end_date, INTERVAL p.waiting_period YEAR) < NOW())))");
		
		$ufile_ids = Set::extract('/uf/id', $ufiles);
		
        $this->paginate['Ufile'] = array(
			'conditions' => array('Ufile.id' => array_unique($ufile_ids))
        );
		$this->set('ufiles', $this->paginate('Ufile'));
	}

	function view($id = null) {
		if (!$id) {
			$this->Session->setFlash(__('Invalid ufile', true));
			$this->redirect(array('action' => 'index'));
		}
        $ufile = $this->Ufile->read(null, $id);
		if ($ufile['Ufile']['invalid'] == 1) {
			$this->Session->setFlash(__('This entry has been marked as invalid!', true));
		}
		$this->set('ufile', $ufile);
	}

	function add() {
		if (!empty($this->data)) {
			$this->Ufile->create();
			if ($this->Ufile->save($this->data)) {
				$this->Session->setFlash(__('The ufile has been saved', true));
				$this->redirect(array('action' => 'index'));
			} else {
				$this->Session->setFlash(__('The ufile could not be saved. Please, try again.', true));
			}
		}
	}

	function edit($id = null) {
		if (!$id && empty($this->data)) {
			$this->Session->setFlash(__('Invalid ufile', true));
			$this->redirect(array('action' => 'index'));
		}
		if (!empty($this->data)) {
			if ($this->Ufile->save($this->data)) {
				$this->Session->setFlash(__('The ufile has been saved', true));
				$this->redirect(array('action' => 'index'));
			} else {
				$this->Session->setFlash(__('The ufile could not be saved. Please, try again.', true));
			}
		}
		if (empty($this->data)) {
			$this->data = $this->Ufile->read(null, $id);
		}
        $keywords = $this->Ufile->Keyword->find('list');
        $this->set(compact('keywords'));
	}

	function delete($id = null) {
		if (!$id) {
			$this->Session->setFlash(__('Invalid id for ufile', true));
			$this->redirect(array('action'=>'index'));
		}
		if ($this->Ufile->delete($id)) {
			$this->Session->setFlash(__('Ufile deleted', true));
			$this->redirect(array('action'=>'index'));
		}
		$this->Session->setFlash(__('Ufile was not deleted', true));
		$this->redirect(array('action' => 'index'));
	}
}
?>
