<commit_before><?php
/**
 * HUBzero CMS
 *
 * Copyright 2005-2011 Purdue University. All rights reserved.
 *
 * This file is part of: The HUBzero(R) Platform for Scientific Collaboration
 *
 * The HUBzero(R) Platform for Scientific Collaboration (HUBzero) is free
 * software: you can redistribute it and/or modify it under the terms of
 * the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any
 * later version.
 *
 * HUBzero is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * HUBzero is a registered trademark of Purdue University.
 *
 * @package   hubzero-cms
 * @author    <NAME> <<EMAIL>>
 * @copyright Copyright 2005-2011 Purdue University. All rights reserved.
 * @license   http://www.gnu.org/licenses/lgpl-3.0.html LGPLv3
 */

// Check to ensure this file is included in Joomla!
defined('_JEXEC') or die( 'Restricted access' );

/**
 * Projects Links plugin
 */
class plgProjectsLinks extends \Hubzero\Plugin\Plugin
{
	/**
	 * Affects constructor behavior. If true, language files will be loaded automatically.
	 *
	 * @var    boolean
	 */
	protected $_autoloadLanguage = true;

	/**
	 * Store redirect URL
	 *
	 * @var	   string
	 */
	protected $_referer = NULL;

	/**
	 * Store output message
	 *
	 * @var	   array
	 */
	protected $_message = NULL;

	/**
	 * Event call to determine if this plugin should return data
	 *
	 * @return     array   Plugin name and title
	 */
	public function &onProjectAreas( $all = false)
	{
		// Not showing side panel
		$area = array();

		if ($all == true)
		{
			$area = array(
				'name' => 'links',
				'title' => 'Links'
			);
		}

		return $area;
	}

	/**
	 * Event call to return count of items
	 *
	 * @param      object  $project 		Project
	 * @param      integer &$counts
	 * @return     array   integer
	 */
	public function onProjectCount( $project, &$counts )
	{
		// Not counting
		return false;
	}

	/**
	 * Event call to return data for a specific project
	 *
	 * @param      object  $project 		Project
	 * @param      string  $option 			Component name
	 * @param      integer $authorized 		Authorization
	 * @param      integer $uid 			User ID
	 * @param      integer $msg 			Message
	 * @param      integer $error 			Error
	 * @param      string  $action			Plugin task
	 * @param      string  $areas  			Plugins to return data
	 * @return     array   Return array of html
	 */
	public function onProject ( $project, $option, $authorized,
		$uid, $msg = '', $error = '', $action = '', $areas = NULL)
	{

		// What's the task?
		$this->_task = $action ? $action : JRequest::getVar('action');

		// Get this area details
		$this->_area = $this->onProjectAreas(true);

		// Check if our area is in the array of areas we want to return results for
		if (is_array( $areas ))
		{
			if (empty($this->_area) || !in_array($this->_area['name'], $areas))
			{
				return;
			}
		}

		$tasks = array('browser', 'select' , 'parseurl',
			'parsedoi', 'addcitation', 'deletecitation',
			'newcite', 'editcite', 'savecite');

		// Publishing?
		if ( in_array($this->_task, $tasks) )
		{
			$this->_project = $project;

			// Set vars
			$this->_database 	= JFactory::getDBO();
			$this->_option 		= $option;
			$this->_authorized 	= $authorized;
			$this->_uid 		= $uid;
			$this->_msg 		= $msg;

			if (!$this->_uid)
			{
				$juser = JFactory::getUser();
				$this->_uid = $juser->get('id');
			}

			// Load component configs
			$this->_config 		= JComponentHelper::getParams('com_projects');
			$this->_pubconfig 	= JComponentHelper::getParams('com_publications');

			// Actions
			switch ($this->_task)
			{
				case 'browser':
				default:
					$html = $this->browser();
					break;

				case 'parseurl':
					$html = $this->parseUrl();
					break;

				case 'parsedoi':
					$html = $this->parseDoi();
					break;

				case 'addcitation':
					$html = $this->addCitation();
					break;

				case 'deletecitation':
					$html = $this->deleteCitation();
					break;

				case 'select':
				case 'newcite':
					$html = $this->select();
					break;
				case 'editcite':
					$html = $this->editcite();
					break;
				case 'savecite':
					$html = $this->savecite();
					break;
			}

			$arr = array(
				'html' 		=> $html,
				'metadata' 	=> '',
				'msg' 		=> $this->_message,
				'referer' 	=> $this->_referer
			);

			return $arr;
		}

		// Nothing to return
		return false;
	}

