Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Propose More Readable Panel Route and Data #23

Closed
taufik-nurrohman opened this issue Oct 4, 2021 · 15 comments
Closed

Propose More Readable Panel Route and Data #23

taufik-nurrohman opened this issue Oct 4, 2021 · 15 comments

Comments

@taufik-nurrohman
Copy link
Member

taufik-nurrohman commented Oct 4, 2021

The $state->x->panel->path property just adds complexity. Since panel relies on user, it would be simpler if we use the $state->x->user->path and $state->x->user->guard->path value as the namespace for panel routes.

Currently, the route pattern contains a command stored as /::command-name::/ in the URL. This pattern for sure makes it easy to instantly swap the commands by replacing the URL value using functions like strtr() and str_replace() due to its striking pattern. This pattern has been around since version 1.x.x of the panel, but currently, such URL patterns got quite dirty and becomes more and more difficult to be served as dynamic route patterns as more features in the panel grew.

Roughly speaking, I’d like to suggest a URL pattern for panel version 3.x.x, which is neater and will blends-in nicely with the front-end routes:

./user → the log-in page
./user/taufik → the user page
./panel/fire/asdf/page/lorem-ipsum.page → the panel path for “asdf” (custom) task
./panel/get/page/lorem-ipsum.page → the panel path for “edit” task
./panel/let/page/lorem-ipsum.page → the panel path for “delete” task
./panel/set/page → the panel path for “create” task

Both /user and /panel path will be stored in the same extension state storage (of the user extension). /user will be stored in $state->x->user->path and /panel can be stored in $state->x->user->guard->path. Due to the nature of user being independent from panel, the (secret) value of $state->x->user->guard->path don’t have to be assigned to user, so that by default, the /panel path will be returned as /user, since it was the default value for the secret user log-in path when that secret value is not set (as /panel, for example).

./user/get/page/lorem-ipsum.page → the default panel path for “edit” task
./user/let/page/lorem-ipsum.page → the default panel path for “delete” task
./user/set/page → the default panel path for “create” task
$base = $state->x->user->guard->path ?? $state->x->user->path ?? '/user';

Route::set($base . '/fire/?/*', function($fn, $path) { … });

Route::set($base . '/get/*', function($path) { … });
Route::set($base . '/let/*', function($path) { … });
Route::set($base . '/set/*', function($path) { … });

Others

Remove $_['/'] property. We should consider to use custom pattern in URL string that later will be replaced by the correct base panel URL. For example, we can use dummy URL protocol or fake relative URL which later will be replaced with http://127.0.0.1/panel/?/ in the output:

get://page/lorem-ipsum.page
let://page/lorem-ipsum.page
set://page/lorem-ipsum.page
.../get/page/lorem-ipsum.page
&/get/page/lorem-ipsum.page

Replace $_['f'] property with $_['source'], which its value can be either file or folder path. Ideally, the most common property name to store a file/folder path in Mecha is “path”. But, it is already used to store URL parts after the folder name, along with $_['hash'], $_['i'], $_['id'], and $_['query'] properties.

Alternatively, instead of removing $_['/'], we can rename it with $_['root'] to follow Mecha’s standard URL properties. But this likely will change the $_['path'] value, ideally, to also include the folder path. Which will make $_['id'] property becomes useless. Later, $_['root'] ideally should also include the $_['task'] part, which will make $_['task'] property becomes useless.

$_['ground'] // "http://127.0.0.1/panel"
$_['root'] // "http://127.0.0.1/panel/get"
$_['path'] // "page/lorem-ipsum.page"
$_['i'] // 1
$_['query'] // "foo=bar&baz=qux"
$_['hash'] // "foo"
// Detect current task
if (str_ends_with($_['root'], '/get')) { … }

// Detect current folder
if ('page' === $_['path'] || str_starts_with($_['path'], 'page/')) { … }
@taufik-nurrohman
Copy link
Member Author

taufik-nurrohman commented Oct 5, 2021

Or, to completely remove the task part in URL, and assign it to the query string instead.

./user/page → “edit” or “read” task by default
./user/page?task=set&type=page/page → “create” task
./user/page?task=let → “delete” task

The benefit is, you can run “delete” task using POST request. Makes it possible to trigger a hook to delete featured image file automatically.

<form method="post">
  <button name="task" type="submit" value="let">
    Delete
  </button>
</form>

@taufik-nurrohman
Copy link
Member Author

taufik-nurrohman commented Oct 5, 2021

What if I put the user name in URL too? This will make it easier to validate current user.

./user/taufik/page → “edit” or “read” task by default
./user/taufik/page?task=set&type=page/page → “create” task
./user/taufik/page?task=let → “delete” task

This would minimize the data used in panel. Less confusing.

$_['root'];
$_['path'];
$_['i'];
$_['query'];
$_['hash'];

@igoynawamreh
Copy link
Member

