Nao

  • Dadman with a boy
  • Posts: 16,082
Re: Template edits
« Reply #30, on February 2nd, 2013, 09:39 PM »
Woohoo, I just realized that by saving skeletons in their own files, I can actually get rid of the index template's skeleton now, and just include it in skin/skeleton.xml, and just consider that if a skeleton isn't found in a skin folder, it should use the parent folder's... :)
(Well, I *think* this is how it could and should be done. I haven't looked at the specifics yet. There may be another reason why I did it that way... But I don't think there was.)
(Then again, the index template's skin shows that it can be injected programmatically through wetem::build(). Maybe that's good enough a reason to keep it that way... But I'd probably rather have a 'sample plugin' that does the rewriting and build() calling by itself.)
Quote from Arantor on February 2nd, 2013, 09:16 PM
Hmm, yeah.
If we have everything in skeleton-*.xml, then skin.xml can stay skin.xml. Or be renamed to skin-info.xml (which I like less), to be consistent with plugin-info.xml. What do you prefer?
Quote from Arantor on February 2nd, 2013, 09:16 PM
msg as a suffix works just fine for me for the main post structure,
Could be message, too... There's no actual reason to go for a 'short' name.
Quote from Arantor on February 2nd, 2013, 09:16 PM
with blog for the main blog post and blog-msg for blog replies, as suggested.
Or 'blog-comment'. Would make more sense, semantically...
Quote from Arantor on February 2nd, 2013, 09:16 PM
Thank you :) Mostly it's just about making a UI that doesn't feel put together by developers.
Yup. Going the Wizard route is something that the early SMF devs tried to do (e.g. installer), but they stopped midway I guess. You're continuing their legacy.
Oh, and with my select box code, wizards just feel so cool to use. :lol:
Quote from Arantor on February 2nd, 2013, 09:16 PM
And for the look of Wedge, you do it very well :) I would even go as far as saying that your flair for making it look good has rubbed off on me, I never used to worry about making things look good.
Ah ah. But quite honestly, I'm still unhappy with so many things. I'm relatively happy with Weaving (I only changed the header font recently), I was very unhappy with Wuthering but the many changes I appled to it made it look much better. I don't know what to do about Wine, to me it's more a variation on Weaving that was mostly kept as a reminder that Wedge used to look like this by default. Once Warm and Wuthering become actual children of Weaving, I don't know if I'll include Wine in the default package (unless you want to.)
Finally, Warm is a bit of a bugger to me... I'm always tempted to drop most of its color set and go for something really "web 2.0" or whatever, with very bright and saturated colors... Oh, if you could see my local Warm... I'd never commit it, it's too.... It's just plain too much ;)

Arantor

  • As powerful as possible, as complex as necessary.
  • Posts: 14,278
Re: Template edits
« Reply #31, on February 2nd, 2013, 10:27 PM »
Quote
If we have everything in skeleton-*.xml, then skin.xml can stay skin.xml. Or be renamed to skin-info.xml (which I like less), to be consistent with plugin-info.xml. What do you prefer?
I'm not fussed either way. I could rename plugin-info.xml to plugin.xml to be honest ;) I'm not that fussed, skin.xml is fine with me, just as skin-info.xml is.
Quote
Could be message, too... There's no actual reason to go for a 'short' name.
Long names *are* more readable, yes.
Quote
Yup. Going the Wizard route is something that the early SMF devs tried to do (e.g. installer), but they stopped midway I guess. You're continuing their legacy.
Oh, and with my select box code, wizards just feel so cool to use. :lol:
I'm trying :)

Also...
WIZARD NEEDS FOOD BADLY.
Quote
Ah ah. But quite honestly, I'm still unhappy with so many things.
The sign of a true artist, continually evolving, striving to improve it all the time.
When we unite against a common enemy that attacks our ethos, it nurtures group solidarity. Trolls are sensational, yes, but we keep everyone honest. | Game Memorial

Nao

  • Dadman with a boy
  • Posts: 16,082
Re: Template edits
« Reply #32, on February 6th, 2013, 09:32 PM »
Okay, re: plugin-info.xml, to me it'd make more sense to have 'plugin.xml', but it's your 'area', so your preference matters more ;)