	/**
	 * Delete a citation from a publication
	 *
	 * @return     string
	 */
	public function deleteCitation()
	{
		// Incoming
		$cid 		= JRequest::getInt('cid', 0);
		$version 	= JRequest::getVar('version', 'dev');
		$pid 		= JRequest::getInt('pid', 0);

		if (!$cid || !$pid)
		{
			$this->setError( JText::_('PLG_PROJECTS_LINKS_ERROR_CITATION_DELETE') );
		}

		// Make sure this publication belongs to this project
		$objP = new Publication( $this->_database );
		if (!$objP->load($pid) || $objP->project_id != $this->_project->id)
		{
			$this->setError( JText::_('PLG_PROJECTS_LINKS_ERROR_CITATION_DELETE') );
		}

		// Remove citation
		if (!$this->getError())
		{
			// Unattach citation
			if ($this->unattachCitation($pid, $cid ))
			{
				$this->_msg = JText::_('PLG_PROJECTS_LINKS_CITATION_DELETED');
			}
		}

		// Pass success or error message
		if ($this->getError())
		{
			$this->_message = array('message' => $this->getError(), 'type' => 'error');
		}
		elseif (isset($this->_msg) && $this->_msg)
		{
			$this->_message = array('message' => $this->_msg, 'type' => 'success');
		}

		// Build pub url
		$route = $this->_project->provisioned
			? 'index.php?option=com_publications' . a . 'task=submit'
			: 'index.php?option=com_projects' . a . 'alias=' . $this->_project->alias
				. a . 'active=publications';
		$url = JRoute::_($route . a . 'pid=' . $pid).'/?version=' . $version . '&section=citations';

		$this->_referer = $url;
		return;
	}

	/**
	 * Attach a citation to a publication
	 *
	 * @return     string
	 */
	public function addCitation()
	{
		// Incoming
		$url 		= JRequest::getVar('citation-doi', '');
		$url		= $url ? $url : urldecode(JRequest::getVar('url'));
		$version 	= JRequest::getVar('version', 'dev');
		$pid 		= JRequest::getInt('pid', 0);

		if (!$url || !$pid)
		{
			$this->setError( JText::_('PLG_PROJECTS_LINKS_NO_DOI') );
		}

		$parts 		= explode("doi:", $url);
		$doi   		= count($parts) > 1 ? $parts[1] : $url;
		$format		= $this->_pubconfig->get('citation_format', 'apa');

		// Attach citation
		if ($this->attachCitation($pid, $doi, $format, $this->_uid ))
		{
			$this->_msg = JText::_('PLG_PROJECTS_LINKS_CITATION_SAVED');
		}

		// Pass success or error message
		if ($this->getError())
		{
			$this->_message = array('message' => $this->getError(), 'type' => 'error');
		}
		elseif (isset($this->_msg) && $this->_msg)
		{
			$this->_message = array('message' => $this->_msg, 'type' => 'success');
		}

		// Build pub url
		$route = $this->_project->provisioned
			? 'index.php?option=com_publications' . a . 'task=submit'
			: 'index.php?option=com_projects' . a . 'alias=' . $this->_project->alias
				. a . 'active=publications';
		$url = JRoute::_($route . a . 'pid=' . $pid)
			.'/?version=' . $version . '&section=citations';

		$this->_referer = $url;
		return;
	}

