├── README.md ├── com_mywalks ├── admin │ ├── access.xml │ ├── config.xml │ ├── forms │ │ ├── filter_mywalk_dates.xml │ │ ├── filter_mywalks.xml │ │ ├── mywalk.xml │ │ └── mywalk_date.xml │ ├── language │ │ └── en-GB │ │ │ ├── com_mywalks.ini │ │ │ └── com_mywalks.sys.ini │ ├── services │ │ └── provider.php │ ├── sql │ │ ├── install.mysql.sql │ │ └── uninstall.mysql.sql │ ├── src │ │ ├── Controller │ │ │ ├── DisplayController.php │ │ │ ├── MywalkController.php │ │ │ ├── Mywalk_dateController.php │ │ │ ├── Mywalk_datesController.php │ │ │ └── MywalksController.php │ │ ├── Extension │ │ │ └── MywalksComponent.php │ │ ├── Helper │ │ │ └── MywalksHelper.php │ │ ├── Model │ │ │ ├── MywalkModel.php │ │ │ ├── Mywalk_dateModel.php │ │ │ ├── Mywalk_datesModel.php │ │ │ └── MywalksModel.php │ │ ├── Table │ │ │ ├── Mywalk_datesTable.php │ │ │ └── MywalksTable.php │ │ └── View │ │ │ ├── Mywalk │ │ │ └── HtmlView.php │ │ │ ├── Mywalk_date │ │ │ └── HtmlView.php │ │ │ ├── Mywalk_dates │ │ │ └── HtmlView.php │ │ │ └── Mywalks │ │ │ └── HtmlView.php │ └── tmpl │ │ ├── mywalk │ │ └── edit.php │ │ ├── mywalk_date │ │ └── edit.php │ │ ├── mywalk_dates │ │ └── default.php │ │ └── mywalks │ │ └── default.php ├── mywalks.xml └── site │ ├── forms │ └── filter_mywalks.xml │ ├── language │ └── en-GB │ │ └── com_mywalks.ini │ ├── src │ ├── Controller │ │ └── DisplayController.php │ ├── Helper │ │ └── RouteHelper.php │ ├── Model │ │ ├── MywalkModel.php │ │ └── MywalksModel.php │ ├── Service │ │ ├── MywalksNomenuRules.php │ │ └── Router.php │ └── View │ │ ├── Mywalk │ │ └── HtmlView.php │ │ └── Mywalks │ │ └── HtmlView.php │ └── tmpl │ ├── mywalk │ └── default.php │ └── mywalks │ ├── default.php │ └── default.xml └── resources ├── mywalks-admin-walk-edit-details.jpg ├── mywalks-admin-walks-list.jpg ├── mywalks-site-walk-dates-list.jpg └── mywalks-site-walks-list.jpg /README.md: -------------------------------------------------------------------------------- 1 | # Joomla 4x Example Component and Tutorial - Mywalks 2 | 3 | A component prepared in 2019 at the Joomla 4.0 Alpha stage for 4 | developer demonstration and tutorial purposes. Updated in 2023 5 | at the 4.3.1 stage with bug fixes and improvements. The component 6 | manages and displays a list of walks. 7 | 8 | This is not intended to be a Production component. 9 | 10 | ### Prerequisites 11 | 12 | Joomla 4. It should not install or work on earlier Joomla versions. 13 | 14 | ### Installing 15 | 16 | Download the zip file and install it in Joomla 4. The initial 17 | installation may show the success message as an all capitals 18 | string key. Just look for the Mywalks menu item under Components 19 | in the Joomla Administrator menu. 20 | 21 | ### Documentation 22 | 23 | The **Wiki** contains two tutorial explanations of what this component does and how it works. Part 1 deals with the Site code and the essential Administrator code to make the site work with sample Walk data. Part 2 deals with the Administrator code. The parts can be taken in any order. 24 | 25 | ## Author 26 | 27 | * **Clifford E Ford** 28 | 29 | ## License 30 | 31 | This project is licensed under the [GPL3 License](http://www.gnu.org/licenses/gpl-3.0.html) 32 | 33 | ## Acknowledgments 34 | 35 | * The Joomla 4 Project Team 36 | 37 | -------------------------------------------------------------------------------- /com_mywalks/admin/access.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 | -------------------------------------------------------------------------------- /com_mywalks/admin/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 |
9 | 10 | 17 | 18 | 19 | 20 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 42 | 43 | 44 | 45 | 46 |
47 | 48 |
53 | 54 | 60 | 61 | 62 | 63 | 64 | 65 | 73 | 74 | 75 | 76 | 77 |
78 | 79 |
84 | 85 | 90 | 91 | 99 | 100 | 101 | 102 | 103 |
104 | 105 |
110 | 119 |
120 |
121 | -------------------------------------------------------------------------------- /com_mywalks/admin/forms/filter_mywalk_dates.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 6 | 13 | 14 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 50 | 51 |
52 | -------------------------------------------------------------------------------- /com_mywalks/admin/forms/filter_mywalks.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 6 | 13 | 14 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 50 | 51 |
52 | -------------------------------------------------------------------------------- /com_mywalks/admin/forms/mywalk.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 | 6 | 14 | 15 | 22 | 23 | 31 | 32 | 38 | 39 | 47 | 48 | 49 | 50 | 51 | 52 | 53 |
54 | 55 |
56 | 60 | 61 | 62 | 63 | 64 | 70 | 71 | 72 | 73 | 74 | 80 | 81 | 82 | 83 |
84 | 85 |
86 | 87 | 92 | 93 | 99 | 100 | 106 | 107 | 113 |
114 | 115 |
116 | -------------------------------------------------------------------------------- /com_mywalks/admin/forms/mywalk_date.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 | 13 | 14 | 20 | 21 | 27 | 28 | 36 | 37 | 45 | 46 | 47 | 48 | 49 | 50 | 51 |
52 |
53 | -------------------------------------------------------------------------------- /com_mywalks/admin/language/en-GB/com_mywalks.ini: -------------------------------------------------------------------------------- 1 | COM_MYWALKS_ERROR_WALK_NOT_FOUND="Walk not found!" 2 | COM_MYWALKS_MYWALK_DATE_ADD_VISIT="Add Walk Visit" 3 | COM_MYWALKS_MYWALK_DATE_EDIT_VISIT="Edit Walk Visit" 4 | COM_MYWALKS_MYWALK_DATE_LABEL_DATE="Date" 5 | COM_MYWALKS_MYWALK_DATE_LABEL_ID="ID" 6 | COM_MYWALKS_MYWALK_DATE_LABEL_WALK_ID="Walk ID" 7 | COM_MYWALKS_MYWALK_DATE_LABEL_WEATHER="Weather" 8 | COM_MYWALKS_MYWALK_DATE_PAGE_TITLE_ADD="Mywalks - Add Visit" 9 | COM_MYWALKS_MYWALK_DATE_PAGE_TITLE_EDIT="Mywalks - Edit Visit" 10 | COM_MYWALKS_MYWALK_DATE_TAB_DETAILS="Details" 11 | COM_MYWALKS_MYWALK_DATES_FILTER_DESC_SEARCH="Search in Weather Report" 12 | COM_MYWALKS_MYWALK_DATES_FILTER_LABEL_SEARCH="Search" 13 | COM_MYWALKS_MYWALK_DATES_LABEL_VISIT_DATE='Visit Date' 14 | COM_MYWALKS_MYWALK_DATES_LABEL_WEATHER_REPORT="Weather Report" 15 | COM_MYWALKS_MYWALK_DATES_PAGE_TITLE="Mywalks - List of Visit Dates" 16 | COM_MYWALKS_MYWALK_DATES_PAGE_TOP="List of Visit Dates for Walk" 17 | COM_MYWALKS_MYWALK_DATES_TABLE_CAPTION="List of Visit Dates" 18 | COM_MYWALKS_MYWALK_LABEL_BOGS="Bogs" 19 | COM_MYWALKS_MYWALK_LABEL_CAFE="Cafe" 20 | COM_MYWALKS_MYWALK_LABEL_DESCRIPTION="Description" 21 | COM_MYWALKS_MYWALK_LABEL_DISTANCE="Distance in Km" 22 | COM_MYWALKS_MYWALK_LABEL_PICTURE_ALT="Alt text" 23 | COM_MYWALKS_MYWALK_LABEL_PICTURE_HEIGHT="Heigh" 24 | COM_MYWALKS_MYWALK_LABEL_PICTURE_URL="Picture URL" 25 | COM_MYWALKS_MYWALK_LABEL_PICTURE_WIDTH="Width" 26 | COM_MYWALKS_MYWALK_LABEL_TITLE="Title" 27 | COM_MYWALKS_MYWALK_LABEL_TOILETS="Toilets" 28 | COM_MYWALKS_MYWALK_PAGE_TITLE_ADD_WALK="Mywalks - Add Walk" 29 | COM_MYWALKS_MYWALK_PAGE_TITLE_EDIT_WALK="Mywalks - Edit Walk" 30 | COM_MYWALKS_MYWALK_TAB_DETAILS="Details" 31 | COM_MYWALKS_MYWALK_TAB_OPTIONS="Options" 32 | COM_MYWALKS_MYWALK_TAB_PICTURE="Picture" 33 | COM_MYWALKS_MYWALKS_FILTER_SEARCH_TITLE_DESC="Search in Title" 34 | COM_MYWALKS_MYWALKS_LABEL_BOGS="Bogs" 35 | COM_MYWALKS_MYWALKS_LABEL_CAFE="Cafe" 36 | COM_MYWALKS_MYWALKS_LABEL_DESCRIPTION="Description" 37 | COM_MYWALKS_MYWALKS_LABEL_DISTANCE="Distance" 38 | COM_MYWALKS_MYWALKS_LABEL_HILLS="Hills" 39 | COM_MYWALKS_MYWALKS_LABEL_NVISITS="nVisits" 40 | COM_MYWALKS_MYWALKS_LABEL_TOILETS="Toilets" 41 | COM_MYWALKS_MYWALKS_PAGE_TITLE="Mywalks - list of Walks" 42 | COM_MYWALKS_MYWALKS_TABLE_CAPTION="List of Walks" 43 | COM_MYWALKS_N_ITEMS_ARCHIVED="%s Items Archived" 44 | COM_MYWALKS_N_ITEMS_DELETED="%s Items Deleted" 45 | COM_MYWALKS_N_ITEMS_PUBLISHED="%s Items Published" 46 | COM_MYWALKS_N_ITEMS_TRASHED="%s Items Trashed" 47 | COM_MYWALKS_N_ITEMS_UNPUBLISHED="%s Items Unpublished" 48 | COM_MYWALKS_WALK_BACK_TO_WALKS="Back to list of walks" 49 | -------------------------------------------------------------------------------- /com_mywalks/admin/language/en-GB/com_mywalks.sys.ini: -------------------------------------------------------------------------------- 1 | COM_MYWALKS_CONFIG_INTEGRATION_SETTINGS_DESC="These settings determine how the Mywalks Component will integrate with other extensions." 2 | COM_MYWALKS_CONFIG_LIST_SETTINGS_DESC="These settings apply for List Layouts Options unless they are changed for a specific menu item or category." 3 | COM_MYWALKS_CONFIGURATION="Mywalks: Options" 4 | COM_MYWALKS_MYWALKS_VIEW_DEFAULT_DESC="Displays a list of walks." 5 | COM_MYWALKS_MYWALKS_VIEW_DEFAULT_OPTION="Default" 6 | COM_MYWALKS_MYWALKS_VIEW_DEFAULT_TITLE="List of Walks" 7 | COM_MYWALKS_SHARED_DESC="These settings apply for Shared Options in List, Blog and Featured unless they are changed by the menu settings." 8 | COM_MYWALKS_SHARED_LABEL="Shared" 9 | COM_MYWALKS_XML_DESCRIPTION="Displays a list of walks with dates visited" 10 | COM_MYWALKS="Mywalks" 11 | -------------------------------------------------------------------------------- /com_mywalks/admin/services/provider.php: -------------------------------------------------------------------------------- 1 | registerServiceProvider(new CategoryFactory('\\J4xdemos\\Component\\Mywalks')); 45 | $container->registerServiceProvider(new MVCFactory('\\J4xdemos\\Component\\Mywalks')); 46 | $container->registerServiceProvider(new ComponentDispatcherFactory('\\J4xdemos\\Component\\Mywalks')); 47 | $container->registerServiceProvider(new RouterFactory('\\J4xdemos\\Component\\Mywalks')); 48 | $container->set( 49 | ComponentInterface::class, 50 | function (Container $container) 51 | { 52 | $component = new MywalksComponent($container->get(ComponentDispatcherFactoryInterface::class)); 53 | 54 | $component->setRegistry($container->get(Registry::class)); 55 | $component->setMVCFactory($container->get(MVCFactoryInterface::class)); 56 | // $component->setCategoryFactory($container->get(CategoryFactoryInterface::class)); 57 | $component->setRouterFactory($container->get(RouterFactoryInterface::class)); 58 | 59 | return $component; 60 | } 61 | ); 62 | } 63 | }; 64 | -------------------------------------------------------------------------------- /com_mywalks/admin/sql/install.mysql.sql: -------------------------------------------------------------------------------- 1 | 2 | -- 3 | -- Table structure for table `#__mywalks` 4 | -- 5 | 6 | CREATE TABLE IF NOT EXISTS `#__mywalks` ( 7 | `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, 8 | `title` varchar(64) NOT NULL, 9 | `description` text NOT NULL, 10 | `distance` decimal(10,0) NOT NULL, 11 | `toilets` tinyint(1) NOT NULL DEFAULT '0', 12 | `cafe` tinyint(1) NOT NULL DEFAULT '0', 13 | `hills` int(11) NOT NULL DEFAULT '0', 14 | `bogs` int(11) NOT NULL DEFAULT '0', 15 | `picture` varchar(128) DEFAULT NULL, 16 | `width` int(11) DEFAULT NULL, 17 | `height` int(11) DEFAULT NULL, 18 | `alt` varchar(64) DEFAULT NULL, 19 | `state` TINYINT NOT NULL DEFAULT '1' 20 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci; 21 | 22 | -- 23 | -- Dumping data for table `#__mywalks` 24 | -- 25 | 26 | INSERT IGNORE INTO `#__mywalks` (`id`, `title`, `description`, `distance`, `toilets`, `cafe`, `hills`, `bogs`, `picture`, `width`, `height`, `alt`) VALUES 27 | (1, 'City Centre', 'Highligts of Anycity', '5', 1, 1, 0, 0, NULL, NULL, NULL, ''), 28 | (2, 'Woods', 'Woodland walk on hard paths', '4', 0, 0, 1, 1, NULL, NULL, NULL, ''), 29 | (3, 'Hills', 'Hill walk with good views on established path.', '6', 0, 0, 3, 2, NULL, NULL, NULL, ''), 30 | (4, 'Lake Thingy', 'Walk around the lake on an accessible path.', '2', 1, 1, 0, 0, NULL, NULL, NULL, ''), 31 | (5, 'Castle Railway Track', 'Walk along the line of the old railway track from start point car park to Thing castle', '2', 1, 1, 0, 0, NULL, NULL, NULL, ''); 32 | 33 | -- -------------------------------------------------------- 34 | 35 | -- 36 | -- Table structure for table `#__mywalk_dates` 37 | -- 38 | 39 | CREATE TABLE IF NOT EXISTS `#__mywalk_dates` ( 40 | `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, 41 | `walk_id` int(11) NOT NULL, 42 | `date` date NOT NULL, 43 | `weather` varchar(256) DEFAULT NULL, 44 | `state` TINYINT NOT NULL DEFAULT '1', 45 | KEY `idx_walk` (`walk_id`) 46 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci; 47 | 48 | -- 49 | -- Dumping data for table `#__mywalk_dates` 50 | -- 51 | 52 | INSERT IGNORE INTO `#__mywalk_dates` (`id`, `walk_id`, `date`, `weather`) VALUES 53 | (1, 1, '2019-05-12', 'Dry and Sunny'), 54 | (2, 2, '2019-06-09', 'Wet and Windy'), 55 | (3, 3, '2019-01-01', 'Cold and wet'), 56 | (4, 4, '2019-01-20', 'Bright but frosty'), 57 | (5, 5, '2019-04-28', 'Dry and warm'), 58 | (6, 1, '2019-05-12', 'Wet and windy'), 59 | (7, 3, '2019-06-09', 'Hot and dry'), 60 | (8, 5, '2019-07-21', 'Overcast but warm and humid'); 61 | -------------------------------------------------------------------------------- /com_mywalks/admin/sql/uninstall.mysql.sql: -------------------------------------------------------------------------------- 1 | -- best to drop tables manually in case data is lost 2 | DROP TABLE IF EXISTS `#__mywalks`; 3 | DROP TABLE IF EXISTS `#__mywalk_dates`; 4 | 5 | -------------------------------------------------------------------------------- /com_mywalks/admin/src/Controller/DisplayController.php: -------------------------------------------------------------------------------- 1 | setRedirect('index.php?option=com_mywalks&view=mywalk_dates'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /com_mywalks/admin/src/Controller/Mywalk_datesController.php: -------------------------------------------------------------------------------- 1 | input->get('view', $this->default_view); 44 | $layout = $this->input->get('layout', 'default'); 45 | $id = $this->input->getInt('id'); 46 | 47 | // Check for edit form. 48 | if ($view == 'mywalk_date' && $layout == 'edit' && !$this->checkEditId('com_mywalks.edit.mywalk_date', $id)) 49 | { 50 | // Somehow the person just went to the form - we don't allow that. 51 | $this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id), 'error'); 52 | $this->setRedirect(Route::_('index.php?option=com_mywalk&view=mywalk_datess', false)); 53 | 54 | return false; 55 | } 56 | 57 | return parent::display(); 58 | } 59 | 60 | /** 61 | * Proxy for getModel. 62 | * 63 | * @param string $name The model name. Optional. 64 | * @param string $prefix The class prefix. Optional. 65 | * @param array $config The array of possible config values. Optional. 66 | * 67 | * @return \Joomla\CMS\MVC\Model\BaseDatabaseModel 68 | * 69 | * @since 1.6 70 | */ 71 | public function getModel($name = 'Mywalk_date', $prefix = 'Administrator', $config = array('ignore_request' => true)) 72 | { 73 | return parent::getModel($name, $prefix, $config); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /com_mywalks/admin/src/Controller/MywalksController.php: -------------------------------------------------------------------------------- 1 | true)) 35 | { 36 | return parent::getModel($name, $prefix, $config); 37 | } 38 | } -------------------------------------------------------------------------------- /com_mywalks/admin/src/Extension/MywalksComponent.php: -------------------------------------------------------------------------------- 1 | getRegistry()->register('mywalksadministrator', new AdministratorService); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /com_mywalks/admin/src/Helper/MywalksHelper.php: -------------------------------------------------------------------------------- 1 | getQuery(true); 33 | $query->select($db->quoteName('title')) 34 | ->from($db->quoteName('#__mywalks')) 35 | ->where('id = :id') 36 | ->bind(':id', $id, ParameterType::INTEGER); 37 | $db->setQuery($query); 38 | return $db->loadObject(); 39 | } 40 | } -------------------------------------------------------------------------------- /com_mywalks/admin/src/Model/MywalkModel.php: -------------------------------------------------------------------------------- 1 | id)) 49 | { 50 | return $this->getCurrentUser()->authorise('core.delete', 'com_mywalks.mywalks.' . (int) $record->id); 51 | } 52 | 53 | return false; 54 | } 55 | 56 | /** 57 | * Method to test whether a record can have its state edited. 58 | * 59 | * @param object $record A record object. 60 | * 61 | * @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component. 62 | * 63 | * @since 1.6 64 | */ 65 | protected function canEditState($record) 66 | { 67 | // Check for existing article. 68 | if (!empty($record->id)) 69 | { 70 | return $this->getCurrentUser()->authorise('core.edit.state', 'com_mywalks.mywalks.' . (int) $record->id); 71 | } 72 | 73 | // Default to component settings if neither article nor category known. 74 | return parent::canEditState($record); 75 | } 76 | 77 | /** 78 | * Method to get a table object, load it if necessary. 79 | * 80 | * @param string $name The table name. Optional. 81 | * @param string $prefix The class prefix. Optional. 82 | * @param array $options Configuration array for model. Optional. 83 | * 84 | * @return Table A Table object 85 | * 86 | * @since 3.0 87 | * @throws \Exception 88 | */ 89 | public function getTable($name = '', $prefix = '', $options = array()) 90 | { 91 | $name = 'mywalks'; 92 | $prefix = 'Table'; 93 | 94 | if ($table = $this->_createTable($name, $prefix, $options)) 95 | { 96 | return $table; 97 | } 98 | 99 | throw new \Exception(Text::sprintf('JLIB_APPLICATION_ERROR_TABLE_NAME_NOT_SUPPORTED', $name), 0); 100 | } 101 | 102 | 103 | /** 104 | * Method to get the record form. 105 | * 106 | * @param array $data Data for the form. 107 | * @param boolean $loadData True if the form is to load its own data (default case), false if not. 108 | * 109 | * @return Form|boolean A Form object on success, false on failure 110 | * 111 | * @since 1.6 112 | */ 113 | public function getForm($data = array(), $loadData = true) 114 | { 115 | // Get the form. 116 | $form = $this->loadForm('com_mywalks.mywalk', 'mywalk', array('control' => 'jform', 'load_data' => $loadData)); 117 | 118 | if (empty($form)) 119 | { 120 | return false; 121 | } 122 | 123 | return $form; 124 | } 125 | 126 | /** 127 | * Method to get the data that should be injected in the form. 128 | * 129 | * @return mixed The data for the form. 130 | * 131 | * @since 1.6 132 | */ 133 | protected function loadFormData() 134 | { 135 | // Check the session for previously entered form data. 136 | $app = Factory::getApplication(); 137 | $data = $app->getUserState('com_mywalks.edit.mywalk.data', array()); 138 | 139 | if (empty($data)) 140 | { 141 | $data = $this->getItem(); 142 | 143 | // Pre-select some filters (Status, Category, Language, Access) in edit form if those have been selected in Article Manager: Articles 144 | } 145 | 146 | $this->preprocessData('com_mywalks.mywalk', $data); 147 | 148 | return $data; 149 | } 150 | 151 | /** 152 | * Method to change the published state of one or more records. 153 | * 154 | * @param array &$pks A list of the primary keys to change. 155 | * @param integer $value The value of the published state. 156 | * 157 | * @return boolean True on success. 158 | * 159 | * @since 4.0.0 160 | */ 161 | public function publish(&$pks, $value = 1) { 162 | /* this is a very simple method to change the state of each item selected */ 163 | $db = $this->getDatabase(); 164 | 165 | $query = $db->getQuery(true); 166 | 167 | $query->update($db->quoteName('#__mywalks')) 168 | ->set($db->quoteName('state') . ' = :value') 169 | ->bind(':value', $value , ParameterType::INTEGER) 170 | ->whereIn($db->quoteName('id'), $pks); 171 | $db->setQuery($query); 172 | $db->execute(); 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /com_mywalks/admin/src/Model/Mywalk_dateModel.php: -------------------------------------------------------------------------------- 1 | id)) 52 | { 53 | return $this->getCurrentUser()->authorise('core.delete', 'com_mywalks.mywalks.' . (int) $record->id); 54 | } 55 | 56 | return false; 57 | } 58 | 59 | /** 60 | * Method to test whether a record can have its state edited. 61 | * 62 | * @param object $record A record object. 63 | * 64 | * @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component. 65 | * 66 | * @since 1.6 67 | */ 68 | protected function canEditState($record) 69 | { 70 | // Check for existing article. 71 | if (!empty($record->id)) 72 | { 73 | return $this->getCurrentUser()->authorise('core.edit.state', 'com_mywalks.mywalks.' . (int) $record->id); 74 | } 75 | 76 | // Default to component settings if neither article nor category known. 77 | return parent::canEditState($record); 78 | } 79 | 80 | /** 81 | * Method to get a table object, load it if necessary. 82 | * 83 | * @param string $name The table name. Optional. 84 | * @param string $prefix The class prefix. Optional. 85 | * @param array $options Configuration array for model. Optional. 86 | * 87 | * @return Table A Table object 88 | * 89 | * @since 3.0 90 | * @throws \Exception 91 | */ 92 | public function getTable($name = '', $prefix = '', $options = array()) 93 | { 94 | $name = 'mywalk_dates'; 95 | $prefix = 'Table'; 96 | 97 | if ($table = $this->_createTable($name, $prefix, $options)) 98 | { 99 | return $table; 100 | } 101 | 102 | throw new \Exception(Text::sprintf('JLIB_APPLICATION_ERROR_TABLE_NAME_NOT_SUPPORTED', $name), 0); 103 | } 104 | 105 | /** 106 | * Method to change the published state of one or more records. 107 | * 108 | * @param array &$pks A list of the primary keys to change. 109 | * @param integer $value The value of the published state. 110 | * 111 | * @return boolean True on success. 112 | * 113 | * @since 4.0.0 114 | */ 115 | public function publish(&$pks, $value = 1) { 116 | /* this is a very simple method to change the state of each item selected */ 117 | $db = $this->getDatabase(); 118 | 119 | $query = $db->getQuery(true); 120 | 121 | $query->update($db->quoteName('#__mywalk_dates')) 122 | ->set($db->quoteName('state') . ' = :state') 123 | ->bind(':state', $state, ParameterType::INTEGER) 124 | ->whereIN($db->quoteName('id'), $pks); 125 | $db->setQuery($query); 126 | $db->execute(); 127 | } 128 | 129 | /** 130 | * Method to get the record form. 131 | * 132 | * @param array $data Data for the form. 133 | * @param boolean $loadData True if the form is to load its own data (default case), false if not. 134 | * 135 | * @return Form|boolean A Form object on success, false on failure 136 | * 137 | * @since 1.6 138 | */ 139 | public function getForm($data = array(), $loadData = true) 140 | { 141 | // Get the form. 142 | $form = $this->loadForm('com_mywalks.mywalk_date', 'mywalk_date', array('control' => 'jform', 'load_data' => $loadData)); 143 | 144 | if (empty($form)) 145 | { 146 | return false; 147 | } 148 | 149 | return $form; 150 | } 151 | 152 | /** 153 | * Method to get the data that should be injected in the form. 154 | * 155 | * @return mixed The data for the form. 156 | * 157 | * @since 1.6 158 | */ 159 | protected function loadFormData() 160 | { 161 | // Check the session for previously entered form data. 162 | $app = Factory::getApplication(); 163 | $data = $app->getUserState('com_mywalks.edit.mywalk_date.data', array()); 164 | 165 | if (empty($data)) 166 | { 167 | $data = $this->getItem(); 168 | 169 | // Pre-select some filters (Status, Category, Language, Access) in edit form if those have been selected in Article Manager: Articles 170 | } 171 | 172 | $this->preprocessData('com_mywalks.mywalk_date', $data); 173 | 174 | return $data; 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /com_mywalks/admin/src/Model/Mywalk_datesModel.php: -------------------------------------------------------------------------------- 1 | input->get('walk_id', 0, 'int'); 73 | if (empty($walk_id)) { 74 | $walk_id = $app->getUserState('com_mywalks.walk_id'); 75 | } 76 | $this->setState('walk_id', $walk_id); 77 | // keep the walk_id for adding new visits 78 | $app->setUserState('com_mywalks.walk_id', $walk_id); 79 | 80 | $search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search'); 81 | $this->setState('filter.search', $search); 82 | 83 | $published = $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', ''); 84 | $this->setState('filter.published', $published); 85 | 86 | // List state information. 87 | parent::populateState($ordering, $direction); 88 | } 89 | 90 | /** 91 | * Method to get a store id based on model configuration state. 92 | * 93 | * This is necessary because the model is used by the component and 94 | * different modules that might need different sets of data or different 95 | * ordering requirements. 96 | * 97 | * @param string $id A prefix for the store id. 98 | * 99 | * @return string A store id. 100 | * 101 | * @since 1.6 102 | */ 103 | protected function getStoreId($id = '') 104 | { 105 | // Compile the store id. 106 | $id .= ':' . $this->getState('filter.search'); 107 | $id .= ':' . $this->getState('filter.published'); 108 | 109 | return parent::getStoreId($id); 110 | } 111 | 112 | /** 113 | * Build an SQL query to load the list data. 114 | * 115 | * @return \Joomla\Database\DatabaseQuery 116 | * 117 | * @since 1.6 118 | */ 119 | protected function getListQuery() 120 | { 121 | // Create a new query object. 122 | $db = $this->getDatabase(); 123 | $query = $db->getQuery(true); 124 | 125 | // Select the required fields from the table. 126 | $query->select( 127 | $this->getState( 128 | 'list.select', 129 | 'a.*' 130 | ) 131 | ); 132 | $query->from($db->quoteName('#__mywalk_dates') . ' AS a'); 133 | 134 | // the walk id should be passed in url or hidden form variables 135 | $walk_id = $this->getState('walk_id'); 136 | $query->where($db->quoteName('a.walk_id') . ' = :walk_id') 137 | ->bind(':walk_id', $walk_id, ParameterType::INTEGER); 138 | 139 | // Filter by published state 140 | $published = (string) $this->getState('filter.published'); 141 | 142 | if (is_numeric($published)) 143 | { 144 | $query->where($db->quoteName('a.state') . ' = :published'); 145 | $query->bind(':published', $published, ParameterType::INTEGER); 146 | } 147 | elseif ($published === '') 148 | { 149 | $query->whereIn($db->quoteName('a.state'), array(0, 1)); 150 | } 151 | 152 | // Filter by search in date. 153 | $search = $this->getState('filter.search'); 154 | 155 | if (!empty($search)) 156 | { 157 | $search = '%' . trim($search) . '%'; 158 | $query->where($db->quoteName('a.weather') . ' LIKE :search') 159 | ->bind(':search', $search, ParameterType::STRING); 160 | } 161 | 162 | // Add the list ordering clause. 163 | $orderCol = $this->state->get('list.ordering', 'a.id'); 164 | $orderDirn = $this->state->get('list.direction', 'ASC'); 165 | 166 | if ($orderCol === 'date') { 167 | $ordering = [ 168 | $db->quoteName('a.date') . ' ' . $db->escape($orderDirn), 169 | ]; 170 | } else { 171 | $ordering = $db->escape($orderCol) . ' ' . $db->escape($orderDirn); 172 | } 173 | 174 | $query->order($ordering); 175 | return $query; 176 | } 177 | 178 | /** 179 | * Method to get a list of walks. 180 | * Overridden to add a check for access levels. 181 | * 182 | * @return mixed An array of data items on success, false on failure. 183 | * 184 | * @since 4.0.0 185 | */ 186 | public function getItems() 187 | { 188 | $items = parent::getItems(); 189 | 190 | return $items; 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /com_mywalks/admin/src/Model/MywalksModel.php: -------------------------------------------------------------------------------- 1 | getUserStateFromRequest($this->context . '.filter.search', 'filter_search'); 68 | $this->setState('filter.search', $search); 69 | 70 | $published = $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', ''); 71 | $this->setState('filter.published', $published); 72 | 73 | // List state information. 74 | parent::populateState($ordering, $direction); 75 | } 76 | 77 | /** 78 | * Method to get a store id based on model configuration state. 79 | * 80 | * This is necessary because the model is used by the component and 81 | * different modules that might need different sets of data or different 82 | * ordering requirements. 83 | * 84 | * @param string $id A prefix for the store id. 85 | * 86 | * @return string A store id. 87 | * 88 | * @since 1.6 89 | */ 90 | protected function getStoreId($id = '') 91 | { 92 | // Compile the store id. 93 | $id .= ':' . $this->getState('filter.search'); 94 | $id .= ':' . $this->getState('filter.published'); 95 | 96 | return parent::getStoreId($id); 97 | } 98 | 99 | /** 100 | * Build an SQL query to load the list data. 101 | * 102 | * @return \Joomla\Database\DatabaseQuery 103 | * 104 | * @since 1.6 105 | */ 106 | protected function getListQuery() 107 | { 108 | // Create a new query object. 109 | $db = $this->getDatabase(); 110 | $query = $db->getQuery(true); 111 | 112 | // Select the required fields from the table. 113 | $query->select( 114 | $this->getState( 115 | 'list.select', 116 | 'a.*, (SELECT count(' 117 | . $db->quoteName('date') 118 | . ') FROM ' . $db->quoteName('#__mywalk_dates') 119 | . ' WHERE walk_id = a.id) AS nvisits' 120 | ) 121 | ); 122 | $query->from($db->quoteName('#__mywalks') . ' AS a'); 123 | 124 | // Filter by published state 125 | $published = (string) $this->getState('filter.published'); 126 | 127 | if (is_numeric($published)) 128 | { 129 | $query->where($db->quoteName('a.state') . ' = :published') 130 | ->bind(':published', $published, ParameterType::INTEGER); 131 | } 132 | elseif ($published === '') 133 | { 134 | $query->whereIn($db->quoteName('a.state'), array(0, 1)); 135 | } 136 | 137 | // Filter by search in title. 138 | $search = $this->getState('filter.search'); 139 | 140 | if (!empty($search)) 141 | { 142 | $search = '%' . trim($search) . '%'; 143 | $query->where($db->quoteName('a.title') . ' LIKE :search') 144 | ->bind(':search', $search, ParameterType::STRING); 145 | } 146 | 147 | // Add the list ordering clause. 148 | $orderCol = $this->state->get('list.ordering', 'a.id'); 149 | $orderDirn = $this->state->get('list.direction', 'ASC'); 150 | 151 | if ($orderCol === 'title') { 152 | $ordering = [ 153 | $db->quoteName('a.title') . ' ' . $db->escape($orderDirn), 154 | ]; 155 | } else { 156 | $ordering = $db->escape($orderCol) . ' ' . $db->escape($orderDirn); 157 | } 158 | 159 | $query->order($ordering); 160 | 161 | return $query; 162 | } 163 | 164 | /** 165 | * Method to get a list of walks. 166 | * Overridden to add a check for access levels. 167 | * 168 | * @return mixed An array of data items on success, false on failure. 169 | * 170 | * @since 4.0.0 171 | */ 172 | public function getItems() 173 | { 174 | $items = parent::getItems(); 175 | 176 | return $items; 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /com_mywalks/admin/src/Table/Mywalk_datesTable.php: -------------------------------------------------------------------------------- 1 | form = $this->get('Form'); 70 | $this->item = $this->get('Item'); 71 | $this->state = $this->get('State'); 72 | 73 | if (count($errors = $this->get('Errors'))) 74 | { 75 | throw new GenericDataException(implode("\n", $errors), 500); 76 | } 77 | 78 | $this->addToolbar(); 79 | 80 | return parent::display($tpl); 81 | } 82 | 83 | /** 84 | * Add the page title and toolbar. 85 | * 86 | * @return void 87 | * 88 | * @throws \Exception 89 | * @since 1.6 90 | */ 91 | protected function addToolbar() 92 | { 93 | Factory::getApplication()->input->set('hidemainmenu', true); 94 | $isNew = ($this->item->id == 0); 95 | 96 | $toolbar = Toolbar::getInstance(); 97 | 98 | ToolbarHelper::title( 99 | Text::_('COM_MYWALKS_MYWALK_PAGE_TITLE_' . ($isNew ? 'ADD_WALK' : 'EDIT_WALK')) 100 | ); 101 | 102 | $canDo = ContentHelper::getActions('com_mywalks'); 103 | if ($canDo->get('core.create')) 104 | { 105 | $toolbar->apply('mywalk.apply'); 106 | $toolbar->save('mywalk.save'); 107 | } 108 | if ($isNew) 109 | { 110 | $toolbar->cancel('mywalk.cancel', 'JTOOLBAR_CANCEL'); 111 | } 112 | else 113 | { 114 | $toolbar->cancel('mywalk.cancel', 'JTOOLBAR_CLOSE'); 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /com_mywalks/admin/src/View/Mywalk_date/HtmlView.php: -------------------------------------------------------------------------------- 1 | form = $this->get('Form'); 85 | $this->item = $this->get('Item'); 86 | $this->state = $this->get('State'); 87 | 88 | // Check for errors. 89 | if (count($errors = $this->get('Errors'))) 90 | { 91 | throw new GenericDataException(implode("\n", $errors), 500); 92 | } 93 | 94 | $this->addToolbar(); 95 | 96 | return parent::display($tpl); 97 | } 98 | 99 | /** 100 | * Add the page title and toolbar. 101 | * 102 | * @return void 103 | * 104 | * @throws \Exception 105 | * @since 1.6 106 | */ 107 | protected function addToolbar() 108 | { 109 | Factory::getApplication()->input->set('hidemainmenu', true); 110 | $user = Factory::getUser(); 111 | $userId = $user->id; 112 | $isNew = ($this->item->id == 0); 113 | 114 | // Built the actions for new and existing records. 115 | //$canDo = $this->canDo; 116 | 117 | $toolbar = Toolbar::getInstance(); 118 | $title = $isNew ? 'ADD' : 'EDIT'; 119 | $title = Text::_('COM_MYWALKS_MYWALK_DATE_PAGE_TITLE_' . $title); 120 | ToolbarHelper::title($title); 121 | 122 | $canDo = ContentHelper::getActions('com_mywalks'); 123 | if ($canDo->get('core.create')) 124 | { 125 | $toolbar->apply('mywalk_date.apply'); 126 | $toolbar->save('mywalk_date.save'); 127 | } 128 | if ($isNew) 129 | { 130 | $toolbar->cancel('mywalk_date.cancel', 'JTOOLBAR_CANCEL'); 131 | } 132 | else 133 | { 134 | $toolbar->cancel('mywalk_date.cancel', 'JTOOLBAR_CLOSE'); 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /com_mywalks/admin/src/View/Mywalk_dates/HtmlView.php: -------------------------------------------------------------------------------- 1 | items = $this->get('Items'); 75 | $this->pagination = $this->get('Pagination'); 76 | $this->state = $this->get('State'); 77 | $this->filterForm = $this->get('FilterForm'); 78 | $this->activeFilters = $this->get('ActiveFilters'); 79 | 80 | // Check for errors. 81 | if (count($errors = $this->get('Errors'))) 82 | { 83 | throw new GenericDataException(implode("\n", $errors), 500); 84 | } 85 | 86 | $this->addToolbar(); 87 | 88 | return parent::display($tpl); 89 | } 90 | 91 | /** 92 | * Add the page title and toolbar. 93 | * 94 | * @return void 95 | * 96 | * @since 1.6 97 | */ 98 | protected function addToolbar() 99 | { 100 | $canDo = ContentHelper::getActions('com_mywalks'); 101 | 102 | $toolbar = Toolbar::getInstance('toolbar'); 103 | 104 | ToolbarHelper::title(Text::_('COM_MYWALKS_MYWALK_DATES_PAGE_TITLE'), 'mywalk_dates'); 105 | 106 | if ($canDo->get('core.create')) 107 | { 108 | $toolbar->addNew('mywalk_date.add'); 109 | } 110 | 111 | if ($canDo->get('core.edit.state')) 112 | { 113 | $dropdown = $toolbar->dropdownButton('status-group') 114 | ->text('JTOOLBAR_CHANGE_STATUS') 115 | ->toggleSplit(false) 116 | ->icon('icon-ellipsis-h') 117 | ->buttonClass('btn btn-action') 118 | ->listCheck(true); 119 | 120 | $childBar = $dropdown->getChildToolbar(); 121 | 122 | $childBar->publish('mywalk_dates.publish')->listCheck(true); 123 | 124 | $childBar->unpublish('mywalk_dates.unpublish')->listCheck(true); 125 | 126 | $childBar->archive('mywalk_dates.archive')->listCheck(true); 127 | 128 | if ($this->state->get('filter.published') != -2) 129 | { 130 | $childBar->trash('mywalk_dates.trash')->listCheck(true); 131 | } 132 | } 133 | 134 | if ($this->state->get('filter.published') == -2 && $canDo->get('core.delete')) 135 | { 136 | $toolbar->delete('mywalk_dates.delete') 137 | ->text('JTOOLBAR_EMPTY_TRASH') 138 | ->message('JGLOBAL_CONFIRM_DELETE') 139 | ->listCheck(true); 140 | } 141 | } 142 | 143 | /** 144 | * Returns an array of fields the table can be sorted by 145 | * 146 | * @return array Array containing the field name to sort by as the key and display text as value 147 | * 148 | * @since 3.0 149 | */ 150 | protected function getSortFields() 151 | { 152 | return array( 153 | 'a.date' => Text::_('COM_MYWALKS_DATES_VISIT_DATE_LABEL'), 154 | 'a.id' => Text::_('JGRID_HEADING_ID'), 155 | ); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /com_mywalks/admin/src/View/Mywalks/HtmlView.php: -------------------------------------------------------------------------------- 1 | items = $this->get('Items'); 73 | $this->pagination = $this->get('Pagination'); 74 | $this->state = $this->get('State'); 75 | $this->filterForm = $this->get('FilterForm'); 76 | $this->activeFilters = $this->get('ActiveFilters'); 77 | 78 | // Check for errors. 79 | if (count($errors = $this->get('Errors'))) 80 | { 81 | throw new GenericDataException(implode("\n", $errors), 500); 82 | } 83 | 84 | $this->addToolbar(); 85 | 86 | return parent::display($tpl); 87 | } 88 | 89 | /** 90 | * Add the page title and toolbar. 91 | * 92 | * @return void 93 | * 94 | * @since 1.6 95 | */ 96 | protected function addToolbar() 97 | { 98 | // Get the toolbar object instance 99 | $toolbar = Toolbar::getInstance('toolbar'); 100 | 101 | ToolbarHelper::title(Text::_('COM_MYWALKS_MYWALKS_PAGE_TITLE'), 'mywalks'); 102 | 103 | $canDo = ContentHelper::getActions('com_mywalks'); 104 | 105 | if ($canDo->get('core.create')) 106 | { 107 | $toolbar->addNew('mywalk.add'); 108 | } 109 | 110 | if ($canDo->get('core.edit.state')) 111 | { 112 | $dropdown = $toolbar->dropdownButton('status-group') 113 | ->text('JTOOLBAR_CHANGE_STATUS') 114 | ->toggleSplit(false) 115 | ->icon('icon-ellipsis-h') 116 | ->buttonClass('btn btn-action') 117 | ->listCheck(true); 118 | 119 | $childBar = $dropdown->getChildToolbar(); 120 | 121 | $childBar->publish('mywalks.publish')->listCheck(true); 122 | 123 | $childBar->unpublish('mywalks.unpublish')->listCheck(true); 124 | 125 | $childBar->archive('mywalks.archive')->listCheck(true); 126 | 127 | if ($this->state->get('filter.published') != -2) 128 | { 129 | $childBar->trash('mywalks.trash')->listCheck(true); 130 | } 131 | } 132 | 133 | if ($this->state->get('filter.published') == -2 && $canDo->get('core.delete')) 134 | { 135 | $toolbar->delete('mywalks.delete') 136 | ->text('JTOOLBAR_EMPTY_TRASH') 137 | ->message('JGLOBAL_CONFIRM_DELETE') 138 | ->listCheck(true); 139 | } 140 | 141 | if ($canDo->get('core.create')) 142 | { 143 | $toolbar->preferences('com_mywalks'); 144 | } 145 | 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /com_mywalks/admin/tmpl/mywalk/edit.php: -------------------------------------------------------------------------------- 1 | 21 | 22 |
24 | 25 | 26 | 27 |
28 | 'details')); ?> 29 | 30 | 31 |
32 |
33 |
34 |
35 | form->renderField('description'); ?> 36 | form->renderField('distance'); ?> 37 | form->renderField('id'); ?> 38 |
39 |
40 |
41 |
42 |
43 |
44 | 45 |
46 |
47 |
48 |
49 | 50 | 51 | 52 |
53 |
54 | form->renderField('toilets'); ?> 55 | form->renderField('cafe'); ?> 56 | form->renderField('bogs'); ?> 57 |
58 |
59 | 60 | 61 | 62 |
63 |
64 | form->renderField('picture'); ?> 65 | form->renderField('width'); ?> 66 | form->renderField('height'); ?> 67 | form->renderField('alt'); ?> 68 |
69 |
70 | 71 | 72 | 73 |
74 | 75 | 76 |
77 | -------------------------------------------------------------------------------- /com_mywalks/admin/tmpl/mywalk_date/edit.php: -------------------------------------------------------------------------------- 1 | getUserState('com_mywalks.walk_id'); 25 | 26 | if (empty($walk_id)) { 27 | throw new GenericDataException("\nThe walk id was not set!\n", 500); 28 | } 29 | 30 | // Fieldsets to not automatically render by /layouts/joomla/edit/params.php 31 | $this->ignore_fieldsets = array('details', 'item_associations', 'jmetadata'); 32 | ?> 33 | 34 |
35 | 36 | 37 | 38 |
39 | 'details')); ?> 40 | 41 | 42 |
43 |
44 |
45 |
46 | form->renderField('date'); ?> 47 | form->renderField('weather'); ?> 48 | form->renderField('id'); ?> 49 | form->setValue('walk_id', null, $walk_id); ?> 50 | form->renderField('walk_id'); ?> 51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | 60 |
61 |
62 |
63 |
64 | 65 | 66 | 67 |
68 | 69 | 70 | 71 |
72 | -------------------------------------------------------------------------------- /com_mywalks/admin/tmpl/mywalk_dates/default.php: -------------------------------------------------------------------------------- 1 | escape($this->state->get('list.ordering')); 23 | $listDirn = $this->escape($this->state->get('list.direction')); 24 | $states = array ( 25 | '0' => Text::_('JUNPUBLISHED'), 26 | '1' => Text::_('JPUBLISHED'), 27 | '2' => Text::_('JARCHIVED'), 28 | '-2' => Text::_('JTRASHED') 29 | ); 30 | $editIcon = ''; 31 | $title = MywalksHelper::getWalkTitle($this->state->get('walk_id'))->title; 32 | $walk_id = $this->state->get('walk_id') 33 | ?> 34 |