Regarding skeletons, I've been considering multiple ways of doing it these last few days, most of them 'unclean'.

So, the two that remain right now are these:
- the 'realistic' solution: wetem remains a singleton, but wetem::$skeleton becomes an array of skeletons. Same for wetem::$layers, etc. Has the advantage of being easy to transition. Can do wetem::render() to render the main skeleton, and wetem::render('message') to render a specific mini-skeleton. Drawback: not that it's necessary inelegant, but having a singleton to manipulate multiple objects can sound strange...
- the 'object-obsessed' solution: wetem becomes an actual object system, we'd then do $msg = new wetem('skeleton-message.xml'), or something like that. Then $msg->build(), then $msg->render(). Main advantage: it looks way better in the code... Main drawback: okay, I can't possibly imagine asking plugin authors to insert a global for $rootSkeleton (or something) and then call $rootSkeleton->add('sidebar', 'my_block') to add a block to the sidebar... This seems uglier to me than wetem::render('message').

I'm trying to figure out whether it's possible to have the best of both world, i.e. if wetem::render is called, then we automatically redirect to the $rootSkeleton object, and if $something->render() is called, render said object. I don't know whether that's possible right now... I could imagine storing the main skeleton inside its own static (or global?! meg...) variable, then relying on it if function render() doesn't find a qualified $this value. But, we'd have to do the same for add(), and so on...

So... Any opinions? I'm afraid I'm not in the best position to comment on object creation :P
Posted: February 6th, 2013, 03:48 PM

Adding to the question.
Both solutions are complicated IMHO...

- Staying static sort of feels like I'm from a procedural world (which is true), and that I'm trying hard to remain traditional while giving the appearance of working with an object.

- Going half static, half dynamic probably means I'm going to have to duplicate a lot of functions... One for mini-skeletons, one for the main skeleton. (Which I'm tempted to rename internally to 'backbone', dunno why :lol:) And that could be even more confusing. Just look at wetemItem: I'd have to rewrite it to address both the 'backbone' and any other skeleton. Because right now it's just acting like it's one big static skeleton. I'll give a try to mixing static and non-static functions and see how they behave when called dynamically and statically.

- Going fully dynamic would be the way to go, but as I mentioned earlier, I would absolutely hate having to force plugin authors to declare a global for backbone/root/main manipulation. I've given them power with so many methods -- I don't want this to be at the cost of simplicity in their main code. And don't get me started with $_GLOBALS['backbone']->build()... Alright? :lol:

---

Okay, it was too hard on me, I decided to immediately try for a simple version of the dynamic/static test I mentioned. Here's the code I tried... Note that all the class and method names are French synonyms of the word 'thing' :P

Code: [Select]
class truc
{
static function machin ()
{
echo 'Hello ', isset($this);
}
function bidule ()
{
echo 'World! ', isset($this);
}
}
error_reporting(E_ALL | E_STRICT);
truc::machin(); // Hello
truc::bidule(); // World!
$chose = new truc();
$chose::machin(); // Hello
$chose::bidule(); // World!
$chose->machin(); // Hello
$chose->bidule(); // World! 1

I'm surprised that I'm not getting any crashes, or even any warning from PHP at this point..?!
This was done with PHP 5.3.4, downgrading to 5.2.9 gave me a 'parse error' crash on both $chose:: lines, meaning only PHP 5.3+ supports using a static call from within a dynamic object. Or something... More 'interestingly', $chose::$any_static_variable doesn't work in PHP 5.2.9 either, even though the php.net docs seem to indicate otherwise.

So, it seems there's something that... could be done, I guess... Regarding using 'wetem::add()' for the main skeleton and '$other->add()' for other skeletons without duplicating the 'add' function -- something like if (!isset($this)) $skel = self::$skeleton; else $skel = $this->skeleton...??
It still makes life complicated and forces me to rewrite all functions to use a pointer to the desired array ($skeleton, $layers...), rather than directly access self::$layers or whatever.

I'm still not much used to all of this... It's really not my initial area of expertise. I think it's important that I get it right on the first try, which is why I haven't developed anything so far.
Waiting for opinions and ideas, then...!
Posted: February 6th, 2013, 05:49 PM