	/**
	 * Attach a citation to a publication (in non-curated flow)
	 *
	 * @return     string
	 */
	public function savecite()
	{
		// Incoming
		$cite 		= JRequest::getVar('cite', array(), 'post', 'none', 2);
		$pid  		= JRequest::getInt('pid', 0);
		$version 	= JRequest::getVar('version', 'dev');

		$new  = $cite['id'] ? false : true;

		include_once( JPATH_ROOT . DS . 'administrator' . DS . 'components'
			. DS . 'com_citations' . DS . 'tables' . DS . 'citation.php' );
		include_once( JPATH_ROOT . DS . 'administrator' . DS . 'components'
			. DS . 'com_citations' . DS . 'tables' . DS . 'association.php' );

		if (!$pid || !$cite['type'] || !$cite['title'])
		{
			$this->setError( JText::_('PLG_PROJECTS_PUBLICATIONS_CITATIONS_ERROR_MISSING_REQUIRED'));
		}
		else
		{
			$citation = new CitationsCitation( $this->_database );
			if (!$citation->bind($cite))
			{
				$this->setError($citation->getError());
			}
			else
			{
				$citation->created 		= $new == true ? JFactory::getDate()->toSql() : $citation->created;
				$citation->uid			= $new == true ? $this->_uid : $citation->uid;
				$citation->published	= 1;

				if (!$citation->store(true))
				{
					// This really shouldn't happen.
					$this->setError(JText::_('PLG_PROJECTS_PUBLICATIONS_CITATIONS_ERROR_SAVE'));
				}
			}
			// Create association
			if (!$this->getError() && $new == true && $citation->id)
			{
				$assoc 		 = new CitationsAssociation( $this->_database );
				$assoc->oid  = $pid;
				$assoc->tbl  = 'publication';
				$assoc->type = 'owner';
				$assoc->cid  = $citation->id;

				// Store new content
				if (!$assoc->store())
				{
					$this->setError($assoc->getError());
				}
			}

			$this->_msg = JText::_('PLG_PROJECTS_LINKS_CITATION_SAVED');
		}

		// Pass success or error message
		if ($this->getError())
		{
			$this->_message = array('message' => $this->getError(), 'type' => 'error');
		}
		elseif (isset($this->_msg) && $this->_msg)
		{
			$this->_message = array('message' => $this->_msg, 'type' => 'success');
		}

		// Build pub url
		$route = $this->_project->provisioned
			? 'index.php?option=com_publications' . a . 'task=submit'
			: 'index.php?option=com_projects' . a . 'alias=' . $this->_project->alias
				. a . 'active=publications';
		$url = JRoute::_($route . a . 'pid=' . $pid)
			.'/?version=' . $version . '&section=citations';

		$this->_referer = $url;
		return;
	}

	/**
	 * Remove citation
	 *
	 * @return   boolean
	 */
	public function unattachCitation($pid = 0, $cid = 0, $returnStatus = false)
	{
		include_once( JPATH_ROOT . DS . 'administrator' . DS . 'components'
			. DS . 'com_citations' . DS . 'tables' . DS . 'citation.php' );
		include_once( JPATH_ROOT . DS . 'administrator' . DS . 'components'
			. DS . 'com_citations' . DS . 'tables' . DS . 'association.php' );
		include_once( JPATH_ROOT . DS . 'components' . DS . 'com_citations'
			. DS . 'helpers' . DS . 'format.php' );

		if (!$cid || !$pid)
		{
			$this->setError( JText::_('PLG_PROJECTS_LINKS_NO_DOI') );

			if ($returnStatus)
			{
				$out['error'] = $this->getError();
				return $out;
			}
			return false;
		}

		$database = JFactory::getDBO();
		$c 		  = new CitationsCitation( $database );
		$assoc 	  = new CitationsAssociation($database);

		// Fetch all associations
		$aPubs = $assoc->getRecords(array('cid' => $cid));

		// Remove citation if only one association
		if (count($aPubs) == 1)
		{
			// Delete the citation
			$c->delete($cid);
		}

		// Remove association
		foreach ($aPubs as $aPub)
		{
			if ($aPub->oid == $pid && $aPub->tbl = 'publication')
			{
				$assoc->delete($aPub->id);
			}
		}

		if ($returnStatus)
		{
			$out['success'] = true;
			return $out;
		}

		return true;
	}

