1<?php
2/**
3 * Joomla! Content Management System
4 *
5 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
6 * @license    GNU General Public License version 2 or later; see LICENSE.txt
7 */
8
9namespace Joomla\CMS\Table;
10
11defined('JPATH_PLATFORM') or die;
12
13use Joomla\CMS\Access\Access;
14use Joomla\CMS\Access\Rules;
15use Joomla\CMS\Application\ApplicationHelper;
16use Joomla\CMS\Table\Observer\Tags;
17use Joomla\CMS\Table\Observer\ContentHistory as ContentHistoryObserver;
18use Joomla\Registry\Registry;
19use Joomla\String\StringHelper;
20
21/**
22 * Content table
23 *
24 * @since       1.5
25 * @deprecated  3.1.4 Class will be removed upon completion of transition to UCM
26 */
27class Content extends Table
28{
29	/**
30	 * Constructor
31	 *
32	 * @param   \JDatabaseDriver  $db  A database connector object
33	 *
34	 * @since   1.5
35	 * @deprecated  3.1.4 Class will be removed upon completion of transition to UCM
36	 */
37	public function __construct(\JDatabaseDriver $db)
38	{
39		parent::__construct('#__content', 'id', $db);
40
41		Tags::createObserver($this, array('typeAlias' => 'com_content.article'));
42		ContentHistoryObserver::createObserver($this, array('typeAlias' => 'com_content.article'));
43
44		// Set the alias since the column is called state
45		$this->setColumnAlias('published', 'state');
46	}
47
48	/**
49	 * Method to compute the default name of the asset.
50	 * The default name is in the form table_name.id
51	 * where id is the value of the primary key of the table.
52	 *
53	 * @return  string
54	 *
55	 * @since   1.6
56	 * @deprecated  3.1.4 Class will be removed upon completion of transition to UCM
57	 */
58	protected function _getAssetName()
59	{
60		$k = $this->_tbl_key;
61
62		return 'com_content.article.' . (int) $this->$k;
63	}
64
65	/**
66	 * Method to return the title to use for the asset table.
67	 *
68	 * @return  string
69	 *
70	 * @since   1.6
71	 * @deprecated  3.1.4 Class will be removed upon completion of transition to UCM
72	 */
73	protected function _getAssetTitle()
74	{
75		return $this->title;
76	}
77
78	/**
79	 * Method to get the parent asset id for the record
80	 *
81	 * @param   Table    $table  A Table object (optional) for the asset parent
82	 * @param   integer  $id     The id (optional) of the content.
83	 *
84	 * @return  integer
85	 *
86	 * @since   1.6
87	 * @deprecated  3.1.4 Class will be removed upon completion of transition to UCM
88	 */
89	protected function _getAssetParentId(Table $table = null, $id = null)
90	{
91		$assetId = null;
92
93		// This is an article under a category.
94		if ($this->catid)
95		{
96			// Build the query to get the asset id for the parent category.
97			$query = $this->_db->getQuery(true)
98				->select($this->_db->quoteName('asset_id'))
99				->from($this->_db->quoteName('#__categories'))
100				->where($this->_db->quoteName('id') . ' = ' . (int) $this->catid);
101
102			// Get the asset id from the database.
103			$this->_db->setQuery($query);
104
105			if ($result = $this->_db->loadResult())
106			{
107				$assetId = (int) $result;
108			}
109		}
110
111		// Return the asset id.
112		if ($assetId)
113		{
114			return $assetId;
115		}
116		else
117		{
118			return parent::_getAssetParentId($table, $id);
119		}
120	}
121
122	/**
123	 * Overloaded bind function
124	 *
125	 * @param   array  $array   Named array
126	 * @param   mixed  $ignore  An optional array or space separated list of properties
127	 *                          to ignore while binding.
128	 *
129	 * @return  mixed  Null if operation was satisfactory, otherwise returns an error string
130	 *
131	 * @see     Table::bind()
132	 * @since   1.6
133	 * @deprecated  3.1.4 Class will be removed upon completion of transition to UCM
134	 */
135	public function bind($array, $ignore = '')
136	{
137		// Search for the {readmore} tag and split the text up accordingly.
138		if (isset($array['articletext']))
139		{
140			$pattern = '#<hr\s+id=("|\')system-readmore("|\')\s*\/*>#i';
141			$tagPos = preg_match($pattern, $array['articletext']);
142
143			if ($tagPos == 0)
144			{
145				$this->introtext = $array['articletext'];
146				$this->fulltext = '';
147			}
148			else
149			{
150				list ($this->introtext, $this->fulltext) = preg_split($pattern, $array['articletext'], 2);
151			}
152		}
153
154		if (isset($array['attribs']) && is_array($array['attribs']))
155		{
156			$registry = new Registry($array['attribs']);
157			$array['attribs'] = (string) $registry;
158		}
159
160		if (isset($array['metadata']) && is_array($array['metadata']))
161		{
162			$registry = new Registry($array['metadata']);
163			$array['metadata'] = (string) $registry;
164		}
165
166		// Bind the rules.
167		if (isset($array['rules']) && is_array($array['rules']))
168		{
169			$rules = new Rules($array['rules']);
170			$this->setRules($rules);
171		}
172
173		return parent::bind($array, $ignore);
174	}
175
176	/**
177	 * Overloaded check function
178	 *
179	 * @return  boolean  True on success, false on failure
180	 *
181	 * @see     Table::check()
182	 * @since   1.5
183	 * @deprecated  3.1.4 Class will be removed upon completion of transition to UCM
184	 */
185	public function check()
186	{
187		if (trim($this->title) == '')
188		{
189			$this->setError(\JText::_('COM_CONTENT_WARNING_PROVIDE_VALID_NAME'));
190
191			return false;
192		}
193
194		if (trim($this->alias) == '')
195		{
196			$this->alias = $this->title;
197		}
198
199		$this->alias = ApplicationHelper::stringURLSafe($this->alias, $this->language);
200
201		if (trim(str_replace('-', '', $this->alias)) == '')
202		{
203			$this->alias = \JFactory::getDate()->format('Y-m-d-H-i-s');
204		}
205
206		if (trim(str_replace('&nbsp;', '', $this->fulltext)) == '')
207		{
208			$this->fulltext = '';
209		}
210
211		/**
212		 * Ensure any new items have compulsory fields set. This is needed for things like
213		 * frontend editing where we don't show all the fields or using some kind of API
214		 */
215		if (!$this->id)
216		{
217			// Images can be an empty json string
218			if (!isset($this->images))
219			{
220				$this->images = '{}';
221			}
222
223			// URLs can be an empty json string
224			if (!isset($this->urls))
225			{
226				$this->urls = '{}';
227			}
228
229			// Attributes (article params) can be an empty json string
230			if (!isset($this->attribs))
231			{
232				$this->attribs = '{}';
233			}
234
235			// Metadata can be an empty json string
236			if (!isset($this->metadata))
237			{
238				$this->metadata = '{}';
239			}
240		}
241
242		// Check the publish down date is not earlier than publish up.
243		if ($this->publish_down < $this->publish_up && $this->publish_down > $this->_db->getNullDate())
244		{
245			// Swap the dates.
246			$temp = $this->publish_up;
247			$this->publish_up = $this->publish_down;
248			$this->publish_down = $temp;
249		}
250
251		// Clean up keywords -- eliminate extra spaces between phrases
252		// and cr (\r) and lf (\n) characters from string
253		if (!empty($this->metakey))
254		{
255			// Only process if not empty
256
257			// Array of characters to remove
258			$bad_characters = array("\n", "\r", "\"", '<', '>');
259
260			// Remove bad characters
261			$after_clean = StringHelper::str_ireplace($bad_characters, '', $this->metakey);
262
263			// Create array using commas as delimiter
264			$keys = explode(',', $after_clean);
265
266			$clean_keys = array();
267
268			foreach ($keys as $key)
269			{
270				if (trim($key))
271				{
272					// Ignore blank keywords
273					$clean_keys[] = trim($key);
274				}
275			}
276
277			// Put array back together delimited by ", "
278			$this->metakey = implode(', ', $clean_keys);
279		}
280
281		return true;
282	}
283
284	/**
285	 * Gets the default asset values for a component.
286	 *
287	 * @param   string  $component  The component asset name to search for
288	 *
289	 * @return  Rules  The Rules object for the asset
290	 *
291	 * @since   3.4
292	 * @deprecated  3.4 Class will be removed upon completion of transition to UCM
293	 */
294	protected function getDefaultAssetValues($component)
295	{
296		// Need to find the asset id by the name of the component.
297		$db = $this->getDbo();
298		$query = $db->getQuery(true)
299			->select($db->quoteName('id'))
300			->from($db->quoteName('#__assets'))
301			->where($db->quoteName('name') . ' = ' . $db->quote($component));
302		$db->setQuery($query);
303		$assetId = (int) $db->loadResult();
304
305		return Access::getAssetRules($assetId);
306	}
307
308	/**
309	 * Overrides Table::store to set modified data and user id.
310	 *
311	 * @param   boolean  $updateNulls  True to update fields even if they are null.
312	 *
313	 * @return  boolean  True on success.
314	 *
315	 * @since   1.6
316	 * @deprecated  3.1.4 Class will be removed upon completion of transition to UCM
317	 */
318	public function store($updateNulls = false)
319	{
320		$date = \JFactory::getDate();
321		$user = \JFactory::getUser();
322
323		$this->modified = $date->toSql();
324
325		if ($this->id)
326		{
327			// Existing item
328			$this->modified_by = $user->get('id');
329		}
330		else
331		{
332			// New article. An article created and created_by field can be set by the user,
333			// so we don't touch either of these if they are set.
334			if (!(int) $this->created)
335			{
336				$this->created = $date->toSql();
337			}
338
339			if (empty($this->created_by))
340			{
341				$this->created_by = $user->get('id');
342			}
343		}
344
345		// Verify that the alias is unique
346		$table = Table::getInstance('Content', 'JTable', array('dbo' => $this->getDbo()));
347
348		if ($table->load(array('alias' => $this->alias, 'catid' => $this->catid)) && ($table->id != $this->id || $this->id == 0))
349		{
350			$this->setError(\JText::_('JLIB_DATABASE_ERROR_ARTICLE_UNIQUE_ALIAS'));
351
352			return false;
353		}
354
355		return parent::store($updateNulls);
356	}
357}
358