I may have found a solution...
http://www.php.net/manual/en/language.oop5.overloading.php#object.call

Basically, set all functions to be private. Calling wetem::add will invoke __callStatic, in which I'll first check through the list of authorized function names, then if allowed, redirect to that function while passing self::$instance as the instance, while $object->add will invoke __callStatic which does the same, but passes $this as the param.
I'm not sure it'll work... But it seems... possible?!
Posted: February 6th, 2013, 06:27 PM

F*ck! __callStatic (not __call) is PHP 5.3+ only... -_-
Posted: February 6th, 2013, 07:46 PM

Okay, there may be a possibility that it "just works"...

Code: [Select]
error_reporting(E_ALL | E_STRICT);
print_r(wetem::$skeleton);
$a = new wetem();
$a->skeleton = array('DELETED');
print_r($a->skeleton);
print_r(wetem::$skeleton);

(Of course, I removed the 'private' keyword for $skeleton.)
The first print_r gives me the main skeleton.
The second print_r gives me 'DELETED'.
The last print_r gives me the main skeleton.

So, it would seem that wetem:: acts just like a regular instance of wetem, and keeps the data associated to it.
Which is pretty good. And means I wasted more hours trying to fix a problem that didn't exist in the first place... :^^;:

Now, the only issue is that E_STRICT supposedly should/would return a warning when calling one of these, because it doesn't like to mix static and dynamic stuff.. But it doesn't give me anything.

Oh, bugger... Forget what I said.
Inside the $a instance, $this->skeleton gives me DELETED, while wetem::$skeleton gives me the main skeleton. I should have guessed...
So it's back to the isset($this) test on each function... Or giving up and using arrays for every instance. :(

Anyone..? I hate talking to myself all day... :whistle:

Dragooon

  • I can code! Really!
  • polygon.com has to be one of the best sites I've seen recently.
  • Posts: 1,841
Re: Template edits
« Reply #33, on February 7th, 2013, 05:25 AM »
Don't use magic functions, they're pathetically slow. Can't you simply declare static functions in a base class, declare a new singleton class for main skeleton extending the base which has calls to the parent class but also passes the first parameter and keeps everything sane? That or make a new class for only one skeleton (you need more than one?) which is singleton and has instance object to return the only instance that it has?
The way it's meant to be

Nao

  • Dadman with a boy
  • Posts: 16,082
Re: Template edits
« Reply #34, on February 7th, 2013, 09:53 AM »
Quote from Dragooon on February 7th, 2013, 05:25 AM
Don't use magic functions, they're pathetically slow.
But.. THAT slow?
They're only called if the method isn't found.

I've been thinking it over last night, and figured out I didn't really need to have __callStatic...
I can simply implement __call, and then pass all the information about the current object to the static wetem object.
For instance, $message->build() would magically call __call(), which would then pass the data to wetem::build($message->id_object) or something. For instance, I could store the contents of the static object into a temp var, replace the static object's vars with the dynamic object's, call the static function, then replace the static object vars with the temp vars.
Of course it's going to be much slower... But we're talking about relatively small arrays. My only concern is with calling these things repeatedly... It'd be better, I guess, to have a dynamic object in the first place and __callStatic to bind the backbone to a dynamic object, because wetem we know isn't being accessed a lot. But we don't have that leisure, as __callStatic is PHP 5.3 only. Unless Pete wants to reconsider our minimum PHP version. But that particular use case probably wouldn't be enough to justify it...

Then again, we could also simply use arrays of arrays. wetem::$skeleton['backbone'], wetem::$layers['backbone'], things like that...
Quote
Can't you simply declare static functions in a base class, declare a new singleton class for main skeleton extending the base which has calls to the parent class but also passes the first parameter and keeps everything sane?
But that's pretty much like one of my first suggestions, duplicating everything...?
Well, now I guess we could hmm... Well we don't have that many public methods in the object in the first place, that's true.