	/**
	 * Attach citation
	 *
	 * @return   boolean
	 */
	public function attachCitation($pid = 0, $doi = NULL, $format = 'apa',
		$actor = 0, $returnStatus = false)
	{
		include_once( JPATH_ROOT . DS . 'administrator' . DS . 'components'
			. DS . 'com_citations' . DS . 'tables' . DS . 'citation.php' );
		include_once( JPATH_ROOT . DS . 'administrator' . DS . 'components'
			. DS . 'com_citations' . DS . 'tables' . DS . 'association.php' );
		include_once( JPATH_ROOT . DS . 'administrator' . DS . 'components'
			. DS . 'com_citations' . DS . 'tables' . DS . 'type.php' );
		include_once( JPATH_ROOT . DS . 'components' . DS . 'com_citations'
			. DS . 'helpers' . DS . 'format.php' );

		$out = array('error' => NULL, 'success' => NULL );

		if (!$doi || !$pid)
		{
			$this->setError( JText::_('PLG_PROJECTS_LINKS_NO_DOI') );

			if ($returnStatus)
			{
				$out['error'] = $this->getError();
				return $out;
			}
			return false;
		}

		$database = JFactory::getDBO();
		$c 		  = new CitationsCitation( $database );

		if ($c->loadPubCitation($doi, $pid))
		{
			$this->setError( JText::_('PLG_PROJECTS_LINKS_CITATION_ALREADY_ATTACHED') );

			if ($returnStatus)
			{
				$out['error'] = $this->getError();
				return $out;
			}

			return false;
		}
		else
		{
			// Get DOI preview
			$output = self::parseUrl($doi, true, true, $format);
			$output = json_decode($output);

			if (isset($output->error) && $output->error)
			{
				$this->setError( $output->error );

				if ($returnStatus)
				{
					$out['error'] = $this->getError();
					return $out;
				}

				return false;
			}
			elseif (isset($output->preview) && $output->preview)
			{
				// Load citation record with the same DOI if present
				if (!$c->loadByDoi($doi))
				{
					$c->created 	= JFactory::getDate()->toSql();
					$c->title   	= $doi;
					$c->uid			= $actor;
					$c->affiliated 	= 1;
				}
				$c->formatted 		= $output->preview;
				$c->format			= $format;
				$c->doi				= $doi;

				// Try getting more metadata
				$data = self::getDoiMetadata($doi, false, $url = '');

				// Save available data
				if ($data)
				{
					foreach ($c as $key => $value)
					{
						$column = strtolower($key);
						if (isset($data->$column))
						{
							$c->$column = $data->$column;
						}
					}

					// Some extra mapping hacks
					$c->pages = $data->page;

					// Get type ID
					$ct = new CitationsType($database);
					$types = $ct->getType();
					$dType = isset($data->type) ? $data->type : 'article';

					// Hub types don't match library types
					// Trying to match the best we can
					$validTypes = array();
					foreach ($types as $type)<commit_msg>[#7142][HUBZERO][PLG_PROJECTS_LINKS] strict standards error fix when adding citation<commit_after><?php
/**
 * HUBzero CMS
 *
 * Copyright 2005-2011 Purdue University. All rights reserved.
 *
 * This file is part of: The HUBzero(R) Platform for Scientific Collaboration
 *
 * The HUBzero(R) Platform for Scientific Collaboration (HUBzero) is free
 * software: you can redistribute it and/or modify it under the terms of
 * the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any
 * later version.
 *
 * HUBzero is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * HUBzero is a registered trademark of Purdue University.
 *
 * @package   hubzero-cms
 * @author    <NAME> <<EMAIL>>
 * @copyright Copyright 2005-2011 Purdue University. All rights reserved.
 * @license   http://www.gnu.org/licenses/lgpl-3.0.html LGPLv3
 */

// Check to ensure this file is included in Joomla!
defined('_JEXEC') or die( 'Restricted access' );

/**
 * Projects Links plugin
 */
class plgProjectsLinks extends \Hubzero\Plugin\Plugin
{
	/**
	 * Affects constructor behavior. If true, language files will be loaded automatically.
	 *
	 * @var    boolean
	 */
	protected $_autoloadLanguage = true;

	/**
	 * Store redirect URL
	 *
	 * @var	   string
	 */
	protected $_referer = NULL;

	/**
	 * Store output message
	 *
	 * @var	   array
	 */
	protected $_message = NULL;

	/**
	 * Event call to determine if this plugin should return data
	 *
	 * @return     array   Plugin name and title
	 */
	public function &onProjectAreas( $all = false)
	{
		// Not showing side panel
		$area = array();

		if ($all == true)
		{
			$area = array(
				'name' => 'links',
				'title' => 'Links'
			);
		}

		return $area;
	}

	/**
	 * Event call to return count of items
	 *
	 * @param      object  $project 		Project
	 * @param      integer &$counts
	 * @return     array   integer
	 */
	public function onProjectCount( $project, &$counts )
	{
		// Not counting
		return false;
	}

	/**
	 * Event call to return data for a specific project
	 *
	 * @param      object  $project 		Project
	 * @param      string  $option 			Component name
	 * @param      integer $authorized 		Authorization
	 * @param      integer $uid 			User ID
	 * @param      integer $msg 			Message
	 * @param      integer $error 			Error
	 * @param      string  $action			Plugin task
	 * @param      string  $areas  			Plugins to return data
	 * @return     array   Return array of html
	 */
	public function onProject ( $project, $option, $authorized,
		$uid, $msg = '', $error = '', $action = '', $areas = NULL)
	{

		// What's the task?
		$this->_task = $action ? $action : JRequest::getVar('action');

		// Get this area details
		$this->_area = $this->onProjectAreas(true);

		// Check if our area is in the array of areas we want to return results for
		if (is_array( $areas ))
		{
			if (empty($this->_area) || !in_array($this->_area['name'], $areas))
			{
				return;
			}
		}

		$tasks = array('browser', 'select' , 'parseurl',
			'parsedoi', 'addcitation', 'deletecitation',
			'newcite', 'editcite', 'savecite');

		// Publishing?
		if ( in_array($this->_task, $tasks) )
		{
			$this->_project = $project;

			// Set vars
			$this->_database 	= JFactory::getDBO();
			$this->_option 		= $option;
			$this->_authorized 	= $authorized;
			$this->_uid 		= $uid;
			$this->_msg 		= $msg;

			if (!$this->_uid)
			{
				$juser = JFactory::getUser();
				$this->_uid = $juser->get('id');
			}

			// Load component configs
			$this->_config 		= JComponentHelper::getParams('com_projects');
			$this->_pubconfig 	= JComponentHelper::getParams('com_publications');

			// Actions
			switch ($this->_task)
			{
				case 'browser':
				default:
					$html = $this->browser();
					break;

				case 'parseurl':
					$html = $this->parseUrl();
					break;

				case 'parsedoi':
					$html = $this->parseDoi();
					break;

				case 'addcitation':
					$html = $this->addCitation();
					break;

				case 'deletecitation':
					$html = $this->deleteCitation();
					break;

				case 'select':
				case 'newcite':
					$html = $this->select();
					break;
				case 'editcite':
					$html = $this->editcite();
					break;
				case 'savecite':
					$html = $this->savecite();
					break;
			}

			$arr = array(
				'html' 		=> $html,
				'metadata' 	=> '',
				'msg' 		=> $this->_message,
				'referer' 	=> $this->_referer
			);

			return $arr;
		}

		// Nothing to return
		return false;
	}

	/**
	 * Delete a citation from a publication
	 *
	 * @return     string
	 */
	public function deleteCitation()
	{
		// Incoming
		$cid 		= JRequest::getInt('cid', 0);
		$version 	= JRequest::getVar('version', 'dev');
		$pid 		= JRequest::getInt('pid', 0);

		if (!$cid || !$pid)
		{
			$this->setError( JText::_('PLG_PROJECTS_LINKS_ERROR_CITATION_DELETE') );
		}

		// Make sure this publication belongs to this project
		$objP = new Publication( $this->_database );
		if (!$objP->load($pid) || $objP->project_id != $this->_project->id)
		{
			$this->setError( JText::_('PLG_PROJECTS_LINKS_ERROR_CITATION_DELETE') );
		}

		// Remove citation
		if (!$this->getError())
		{
			// Unattach citation
			if ($this->unattachCitation($pid, $cid ))
			{
				$this->_msg = JText::_('PLG_PROJECTS_LINKS_CITATION_DELETED');
			}
		}

		// Pass success or error message
		if ($this->getError())
		{
			$this->_message = array('message' => $this->getError(), 'type' => 'error');
		}
		elseif (isset($this->_msg) && $this->_msg)
		{
			$this->_message = array('message' => $this->_msg, 'type' => 'success');
		}

		// Build pub url
		$route = $this->_project->provisioned
			? 'index.php?option=com_publications' . a . 'task=submit'
			: 'index.php?option=com_projects' . a . 'alias=' . $this->_project->alias
				. a . 'active=publications';
		$url = JRoute::_($route . a . 'pid=' . $pid).'/?version=' . $version . '&section=citations';

		$this->_referer = $url;
		return;
	}

	/**
	 * Attach a citation to a publication
	 *
	 * @return     string
	 */
	public function addCitation()
	{
		// Incoming
		$url 		= JRequest::getVar('citation-doi', '');
		$url		= $url ? $url : urldecode(JRequest::getVar('url'));
		$version 	= JRequest::getVar('version', 'dev');
		$pid 		= JRequest::getInt('pid', 0);

		if (!$url || !$pid)
		{
			$this->setError( JText::_('PLG_PROJECTS_LINKS_NO_DOI') );
		}

		$parts 		= explode("doi:", $url);
		$doi   		= count($parts) > 1 ? $parts[1] : $url;
		$format		= $this->_pubconfig->get('citation_format', 'apa');

		// Attach citation
		if ($this->attachCitation($pid, $doi, $format, $this->_uid ))
		{
			$this->_msg = JText::_('PLG_PROJECTS_LINKS_CITATION_SAVED');
		}

		// Pass success or error message
		if ($this->getError())
		{
			$this->_message = array('message' => $this->getError(), 'type' => 'error');
		}
		elseif (isset($this->_msg) && $this->_msg)
		{
			$this->_message = array('message' => $this->_msg, 'type' => 'success');
		}

		// Build pub url
		$route = $this->_project->provisioned
			? 'index.php?option=com_publications' . a . 'task=submit'
			: 'index.php?option=com_projects' . a . 'alias=' . $this->_project->alias
				. a . 'active=publications';
		$url = JRoute::_($route . a . 'pid=' . $pid)
			.'/?version=' . $version . '&section=citations';

		$this->_referer = $url;
		return;
	}

	/**
	 * Attach a citation to a publication (in non-curated flow)
	 *
	 * @return     string
	 */
	public function savecite()
	{
		// Incoming
		$cite 		= JRequest::getVar('cite', array(), 'post', 'none', 2);
		$pid  		= JRequest::getInt('pid', 0);
		$version 	= JRequest::getVar('version', 'dev');

		$new  = $cite['id'] ? false : true;

		include_once( JPATH_ROOT . DS . 'administrator' . DS . 'components'
			. DS . 'com_citations' . DS . 'tables' . DS . 'citation.php' );
		include_once( JPATH_ROOT . DS . 'administrator' . DS . 'components'
			. DS . 'com_citations' . DS . 'tables' . DS . 'association.php' );

		if (!$pid || !$cite['type'] || !$cite['title'])
		{
			$this->setError( JText::_('PLG_PROJECTS_PUBLICATIONS_CITATIONS_ERROR_MISSING_REQUIRED'));
		}
		else
		{
			$citation = new CitationsCitation( $this->_database );
			if (!$citation->bind($cite))
			{
				$this->setError($citation->getError());
			}
			else
			{
				$citation->created 		= $new == true ? JFactory::getDate()->toSql() : $citation->created;
				$citation->uid			= $new == true ? $this->_uid : $citation->uid;
				$citation->published	= 1;

				if (!$citation->store(true))
				{
					// This really shouldn't happen.
					$this->setError(JText::_('PLG_PROJECTS_PUBLICATIONS_CITATIONS_ERROR_SAVE'));
				}
			}
			// Create association
			if (!$this->getError() && $new == true && $citation->id)
			{
				$assoc 		 = new CitationsAssociation( $this->_database );
				$assoc->oid  = $pid;
				$assoc->tbl  = 'publication';
				$assoc->type = 'owner';
				$assoc->cid  = $citation->id;

				// Store new content
				if (!$assoc->store())
				{
					$this->setError($assoc->getError());
				}
			}

			$this->_msg = JText::_('PLG_PROJECTS_LINKS_CITATION_SAVED');
		}

		// Pass success or error message
		if ($this->getError())
		{
			$this->_message = array('message' => $this->getError(), 'type' => 'error');
		}
		elseif (isset($this->_msg) && $this->_msg)
		{
			$this->_message = array('message' => $this->_msg, 'type' => 'success');
		}

		// Build pub url
		$route = $this->_project->provisioned
			? 'index.php?option=com_publications' . a . 'task=submit'
			: 'index.php?option=com_projects' . a . 'alias=' . $this->_project->alias
				. a . 'active=publications';
		$url = JRoute::_($route . a . 'pid=' . $pid)
			.'/?version=' . $version . '&section=citations';

		$this->_referer = $url;
		return;
	}

	/**
	 * Remove citation
	 *
	 * @return   boolean
	 */
	public function unattachCitation($pid = 0, $cid = 0, $returnStatus = false)
	{
		include_once( JPATH_ROOT . DS . 'administrator' . DS . 'components'
			. DS . 'com_citations' . DS . 'tables' . DS . 'citation.php' );
		include_once( JPATH_ROOT . DS . 'administrator' . DS . 'components'
			. DS . 'com_citations' . DS . 'tables' . DS . 'association.php' );
		include_once( JPATH_ROOT . DS . 'components' . DS . 'com_citations'
			. DS . 'helpers' . DS . 'format.php' );

		if (!$cid || !$pid)
		{
			$this->setError( JText::_('PLG_PROJECTS_LINKS_NO_DOI') );

			if ($returnStatus)
			{
				$out['error'] = $this->getError();
				return $out;
			}
			return false;
		}

		$database = JFactory::getDBO();
		$c 		  = new CitationsCitation( $database );
		$assoc 	  = new CitationsAssociation($database);

		// Fetch all associations
		$aPubs = $assoc->getRecords(array('cid' => $cid));

		// Remove citation if only one association
		if (count($aPubs) == 1)
		{
			// Delete the citation
			$c->delete($cid);
		}

		// Remove association
		foreach ($aPubs as $aPub)
		{
			if ($aPub->oid == $pid && $aPub->tbl = 'publication')
			{
				$assoc->delete($aPub->id);
			}
		}

		if ($returnStatus)
		{
			$out['success'] = true;
			return $out;
		}

		return true;
	}

	/**
	 * Attach citation
	 *
	 * @return   boolean
	 */
	public function attachCitation($pid = 0, $doi = NULL, $format = 'apa',
		$actor = 0, $returnStatus = false)
	{
		include_once( JPATH_ROOT . DS . 'administrator' . DS . 'components'
			. DS . 'com_citations' . DS . 'tables' . DS . 'citation.php' );
		include_once( JPATH_ROOT . DS . 'administrator' . DS . 'components'
			. DS . 'com_citations' . DS . 'tables' . DS . 'association.php' );
		include_once( JPATH_ROOT . DS . 'administrator' . DS . 'components'
			. DS . 'com_citations' . DS . 'tables' . DS . 'type.php' );
		include_once( JPATH_ROOT . DS . 'components' . DS . 'com_citations'
			. DS . 'helpers' . DS . 'format.php' );

		$out = array('error' => NULL, 'success' => NULL );

		if (!$doi || !$pid)
		{
			$this->setError( JText::_('PLG_PROJECTS_LINKS_NO_DOI') );

			if ($returnStatus)
			{
				$out['error'] = $this->getError();
				return $out;
			}
			return false;
		}

		$database = JFactory::getDBO();
		$c 		  = new CitationsCitation( $database );

		if ($c->loadPubCitation($doi, $pid))
		{
			$this->setError( JText::_('PLG_PROJECTS_LINKS_CITATION_ALREADY_ATTACHED') );

			if ($returnStatus)
			{
				$out['error'] = $this->getError();
				return $out;
			}

			return false;
		}
		else
		{
			// Get DOI preview
			$output = self::parseUrl($doi, true, true, $format);
			$output = json_decode($output);

			if (isset($output->error) && $output->error)
			{
				$this->setError( $output->error );

				if ($returnStatus)
				{
					$out['error'] = $this->getError();
					return $out;
				}

				return false;
			}
			elseif (isset($output->preview) && $output->preview)
			{
				// Load citation record with the same DOI if present
				if (!$c->loadByDoi($doi))
				{
					$c->created 	= JFactory::getDate()->toSql();
					$c->title   	= $doi;
					$c->uid			= $actor;
					$c->affiliated 	= 1;
				}
				$c->formatted 		= $output->preview;
				$c->format			= $format;
				$c->doi				= $doi;

				// Try getting more metadata
				$url = '';
				$data = self::getDoiMetadata($doi, false, $url);

				// Save available data
				if ($data)
				{
					foreach ($c as $key => $value)
					{
						$column = strtolower($key);
						if (isset($data->$column))
						{
							$c->$column = $data->$column;
						}
					}

					// Some extra mapping hacks
					$c->pages = $data->page;

					// Get type ID
					$ct = new CitationsType($database);
					$types = $ct->getType();
					$dType = isset($data->type) ? $data->type : 'article';

					// Hub types don't match library types
					// Trying to match the best we can
					$validTypes = array();
					foreach ($types as $type)
{'fraction_non_alphanumeric': 0.17560192616372391, 'fraction_numerical': 0.002568218298555377, 'mean_word_length': 2.8170183798502384, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 345, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1861147', 'n_tokens_mistral': 11588, 'n_tokens_neox': 9682, 'n_words': 2299}