What if I put the user name in URL too? This will make it easier to validate current user.

How about removing /user in the URL?

@taufik-nurrohman
Copy link
Member Author

taufik-nurrohman commented Oct 6, 2021

How about removing /user in the URL?

@igoynawamreh the reason why I want to keep the /user part is because user extension has a secret log-in path feature. It’s just that I don’t have the time to document it. If you set a path property to the guard property with random value, that value will then becomes the log-in path:

<?php

return [
    'path' => '/user',
    'guard' => [
        'path' => '/panel'
    ]
];

From the states above, expect to have http://127.0.0.1/user/taufik-nurrohman as the user profile page, and http://127.0.0.1/panel as the log-in path.

@igoynawamreh
Copy link
Member

If so then I agree to use username in the URL.

@igoynawamreh
Copy link
Member

But for some web apps I prefer not to put the user in the URL.

What do you think?

@taufik-nurrohman
Copy link
Member Author

taufik-nurrohman commented Oct 6, 2021

What kind of web app is that?

You can always alias the route if you want:

Route::set('taufik-nurrohman', function() {
    // Probably put some conditional check here, to prevent
    // conflict with the existing static page URL.
    if ($file = File::exist(LOT . DS . 'page' . DS . 'taufik-nurrohman.page')) {
        // Load static page here!
        Route::fire('*', ['taufik-nurrohman']);
    } else {
        Route::fire('user/:user', ['taufik-nurrohman']);
    }
});

@taufik-nurrohman
Copy link
Member Author

taufik-nurrohman commented Oct 6, 2021

You can also make your own control panel application if you want, by detecting if user is logged-in this way:

if (Is::user()) {
    require __DIR__ . DS . 'app.php';
} else {
    $path = $state->x->user->guard->path ?? $state->x->user->path ?? '/user';
    Guard::kick($path); // Redirect to log-in form
}

Check specific user name:

if (Is::user('taufik-nurrohman')) { … }

@taufik-nurrohman
Copy link
Member Author

taufik-nurrohman commented Oct 7, 2021

Ummm, probably shouldn’t put the user name in URL. User name in URL is useless because internally, we take the current user name from document cookie.

And to prevent conflict with public user URL, a task data in URL path is still needed anyway.

./user/asset → a user page for `@asset` user name
./user/get → a user page for `@get` user name
./user/get/asset → a panel page to retrieve the asset folder details

@taufik-nurrohman
Copy link
Member Author

taufik-nurrohman commented Oct 7, 2021

Expect panel to set $state->x->user->guard->path value automatically if it is not set:

// `.\lot\x\panel\index.php`
if (!State::get('x.user.guard.path')) {
    State::set('x.user.guard.path', '/panel');
}

@taufik-nurrohman
Copy link
Member Author

taufik-nurrohman commented Oct 15, 2021

Rethinking the root data. Probably, a path property is enough to store panel URL for testing purpose.

---
asset:
  0: []
  1: []
  2: []
  #
  script: []
  style: []
author: null
can: []
d: null
description: null
form:
  lot: []
  type: null
has: []
hash: null
i: null
icon: []
is: []
kick: null
lot: []
not: []
path: null
query: []
source: null
status: 200
title: null
type: null

@taufik-nurrohman
Copy link
Member Author

taufik-nurrohman commented Oct 15, 2021

Internal URL builder for link and url component can be added to convert URL via component properties.

namespace x\panel\from {
    function link($value, $key) {}
}

namespace x\panel\to {
    function link($value, $key) {}
}
// `http://127.0.0.1/user/get/page/article/1?type=files#main`
echo x\panel\to\link([
    'd' => 'user/get',
    'hash' => 'main',
    'i' => 1,
    'path' => 'page/article',
    'query' => [
        'type' => 'files'
    ]
]);

@taufik-nurrohman taufik-nurrohman added this to the v3.0.0 milestone Nov 11, 2021
@taufik-nurrohman
Copy link
Member Author

if (str_ends_with($_['d'], '/get') && str_starts_with($_['type'] . '/', 'page/')) {
    // Is editing a page file and is in page editor mode
}

@taufik-nurrohman
Copy link
Member Author

taufik-nurrohman commented Dec 2, 2021

In Mecha 3.x.x, d and i property will be removed from URL data, including the form API.

---
asset:
  0: []
  1: []
  2: []
  #
  script: []
  style: []
author: null
can: []
description: null
file: null
folder: null
has: []
hash: null
icon: []
is: []
kick: null
lot: []
not: []
path: null
query: []
status: 200
title: null
type: null

@taufik-nurrohman
Copy link
Member Author

taufik-nurrohman commented Dec 2, 2021

All data stored in $_ variable must be primitive and can be easily encoded/decoded from/to JSON for easy data transmission.

Who know, someday I will have the chance to fully convert the panel extension into React or Vue thing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

No branches or pull requests

2 participants