(I also liked having the 'final' keyword on wetem... It's the only time I ever used it, and because I use it in Class-CSS, it sounded cool to also have it in a proper PHP class :lol:)
Quote
That or make a new class for only one skeleton (you need more than one?) which is singleton and has instance object to return the only instance that it has?
But it would thus require to do wetem::getInstance() every time we want to access the main skeleton. To me, it's exactly the same as doing a global $backbone thingy... Isn't it?

I'd really like more of your input on this, as well as Pete's -- and anyone who's into OOP really. (Yeah, OOP, not the other word I used last time, remember Shitiz :lol:)

Dragooon

  • I can code! Really!
  • polygon.com has to be one of the best sites I've seen recently.
  • Posts: 1,841
Re: Template edits
« Reply #35, on February 7th, 2013, 10:25 AM »
Quote
But.. THAT slow?
They're only called if the method isn't found.
Benchmark them, AFAIK they're atleast 10-20 times slower than direct calls.
Quote
But that's pretty much like one of my first suggestions, duplicating everything...?
Well, now I guess we could hmm... Well we don't have that many public methods in the object in the first place, that's true.
You're not really duplicating, you're just making the child function call its parent.
Quote
But it would thus require to do wetem::getInstance() every time we want to access the main skeleton. To me, it's exactly the same as doing a global $backbone thingy... Isn't it?
Maybe, but IMO getInstance is better. Simply because wetem::getInstance is more verbose than a global variable called $backbone, secondly as far as clean code goes we need not have it at the top of the function and can place it anywhere. That, and a jackass function can't overwrite it with it's own stuff.
Code: [Select]
$backbone = null; // Have fun suckers!

Or here's another fun idea, make a base template class (dynamic, ofcourse) which is not a singleton. Then make a singleton class which is the main skeleton (extend it and make the constructor private and add getInstance), use it for the backbone skeleton and add a function in base class that can import full skeletons from an instance of the class to that class. This way a mod can do something like create it's own skeleton, and import it to the main skeleton.

Arantor

  • As powerful as possible, as complex as necessary.
  • Posts: 14,278
Re: Template edits
« Reply #36, on February 7th, 2013, 04:58 PM »
Quote
Or here's another fun idea, make a base template class (dynamic, ofcourse) which is not a singleton. Then make a singleton class which is the main skeleton (extend it and make the constructor private and add getInstance), use it for the backbone skeleton and add a function in base class that can import full skeletons from an instance of the class to that class. This way a mod can do something like create it's own skeleton, and import it to the main skeleton.
I think this is the way it's going to go. ;)

Nao

  • Dadman with a boy
  • Posts: 16,082
Re: Template edits
« Reply #37, on February 7th, 2013, 05:15 PM »
Yep, except I don't understand that suggestion... ;)

Using functions is something I considered yesterday too, doing things like wetem_add() that would redirect to wetem::getInstance()->add(), but it's even more overhead... Imagine that: a function call, then a static call, then a dynamic call...
I could rename getInstance() to something more 'direct', like wetem::backbone(), but it's still too long. wetem::main()->add() simply feels odd to me. I don't really know where this is going...

All I can say is, I did a last attempt at making a static class that extends on the dynamic one, and call $this everywhere. No functions at all inside the static class. Not surprised here: it all works... until the dynamic methods get called and try to access $this. It's a bit annoying, but it's as it is...
Re: Template edits
« Reply #38, on February 7th, 2013, 05:33 PM »
So... I wrote this.
I dislike the list of functions, but I made them one-liners, so it basically looks a lot like wetemItem.

Code: [Select]
final class wetem extends weSkeleton
{
private static $instance = null; // container for self

// What kind of class are you, anyway? One of a kind!
private function __clone()
{
return false;
}

// Bootstrap's bootstraps
static function getInstance()
{
// Squeletto ergo sum
if (self::$instance == null)
self::$instance = new weSkeleton();

return self::$instance;
}

function has($item) { return wetem::getInstance()->has($item); }
function has_block($block) { return wetem::getInstance()->has_block($block); }
function has_layer($layer) { return wetem::getInstance()->has_layer($layer); }
function build(&$arr) { wetem::getInstance()->build($arr); }
function render() { wetem::getInstance()->render(); }
function get($targets = '') { return wetem::getInstance()->get($targets); }
function before($target, $contents = '') { return wetem::getInstance()->before($target, $contents); }
function after($target, $contents = '') { return wetem::getInstance()->after($target, $contents); }
function remove($target) { wetem::getInstance()->remove($target); }
function move($item, $target, $where) { return wetem::getInstance()->move($item, $target, $where); }
function parent($child) { return wetem::getInstance()->parent($child); }
function load($target, $contents = '') { return wetem::getInstance()->load($target, $contents); }
function add($target, $contents = '') { return wetem::getInstance()->add($target, $contents); }
function first($target, $contents = '') { return wetem::getInstance()->first($target, $contents); }
function replace($target, $contents = '') { return wetem::getInstance()->replace($target, $contents); }
function rename($target, $new_name) { return wetem::getInstance()->rename($target, $new_name); }
function outer($target, $new_layer = '') { return wetem::getInstance()->outer($target, $new_layer); }
function inner($target, $new_layer = '') { return wetem::getInstance()->inner($target, $new_layer); }
function hide($layer = '') { return wetem::getInstance()->hide($layer); }
function layer($layer, $target = '', $where = 'replace') { return wetem::getInstance()->layer($layer, $target, $where); }
}

Fact is... It seems to be working. The original wetem class is now weSkeleton, and is entirely dynamic.
What do you think..? Is it worth calling functions that will simply redirect to... These anyway?
Well, I think I could event get away with wetem::getInstance() calls by simply using self::$instance. I'm going to do that, as getInstance() is always called at startup anyway.
Re: Template edits
« Reply #39, on February 7th, 2013, 06:02 PM »
'kay, I've done everything I said, and also rewrote a bit of wetemItem (renamed to weSkeletonItem) to handle both wetem and weSkeleton objects.

And I'm happy to report... That it's all working just fine :)

