How to add a user account page (and not just a menu item)

Hello,

I would like to add a custom user account page for an affiliation program.
So I managed to add my new page in the menu using this :

add_filter(
	'hivepress/v1/menus/user_account',
	function( $menu ) {
		$menu['items']['affiliation'] = [
			'label'  => 'Affiliation',
			'url'    => '/account/affiliation',
			'_order' => 124,
		];
		return $menu;
	}
);

Result :

Is there a way to keep the “context”, meaning the sidebar, once you click and reach the new page ? At the moment, this sidebar disappears.

Another user, @hyva , said it was possible pointing to the documentation.
However I cannot really make heads or tails out of it…

Thanks !

1 Like

Ok, I found out, mostly by reverse-engineering (so to speak) the foo-followers (demo) plugin.

Here’s the result :

I share the code for those interested. Beware : It’s based on MVC, quite convoluted and overly complicated according to me, you need to respect the required naming conventions (and paths) so every case is different.

Basically you create your plugin, starting with a single file, at the root level

<?php
/**
 * Plugin Name: Condorito for HivePress
 * Description: Adding a custom page under user account.
 * Version: 
 * Author: Condorito.fr
 * Author URI: https://condorito.fr/
 * Text Domain: condorito
 * Domain Path: /languages/
 */

// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;

// Register extension directory.
add_filter(
	'hivepress/v1/extensions',
	function( $extensions ) {
		$extensions[] = __DIR__;

		return $extensions;
	}
);

//add extra menu under user account (will appear in the drop-down, as well as the side bar. 
add_filter(
	'hivepress/v1/menus/user_account',
	function( $menu ) {
		$menu['items']['affiliation'] = [
			'label'  => 'Affiliation',
			'url'    => '/account/affiliation',
			'_order' => 124,
		];

		return $menu;
	}
);

Then you add a controller under /includes/controllers/

<?php
namespace HivePress\Controllers;

use HivePress\Helpers as hp;
use HivePress\Models;
use HivePress\Blocks;

// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;

/**
 * Controller class. (based on foo-followers' / includes / controllers / class-followers )
 */
final class lancelo extends Controller {

	/**
	 * Class constructor.
	 *
	 * @param array $args Controller arguments.
	 */
	public function __construct( $args = [] ) {
		$args = hp\merge_arrays(
			[
				'routes' => [
					/*OCO*/
					'affiliation_page'      => [
						'title'     => esc_html__( 'Affiliation', 'condorito' ),
						'base'      => 'user_account_page',
						'path'      => '/affiliation',
						'redirect'  => [ $this, 'redirect_aff_page' ],
						'action'    => [ $this, 'render_aff_page' ],
						'paginated' => true,
					],
				],
			],
			$args
		);

		parent::__construct( $args );
	}

	public function redirect_aff_page() {

		// Check authentication.
		if ( ! is_user_logged_in() ) {
			return hivepress()->router->get_return_url( 'user_login_page' );
		}
		return false;
	}
	
	/**
	 * Renders affiliate page.
	 *
	 * @return string
	 */
	public function render_aff_page() {

		// Render page template.
		return ( new Blocks\Template(
			[
				'template' => 'aff_page',
				'context'  => [
					'listings' => [],
				],
			]
		) )->render();
	}	
}

Finally you need to add the template file under /includes/templates/

<?php
namespace HivePress\Templates;

use HivePress\Helpers as hp;

// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;

/**
 * Template class.
 */
class Aff_Page extends User_Account_Page {

	/**
	 * Class constructor.
	 *
	 * @param array $args Template arguments.
	 */
	public function __construct( $args = [] ) {
		$args = hp\merge_trees(
			[
				'blocks' => [
					'page_content' => [
						'blocks' => [
							'custom_text' => [
								'type'    => 'content',
								'content' => '<p>Some HTML content goes here</p>',
								'_order' => 60,
							],				
							'custom_listing_shortcode' => [
								'type'    => 'content',
								'content' => do_shortcode('[some_shortcode]'), /*if you have a shortcode coming from a third-party plugin */
								'_order' => 61,
							],						
						],
					],
				],
			],
			$args
		);

		parent::__construct( $args );
	}
}

And voilà ! Hope this helps !

There is only thing missing to make it perfect, the ‘current-menu-item’ CSS class is missing for some reasons. I don’t know how to add it. So the active menu does no show in a different color.

So @ihor or @andrii feel free to help me out on that.
Minor problem though.

2 Likes

Hi,

Thank you for the solution, it will be useful for our community.

For the sake of completeness, here’s the plugin structure (I said naming conventions needed to be respected, without naming the files, my bad):

Folder name : lancelo-hivepress
/lancelo-hivepress.php
+/includes/controllers/class-lancelo.php
+/includes/templates/class-aff-page.php

If you want to add the .current-menu_item class to the selected menu :

// search in all links the one having "Affiliation" as text attribute, 
//then go up in the DOM and apply css class to its parent (<li>)
jQuery(document).ready(function($) {			
  $('a').filter(function(index) { return $(this).text() === "Affiliation";}).parent().addClass('current-menu-item');
}); 

This javascript snippet needs to be injected when browsing this page only, of course, using this trick for instance.
That’s the best I could up with, but since nobody else provided a solution, here’s mine.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.