35 |
36 |
37 |
38 |
39 | $this)); ?> 40 | items)) : ?> 41 |
42 | 43 | 44 |
45 | 46 | 47 | 48 | 49 | 52 | 55 | 58 | 61 | 64 | 65 | 66 | 67 | items); 69 | foreach ($this->items as $i => $item) : 70 | ?> 71 | 72 | 75 | 78 | 82 | 85 | 88 | 89 | 90 | 91 |
50 | 51 | 53 | 54 | 56 | 57 | 59 | 60 | 62 | 63 |
73 | id); ?> 74 | 76 | state]; ?> 77 | 79 | 80 | date; ?> 81 | 83 | weather; ?> 84 | 86 | id; ?> 87 |
92 | 93 | 94 | pagination->getListFooter(); ?> 95 | 96 | 97 | 98 | 99 | 100 | 101 |
102 |
103 |
104 |
105 | 106 | 107 | -------------------------------------------------------------------------------- /com_mywalks/admin/tmpl/mywalks/default.php: -------------------------------------------------------------------------------- 1 | escape($this->state->get('list.ordering')); 18 | $listDirn = $this->escape($this->state->get('list.direction')); 19 | $states = array ( 20 | '0' => Text::_('JUNPUBLISHED'), 21 | '1' => Text::_('JPUBLISHED'), 22 | '2' => Text::_('JARCHIVED'), 23 | '-2' => Text::_('JTRASHED') 24 | ); 25 | $editIcon = ''; 26 | ?> 27 |
28 | $this)); ?> 29 | items)) : ?> 30 |
31 | 32 | 33 |
34 | 35 | 36 | 37 | 38 | 41 | 44 | 47 | 50 | 53 | 56 | 59 | 62 | 65 | 68 | 71 | 72 | 73 | 74 | items); 76 | foreach ($this->items as $i => $item) : 77 | ?> 78 | 79 | 82 | 85 | 90 | 93 | 96 | 100 | 103 | 106 | 109 | 112 | 115 | 116 | 117 | 118 |
39 | 40 | 42 | 43 | 45 | 46 | 48 | 49 | 51 | 52 | 54 | 55 | 57 | 58 | 60 | 61 | 63 | 64 | 66 | 67 | 69 | 70 |
80 | id); ?> 81 | 83 | state]; ?> 84 | 86 | 87 | escape($item->title); ?> 88 | 89 | 91 | description; ?> 92 | 94 | distance; ?> 95 | 97 | 98 | nvisits; ?> 99 | 101 | toilets; ?> 102 | 104 | cafe; ?> 105 | 107 | hills; ?> 108 | 110 | bogs; ?> 111 | 113 | id; ?> 114 |
119 | 120 | 121 | pagination->getListFooter(); ?> 122 | 123 | 124 | 125 | 126 | 127 |
128 | -------------------------------------------------------------------------------- /com_mywalks/mywalks.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | com_mywalks 4 | 5 | August 2019 6 | Clifford E Ford 7 | cliff@ford.myzen.co.uk 8 | http://www.fford.me.uk/ 9 | Copyright (C) 2019-2023 Clifford E Ford, All rights reserved. 10 | GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html 11 | 12 | 0.3.0 13 | 14 | COM_MYWALKS_XML_DESCRIPTION 15 | J4xdemos\Component\Mywalks 16 | 17 | 18 | 19 | sql/install.mysql.sql 20 | 21 | 22 | 23 | 24 | sql/uninstall.mysql.sql 25 | 26 | 27 | 28 | 29 | 32 | 33 | 34 | forms 35 | language 36 | src 37 | tmpl 38 | 39 | 40 | 41 | 42 | access.xml 43 | config.xml 44 | forms 45 | language 46 | services 47 | sql 48 | src 49 | tmpl 50 | 51 | com_mywalks 52 | 53 | 54 | -------------------------------------------------------------------------------- /com_mywalks/site/forms/filter_mywalks.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 6 | 13 | 14 | 15 | 16 | 17 | 18 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 39 | 40 |
41 | -------------------------------------------------------------------------------- /com_mywalks/site/language/en-GB/com_mywalks.ini: -------------------------------------------------------------------------------- 1 | COM_MYWALKS_ERROR_WALK_NOT_FOUND="Walk not found!" 2 | COM_MYWALKS_LIST_PAGE_HEADING="List of Walks" 3 | COM_MYWALKS_LIST_TITLE="Title" 4 | COM_MYWALKS_LIST_DESCRIPTION="Description" 5 | COM_MYWALKS_LIST_DISTANCE="Distance in Km" 6 | COM_MYWALKS_LIST_LAST_VISIT="Last Visit" 7 | COM_MYWALKS_LIST_NVISITS="nVisits" 8 | COM_MYWALKS_LIST_TABLE_CAPTION="List of Walks" 9 | COM_MYWALKS_MYWALKS_FILTER_SEARCH_TITLE_DESC="Search in Title" 10 | COM_MYWALKS_WALK_BACK_TO_WALKS="Back to list of walks" 11 | COM_MYWALKS_WALK_REPORTS="Walk Reports" 12 | COM_MYWALKS_WALK_DATE="Visit date" 13 | COM_MYWALKS_WALK_WEATHER="Weather Report" 14 | -------------------------------------------------------------------------------- /com_mywalks/site/src/Controller/DisplayController.php: -------------------------------------------------------------------------------- 1 | input->getInt('id'); 48 | $this->setState('mywalk.id', $pk); 49 | } 50 | 51 | /** 52 | * Method to get walk data. 53 | * 54 | * @param integer $pk The id of the walk. 55 | * 56 | * @return object|boolean Menu item data object on success, boolean false 57 | */ 58 | public function getItem($pk = null) 59 | { 60 | $pk = (!empty($pk)) ? $pk : (int) $this->getState('mywalk.id'); 61 | 62 | try 63 | { 64 | $db = $this->getDatabase(); 65 | $query = $db->getQuery(true) 66 | ->select( 67 | $this->getState( 68 | 'item.select', 'a.*' 69 | ) 70 | ); 71 | $query->from($db->quoteName('#__mywalks') . ' AS a') 72 | ->where($db->quoteName('a.id') . ' = :id') 73 | ->bind(':id', $pk, ParameterType::INTEGER); 74 | 75 | $db->setQuery($query); 76 | 77 | $data = $db->loadObject(); 78 | 79 | if (empty($data)) 80 | { 81 | throw new \Exception(Text::_('COM_MYWALKS_ERROR_WALK_NOT_FOUND'), 404); 82 | } 83 | } 84 | catch (\Exception $e) 85 | { 86 | if ($e->getCode() == 404) 87 | { 88 | // Need to go through the error handler to allow Redirect to work. 89 | throw new \Exception($e->getMessage(), 404); 90 | } 91 | else 92 | { 93 | $this->setError($e); 94 | $this->_item[$pk] = false; 95 | } 96 | } 97 | 98 | return $data; 99 | } 100 | /** 101 | * Method to get walk visit data. 102 | * 103 | * @param integer $pk The id of the walk. 104 | * 105 | * @return object|boolean Menu item data object on success, boolean false 106 | */ 107 | public function getReports($pk = null) 108 | { 109 | $pk = (!empty($pk)) ? $pk : (int) $this->getState('mywalk.id'); 110 | 111 | try 112 | { 113 | $db = $this->getDatabase(); 114 | $query = $db->getQuery(true) 115 | ->select('b.*') 116 | ->from($db->quoteName('#__mywalk_dates') . ' AS b') 117 | ->where($db->quoteName('b.walk_id') . ' = :id') 118 | ->bind(':id', $pk, ParameterType::INTEGER) 119 | ->order($db->quoteName('date') . ' DESC'); 120 | 121 | $db->setQuery($query); 122 | 123 | $data = $db->loadObjectList(); 124 | 125 | // It is OK to have a walk without visit data - handle it the view. 126 | } 127 | catch (\Exception $e) 128 | { 129 | if ($e->getCode() == 404) 130 | { 131 | // Need to go through the error handler to allow Redirect to work. 132 | throw new \Exception($e->getMessage(), 404); 133 | } 134 | else 135 | { 136 | $this->setError($e); 137 | $this->_item[$pk] = false; 138 | } 139 | } 140 | 141 | return $data; 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /com_mywalks/site/src/Model/MywalksModel.php: -------------------------------------------------------------------------------- 1 | getUserStateFromRequest($this->context . '.filter.search', 'filter_search'); 65 | $this->setState('filter.search', $search); 66 | 67 | // List state information. 68 | parent::populateState($ordering, $direction); 69 | } 70 | 71 | /** 72 | * Method to get a store id based on model configuration state. 73 | * 74 | * This is necessary because the model is used by the component and 75 | * different modules that might need different sets of data or different 76 | * ordering requirements. 77 | * 78 | * @param string $id A prefix for the store id. 79 | * 80 | * @return string A store id. 81 | * 82 | * @since 1.6 83 | */ 84 | protected function getStoreId($id = '') 85 | { 86 | // Compile the store id. 87 | $id .= ':' . $this->getState('filter.search'); 88 | 89 | return parent::getStoreId($id); 90 | } 91 | 92 | /** 93 | * Get the master query for retrieving a list of walks subject to the model state. 94 | * 95 | * @return \JDatabaseQuery 96 | * 97 | * @since 1.6 98 | */ 99 | protected function getListQuery() 100 | { 101 | 102 | // Create a new query object. 103 | $db = $this->getDatabase(); 104 | $query = $db->getQuery(true); 105 | 106 | // Select the required fields from the table. 107 | $query->select( 108 | $this->getState( 109 | 'list.select', 110 | 'a.*, 111 | (SELECT MAX(' . $db->quoteName('date') 112 | . ') FROM ' . $db->quoteName('#__mywalk_dates') 113 | . ' WHERE ' . $db->quoteName('walk_id') . ' = ' . $db->quoteName('a.id') . ') AS last_visit, 114 | (SELECT count(' . $db->quote('date') . ') FROM ' . $db->quoteName('#__mywalk_dates') 115 | . ' WHERE ' . $db->quoteName('walk_id') . ' = ' . $db->quoteName('a.id') . ') AS nvisits' 116 | ) 117 | ); 118 | $query->from($db->quoteName('#__mywalks') . ' AS a'); 119 | 120 | // Filter by search in title. 121 | $search = $this->getState('filter.search'); 122 | 123 | if (!empty($search)) 124 | { 125 | $search = '%' . trim($search) . '%'; 126 | $query->where($db->quoteName('a.title') . ' LIKE :search') 127 | ->bind(':search', $search, ParameterType::STRING); 128 | } 129 | 130 | // Add the list ordering clause. 131 | $orderCol = $this->state->get('list.ordering', 'a.id'); 132 | $orderDirn = $this->state->get('list.direction', 'ASC'); 133 | 134 | if ($orderCol === 'title') { 135 | $ordering = [ 136 | $db->quoteName('a.title') . ' ' . $db->escape($orderDirn), 137 | ]; 138 | } else { 139 | $ordering = $db->escape($orderCol) . ' ' . $db->escape($orderDirn); 140 | } 141 | 142 | $query->order($ordering); 143 | 144 | return $query; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /com_mywalks/site/src/Service/MywalksNomenuRules.php: -------------------------------------------------------------------------------- 1 | router = $router; 41 | } 42 | 43 | /** 44 | * Dummymethod to fullfill the interface requirements 45 | * 46 | * @param array &$query The query array to process 47 | * 48 | * @return void 49 | * 50 | * @since 3.4 51 | * @codeCoverageIgnore 52 | */ 53 | public function preprocess(&$query) 54 | { 55 | $test = 'Test'; 56 | } 57 | 58 | /** 59 | * Parse a menu-less URL 60 | * 61 | * @param array &$segments The URL segments to parse 62 | * @param array &$vars The vars that result from the segments 63 | * 64 | * @return void 65 | * 66 | * @since 3.4 67 | */ 68 | public function parse(&$segments, &$vars) 69 | { 70 | //with this url: http://localhost/j4x/my-walks/mywalk-n/walk-title.html 71 | // segments: [[0] => mywalk-n, [1] => walk-title] 72 | // vars: [[option] => com_mywalks, [view] => mywalks, [id] => 0] 73 | 74 | $vars['view'] = 'mywalk'; 75 | $vars['id'] = substr($segments[0], strpos($segments[0], '-') + 1); 76 | array_shift($segments); 77 | array_shift($segments); 78 | return; 79 | } 80 | 81 | /** 82 | * Build a menu-less URL 83 | * 84 | * @param array &$query The vars that should be converted 85 | * @param array &$segments The URL segments to create 86 | * 87 | * @return void 88 | * 89 | * @since 3.4 90 | */ 91 | public function build(&$query, &$segments) 92 | { 93 | // content of $query ($segments is empty or [[0] => mywalk-3]) 94 | // when called by the menu: [[option] => com_mywalks, [Itemid] => 126] 95 | // when called by the component: [[option] => com_mywalks, [view] => mywalk, [id] => 1, [Itemid] => 126] 96 | // when called from a module: [[option] => com_mywalks, [view] => mywalks, [format] => html, [Itemid] => 126] 97 | // when called from breadcrumbs: [[option] => com_mywalks, [view] => mywalks, [Itemid] => 126] 98 | 99 | // the url should look like this: /site-root/mywalks/walk-n/walk-title.html 100 | 101 | // if the view is not mywalk - the single walk view 102 | if (!isset($query['view']) || (isset($query['view']) && $query['view'] !== 'mywalk') || isset($query['format'])) 103 | { 104 | return; 105 | } 106 | $segments[] = $query['view'] . '-' . $query['id']; 107 | // the last part of the url may be missing 108 | if (isset($query['slug'])) { 109 | $segments[] = $query['slug']; 110 | unset($query['slug']); 111 | } 112 | unset($query['view']); 113 | unset($query['id']); 114 | } 115 | } 116 | 117 | -------------------------------------------------------------------------------- /com_mywalks/site/src/Service/Router.php: -------------------------------------------------------------------------------- 1 | categoryFactory = $categoryFactory; 65 | $this->db = $db; 66 | 67 | $params = ComponentHelper::getParams('com_mywalks'); 68 | $this->noIDs = (bool) $params->get('sef_ids'); 69 | 70 | $mywalks = new RouterViewConfiguration('mywalks'); 71 | $mywalks->setKey('id'); 72 | $this->registerView($mywalks); 73 | 74 | $mywalk = new RouterViewConfiguration('mywalk'); 75 | $mywalk->setKey('id'); 76 | $this->registerView($mywalk); 77 | 78 | parent::__construct($app, $menu); 79 | 80 | $this->attachRule(new MenuRules($this)); 81 | $this->attachRule(new StandardRules($this)); 82 | $this->attachRule(new NomenuRules($this)); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /com_mywalks/site/src/View/Mywalk/HtmlView.php: -------------------------------------------------------------------------------- 1 | state = $this->get('State'); 58 | $this->item = $this->get('Item'); 59 | $this->reports = $this->get('Reports'); 60 | 61 | // Check for errors. 62 | if (count($errors = $this->get('Errors'))) 63 | { 64 | throw new GenericDataException(implode("\n", $errors), 500); 65 | } 66 | 67 | return parent::display($tpl); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /com_mywalks/site/src/View/Mywalks/HtmlView.php: -------------------------------------------------------------------------------- 1 | state = $this->get('State'); 70 | $this->items = $this->get('Items'); 71 | $this->filterForm = $this->get('FilterForm'); 72 | $this->activeFilters = $this->get('ActiveFilters'); 73 | $this->pagination = $this->get('Pagination'); 74 | // Flag indicates to not add limitstart=0 to URL 75 | $this->pagination->hideEmptyLimitstart = true; 76 | 77 | // Check for errors. 78 | if (count($errors = $this->get('Errors'))) 79 | { 80 | throw new GenericDataException(implode("\n", $errors), 500); 81 | } 82 | 83 | return parent::display($tpl); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /com_mywalks/site/tmpl/mywalk/default.php: -------------------------------------------------------------------------------- 1 | 16 | 19 | 20 |

item->description; ?>!

21 | 22 |

23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | reports as $id => $report) : ?> 34 | 35 | 36 | 37 | 38 | 39 | 40 |
date; ?>weather; ?>
41 |
42 | 43 | 44 | -------------------------------------------------------------------------------- /com_mywalks/site/tmpl/mywalks/default.php: -------------------------------------------------------------------------------- 1 | escape($this->state->get('list.ordering')); 19 | $listDirn = $this->escape($this->state->get('list.direction')); 20 | 21 | ?> 22 | 23 |

24 | 25 |
26 | 27 | $this)); ?> 28 | 29 |
30 | 31 | 32 | 33 | 36 | 37 | 40 | 43 | 46 | 47 | 48 | 49 | items as $id => $item) : 50 | $slug = preg_replace('/[^a-z\d]/i', '-', $item->title); 51 | $slug = strtolower(str_replace(' ', '-', $slug)); 52 | ?> 53 | 54 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |
34 | 35 | 38 | 39 | 41 | 42 | 44 | 45 |
55 | title; ?>description; ?>distance; ?>last_visit //$item->lastvisit; ?>nvisits; ?>
64 |
65 | 66 | pagination->getListFooter(); ?> 67 | 68 | 69 | 70 | 71 | 72 |
-------------------------------------------------------------------------------- /com_mywalks/site/tmpl/mywalks/default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 |
17 | 18 | 19 | 20 | 21 |
22 | 23 |
24 | 25 | 26 |
27 | 28 |
29 |
30 |
31 | -------------------------------------------------------------------------------- /resources/mywalks-admin-walk-edit-details.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ceford/j4xdemos-com-mywalks/9005b8a73e660a168878d2e1ffabfc9ae2787327/resources/mywalks-admin-walk-edit-details.jpg -------------------------------------------------------------------------------- /resources/mywalks-admin-walks-list.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ceford/j4xdemos-com-mywalks/9005b8a73e660a168878d2e1ffabfc9ae2787327/resources/mywalks-admin-walks-list.jpg -------------------------------------------------------------------------------- /resources/mywalks-site-walk-dates-list.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ceford/j4xdemos-com-mywalks/9005b8a73e660a168878d2e1ffabfc9ae2787327/resources/mywalks-site-walk-dates-list.jpg -------------------------------------------------------------------------------- /resources/mywalks-site-walks-list.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ceford/j4xdemos-com-mywalks/9005b8a73e660a168878d2e1ffabfc9ae2787327/resources/mywalks-site-walks-list.jpg --------------------------------------------------------------------------------