With the added benefit that a dynamic class is (very slightly!) faster than a static one, this should help alleviate some of the load on our future message skeleton (considering it'll be rendered 15 times per pages... It's always best to put the priority on this rather than on the main skeleton, which is only rendered once.)

So... Do you think I should keep my code as modified, or I should ditch wetem:: altogether and use either a global $skeleton or a series of functions...?

Or even something I just thought of... Well, a bit silly but...

wetem()->load()

function wetem()
{
  static $instance;
  if (!$instance)
   $instance = new weSkeleton();
  return $instance;
}

Lol... This is actually ALL I would need in the entire codebase... No need for the wetem object anymore, no need for function duplication. Hmm. And to think I didn't think of that silly little 4-line function until NOW..!

wetem()->load() or wetem::load()? Which one looks best to you? Which would you rather see used in Wedge..?

Arantor

  • As powerful as possible, as complex as necessary.
  • Posts: 14,278
Re: Template edits
« Reply #41, on February 7th, 2013, 07:57 PM »
* Arantor has several copies of this tab open now at differing levels of the topic :/

wetem()->load() is unusual. It's fine, of course, but it feels unusual to write. wetem::load() would be better.

* Arantor can't mentally deal with thinking through all the other consequences right now.

Nao

  • Dadman with a boy
  • Posts: 16,082
Re: Template edits
« Reply #42, on February 7th, 2013, 09:12 PM »
Quote from Arantor on February 7th, 2013, 07:57 PM
* Arantor has several copies of this tab open now at differing levels of the topic :/
Oh, I have hundreds of tabs with dozens of topics open... 99% of which will never be closed!
Quote
wetem()->load() is unusual. It's fine, of course, but it feels unusual to write. wetem::load() would be better.
Plus I don't need to update the hundreds of existing calls... ;)
Quote
* Arantor can't mentally deal with thinking through all the other consequences right now.
There are no consequences whatsoever. The only things to think about are ease of use, and performance.

Arantor

  • As powerful as possible, as complex as necessary.
  • Posts: 14,278
Re: Template edits
« Reply #43, on February 7th, 2013, 09:30 PM »
Performance is a big consequence to me as well as ease of use.

I don't really mind ease of use being changed provided it's not made insanely hard to use. The current setup is not that hard to use, which is fine with me.

Nao

  • Dadman with a boy
  • Posts: 16,082
Re: Template edits
« Reply #44, on February 7th, 2013, 09:45 PM »
I don't think there's a significant difference between a function call and a static method call.