Wedge

Public area => The Pub => Topic started by: Nao on December 23rd, 2012, 11:26 AM

Title: Context object?
Post by: Nao on December 23rd, 2012, 11:26 AM
I'd also like to create a cx (context) object. Not with the usual 'we' prefix, I know, but the idea is to keep it very, very short, and 'we' is already taken for the system class, although we MIGHT be able to use 'we' instead and just have we::$user behave like if it is was $context['user'], or whatever.

The main problems are:
1/ Performance. $context is used in TONS of areas, including time-critical code, so it's going to be hard to tell people to use 'cx::$var' instead of '$context['var']' in these areas. So we'd need to keep having a global point to the array.
2/ Because of (1) and general laziness from devs who might have $context so deeply carved into their DNA, we could/should/might use $context =& we::$cx, or cx::$cx, or something, but that means we can't use cx::$var, but instead we::$cx['var'], which only saves one byte compared to $context['var']. We could go as far as we:$c['var'], but even then, it's a bit ugly and all anyway...
3/ Some people might argue that we could simply rename $context to $cx, and be done with it, accept globals and that's it. :P

I'm looking into other solutions... So far I've found a strange one, which could work but only for variables that never change...
$context = get_object_vars(cx::getInstance());

This will effectively transform cx::$var into $context['var']. Seriously. But I'm guessing that, even without benchmarking it, this function call is not 'free' and thus can only be done on purpose at one point or another...

Ahhhhhhh... If only accessing a singleton variable was just as fast as accessing a global var! Why does it have to be about 60% slower..?!
Title: Re: Context object?
Post by: Arantor on December 23rd, 2012, 01:38 PM
Because of the fact you're addressing an object statically rather than actually addressing a variable. It is much the same overhead as calling a function - classes live in the same sort of place as functions and addressing is handled in much the same way.
Title: Re: Context object?
Post by: Nao on December 23rd, 2012, 04:06 PM
Nope, remember... we::$var is 60% slower than $var, while we::get('var') with function get ($v) { return self::$$v; } or something like that would be something like 1000% slower... So it's definitely better to use method static variables than functions to retrieve a variable that's not within our scope.

Other than that, I'd like to know if any of these ideas made sense to you... ;)
Title: Re: Context object?
Post by: Arantor on December 23rd, 2012, 04:13 PM
The reason is that it has to do lookups to find the class and the way it does that is much the same as the way it looks up defined functions...

I have no problem with telling people not to be lazy. So if that means they have to learn not to use $context, that's fine with me.

I'm not opposed to such a class but it might be better served with other kinds of refactoring and making sure that what goes into $context actually needs to go into $context. Of course, when in loops it can always be pulled into a local variable, acted upon and if needed, later pushed back to $context.
Title: Re: Context object?
Post by: Arantor on December 31st, 2012, 07:42 PM
Ahhhh.

Now I remember why we::$user or similar wouldn't work for me when I first tried it... it's PHP 5.3 only. We just effectively made Wedge PHP 5.3+ only.

When I previously tried it I was still using PHP 5.2 which is why it wouldn't work.
Title: Re: Context object?
Post by: Nao on December 31st, 2012, 11:17 PM
I probably forgot to declare the variables as static.
Can you verify it works if you do that? I'm pretty sure it does. 5.3 only allows NOT specifying the static keyword and still being able to access it.
Title: Re: Context object?
Post by: Arantor on December 31st, 2012, 11:23 PM
Given that it appears to be run through the LSB code which is 5.3+ only and it's even specifically referred to in the Zend PHP 5.3 certification as such...
Title: Re: Context object?
Post by: Nao on December 31st, 2012, 11:42 PM
I dont get it?

Im just saying, in we::$user, we need to declare public static $user instead of just public $user. Is that the case? I'm not in front of my computer for now...
Title: Re: Context object?
Post by: Arantor on December 31st, 2012, 11:48 PM
And I'm saying that as far as I'm aware, that won't work before PHP 5.3 for calling it outside the class.

I'm taking the Zend certification in two weeks, so I'm reading up, and in the study guide for PHP 5.3 it actually mentions this and says that it should only work in 5.3+, suggesting that it is reliant on the implementation of Late Static Binding (which would also explain the performance hit)

Mind you, I've found multiple other issues in the study guide so it wouldn't surprise me if it were actually wrong anyway. All I know for certain is, I tried to do something much the same a couple of years ago and it baulked at it because it was PHP 5.2. Whether something is slightly different or not, I don't know. Whether I did something different or not, I don't know. But I was following much the same basic approach then and it didn't work.

And I'm concerned that this effectively makes PHP 5.3 a minimum for Wedge. I'm not entirely convinced that's a bad thing, though.

I have to admit my temper is *a lot* shorter in recent times. I don't like Christmas. I don't particularly like New Year. I've spent a lot of time trying to make sense of all the changes to we::* to figure out why stylesheets aren't rendering properly any more (at all) and given up hoping that it'll just be fixed some time so that I can actually navigate the admin menus again... combined with the fact that I basically wrote all those little things last night to feel like I'm actually doing something useful rather than spending weeks farting around with something that just feels like a total waste of time.
Title: Re: Context object?
Post by: Nao on January 1st, 2013, 12:54 AM
I'll have a look when I'm on my pc.
Everything works fine for me locally, otherwise I wouldn't have committed. I'm very surprised.  Hopefully this won't represent the quality of my work in 2013 ;)
Title: Re: Context object?
Post by: Arantor on January 1st, 2013, 01:03 AM
Well, I found another bug that I've caused by my removal of loadUserSettings, which I've fixed locally, but ever since we was introduced, stylesheets are compiled but there's nothing browser specific in them, meaning menus don't have a background (which makes then practically unusable), the error log counter etc. is invisible, the background to the page is not a nice gradient but instead just blue, etc.

As far as my last point goes, yes, I could just ignore the whole package thing and just remove the add plugin setup, instead of faffing around understanding the zip format and making a nice class instead of the crap I found online (I think you'd rather I committed something around 80KB instead of a 199KB library, for example) and I'm just pissed off with how much work has gone into it with no visible benefits yet.
Title: Re: Context object?
Post by: godboko71 on January 1st, 2013, 02:00 AM
Yet being the key word. You are doing great worK both of you. As for 5.3 hard to say its a bad thing really might annoye some.
Title: Re: Context object?
Post by: Arantor on January 1st, 2013, 02:03 AM
That's the thing, I'm not really the delayed gratification type. I like to see visible signs of progress as I go. The thought of spending two weeks staring at a piece of crap code[1] and without anything to show for it except a strong dislike of anyone else's code... yeah, it's as frustrating as it sounds.

After two weeks of attacking it, stripping it down to half size, I realised it could be done further but it would at that point be quicker just to start fresh, which I did.
 1. In his defence, he's written it as a C-style PHP script, not as a PHP destined one, so using p_ and v_ prefixes to indicate that things are pointers and local vars, not to mention dancing around returning 1 and 0 everywhere rather than actually returning values from functions. But it's still frustrating to have to clean up, especially the crazy ass indentation.
Title: Re: Context object?
Post by: Nao on January 1st, 2013, 02:58 AM
Pete -- I just can't seem to be able to install PHP 5.2 on my PC. It keeps sending me a connection error in WampServer, even though I followed the pretty straightforward install process. Anyway, problem is -- the system object DOES have 'static' keywords in front of our variables like $user. So it really should be working in PHP 5.2... I've even seen comments to that effect on the web.
Maybe (but it's very unlikely) you need to add '&' in front of the getInstance method in the object, to return a reference, but I don't see why that would change anything.
Anyway, I found this:
http://www.nqbao.com/2009/11/the-best-way-to-access-PHP-global-variable
The guy runs PHP 5.2.9 and look at solution #7... It's the same as mine, pretty much, only very simplified.
So I'm guessing it does work in PHP 5.2, it just doesn't work for you in that particular fashion.

Re: stylesheets, the main problem is that my own local version is uncommitted because it makes so many little changes here and there... I don't know exactly if committing them immediately would fix your problems.

Re: zip class, I don't know any better... I think a 80KB library is overkill already. But that's just me... If it makes life easier for everyone...
Title: Re: Context object?
Post by: Arantor on January 1st, 2013, 03:13 AM
I could have sworn that it wouldn't work. I don't know what I did differently that made it not work, and when I stumbled on the reference to it in the study guide, I figured that it was all related, and it probably is. I don't know. I just don't want to compromise Wedge working on PHP 5.2.

The problem with stylesheets isn't the content of the stylesheet itself as such, but the content of the WeCSS loader/handler barfing over we::something. I don't know anywhere nearly enough to even begin debugging.

Re: zip class. Well, the choices are simple.
1) We don't have add plugin or auto update at all.
2) I add a 199KB class that is beyond ugly.
3) I finish writing my own class that does the job. It'll be usable when finished. The thing is it's a complete Zip class, not just the minimum required for extracting files. If I thought that was acceptable, I'd do that, but I can see the benefits of a full zip class that I can redistribute separately as well.


Also: with what I'm working on, I'm going to be adding a copy of jQuery UI. Primarily for the sortable unit but it seems that for the admin panel we could just include and be done with it. I don't have the patience or mindset to sit and write my own sortable/draggable component right now, I'd rather just run with a proven and stable one for the time being but if anyone wants to write a newer, less bulky one, go nuts. Just don't break anything :P
Title: Re: Context object?
Post by: Arantor on January 2nd, 2013, 11:14 PM
Just as a quick footnote, I realised that in actuality a zip creation library is not really needed - we already have a limited one as it is. So I'm just going to shave that stuff off and concentrate on it being a read library as I originally intended. Much closer to 18KB than 80KB.
Title: Re: Context object?
Post by: Nao on January 2nd, 2013, 11:56 PM
Good :)

Also please confirm that we::$browser now works as intended? It does for me. php 5.2 with apache 2.2.11.
Title: Re: Context object?
Post by: Arantor on January 2nd, 2013, 11:57 PM
I haven't got PHP 5.2... haven't had it in almost a year... but back a year or so ago I was trying to make a weusr object and it wasn't working :/

If it's working for you, it'll almost certainly work for everyone else. But I'm going to be doing some real testing on real hosting before long (not a VPS I have total control over)
Title: Re: Context object?
Post by: Nao on January 3rd, 2013, 05:41 PM
Quote from Arantor on January 2nd, 2013, 11:57 PM
I haven't got PHP 5.2... haven't had it in almost a year... but back a year or so ago I was trying to make a weusr object and it wasn't working :/
I see. Perhaps you forgot to add a static keyword to the variable? Which would be surprising...
Anyway, I can assure you that it works in all situations I tried.
Quote
If it's working for you, it'll almost certainly work for everyone else. But I'm going to be doing some real testing on real hosting before long (not a VPS I have total control over)
Lulz.

Okay, I'll be posting my comments on your latest commits here...

- ManageBans.english.php: this has exclusively $txt['ban_*'] entries, some of which are still present in other files. Do you think these other files have to be cleaned up, or they really need these entries separately from a custom loadLanguage('ManageBans') call...? It'd be nice to look into this.

- Actually a commit of mine...: I was wondering... Is ::getInstance() really THAT useful? I did a few class_exists('we') calls which I later realized return true not after calling we::getInstance(), but instead simply after loading the class file. Also, Wedge never actually requires getting an instance to treat it (for instance to get a list of variables or whatever, like I suggested in another post in this topic), so the only 'point' is to prevent getting two instances... However, it can also be done by providing a dummy __construct, a dummy __clone, and basically: what's the need for that..? Admins and users have no need for these, and plugin authors are unlikely to try and get an instance either (they'll 'do it' the way we do it, because they'll look at our code). So, I'd suggest simply having init() functions when needed (e.g. we object), and not bothering with calling new self() anywhere. Obviously, tested on PHP 5.2. One of the advantages is that you no longer need the strange call_array_func function call in Class-DB to extend the DB object. Because it doesn't do anything anyway... As you're more versed into objects than I am, please advise.

- Haven't tested your badge display order changes yet, but I was wondering... Couldn't my earlier system be replaced with yours? Or does it need both the display order thing and show_when stuff? (I'm not sure it can't be replaced with a negative value or whatever..?) I'm probably wrong, though. :)

- I liked, as a regular user, being able to view my own IP, so that I can determine if I'm on a dynamic or static IP. Though, it's also true that only power users would do that, and they'd usually have other ways to determine that... Or they'd own their own forum like I do, and check their IPs on them. ;)

- While I certainly don't mind you using British English in your comments (you are, after all, Her Majesty's subject), I'd like to point out that you're also using it in the language files (e.g. 'organise'), which is different -- AFAIK the language files are in US English, and British versions are to be provided in addition to them, not as replacements. I don't care what phpBB does, I just don't want to mix up British and US English, I already do it too much personally, but I have an excuse for that :lol:

More to (possibly) come later...
Title: Re: Context object?
Post by: Arantor on January 3rd, 2013, 10:07 PM
Quote
- ManageBans.english.php: this has exclusively $txt['ban_*'] entries, some of which are still present in other files. Do you think these other files have to be cleaned up, or they really need these entries separately from a custom loadLanguage('ManageBans') call...? It'd be nice to look into this.
Yup, I'm aware of that. They are going to be cleaned up in due course when I finish the rest of the UI. Mostly it's going to be pushed to the ManageBans file, the only stuff actually needed in the main admin language file is stuff that is needed for the main admin menu itself.
Quote
- Actually a commit of mine...: I was wondering... Is ::getInstance() really THAT useful? I did a few class_exists('we') calls which I later realized return true not after calling we::getInstance()
Well, it's sort of required, if you're not calling getInstance(), you need to do something else to instantiate it and its content. Just loading it isn't enough.
Quote
Also, Wedge never actually requires getting an instance to treat it (for instance to get a list of variables or whatever, like I suggested in another post in this topic),
So if you don't get the instance, how exactly does it get any of its content? Just loading it is not enough.
Quote
so the only 'point' is to prevent getting two instances...
That's the other aspect to it. Really though it's about a sense of correctness as well as anything else. The whole point of creating singletons as true singletons is to prevent them being abused, in particular around the class properties.

Classes aren't just a specific way of breaking functionality up, they're also there for protecting class parameters from outside the class. For example, the template list can only be modified from within the wetem class. In the case of user information and permissions, I'd argue that we::* should be keeping that as a private member if it isn't already, because there is no reason the permissions need to be exposed outside the we object except for allowedTo(), and arguably that should be a method of we::* anyway, as should loading permissions really.
Quote
One of the advantages is that you no longer need the strange call_array_func function call in Class-DB to extend the DB object. Because it doesn't do anything anyway... As you're more versed into objects than I am, please advise.
I've been tempted more than once to rewrite that in some fashion to clean it up, it's mostly a thinly veiled port of how it was done before.
Quote
- Haven't tested your badge display order changes yet, but I was wondering... Couldn't my earlier system be replaced with yours? Or does it need both the display order thing and show_when stuff? (I'm not sure it can't be replaced with a negative value or whatever..?) I'm probably wrong, though.
Your earlier system just got a little supersized. All I did was put a UI to what you'd implemented with show_when and then been able to set the *order* of badges to be displayed. For example, I know one site that uses a forum to manage its software development, and there are teams such as Map-Maker, Graphic Designer, Administrator and some others. This way, they could put the badges in whatever order they liked, regardless of what the user's primary group may actually be - that other forum puts them all in alphabetic order for example.
Quote
- I liked, as a regular user, being able to view my own IP, so that I can determine if I'm on a dynamic or static IP. Though, it's also true that only power users would do that, and they'd usually have other ways to determine that... Or they'd own their own forum like I do, and check their IPs on them. ;)
I give you http://www.whatsmyip.org/
Quote
- While I certainly don't mind you using British English in your comments (you are, after all, Her Majesty's subject), I'd like to point out that you're also using it in the language files (e.g. 'organise'), which is different -- AFAIK the language files are in US English, and British versions are to be provided in addition to them, not as replacements. I don't care what phpBB does, I just don't want to mix up British and US English, I already do it too much personally, but I have an excuse for that :lol:
That's mostly just a mental lapse. It's hard work for me to consciously use bastardised English.
Title: Re: Context object?
Post by: Arantor on January 4th, 2013, 01:05 AM
Also, I looked at r1825. Thanks for fixing my typo :)

As to the other changes regarding the we object, the change of __clone, yes, technically it can be a void method though returning false is more 'correct'.

As to the other loading, it doesn't matter whether we::* is defined or not, because that's not really the problem. The problem is that the permissions haven't been loaded yet, and we::* doesn't deal with permissions anyway other than storing them. There should never be any reason to check permissions prior to permissions being loaded, other than the fact topic privacy is currently fatally broken.

I think I'm going to have to implement what I said about fixing permissions before, and restructuring it entirely. Ugh, not looking forward to that, but I guess it's got to be done. Let me tackle that job, because I know what I have in mind, and it has a lot more consequences than just the loading order.
Title: Re: Context object?
Post by: Dragooon on January 4th, 2013, 07:32 AM
Singleton's __clone can also be private, just nuke the entire thing :P.
Title: Re: Context object?
Post by: Nao on January 4th, 2013, 05:02 PM
Quote from Arantor on January 3rd, 2013, 10:07 PM
Yup, I'm aware of that. They are going to be cleaned up in due course when I finish the rest of the UI. Mostly it's going to be pushed to the ManageBans file, the only stuff actually needed in the main admin language file is stuff that is needed for the main admin menu itself.
Well, good that you're aware of it. I like things clean. Enough work for translators already with the new strings... :)
Maybe we should do a script that takes all $txt[] strings and tests for them in the entire file set. If not found, add to a 'suspicious list' where we'll manually check that these strings aren't at least used in some more complex manners like string building ($txt['we_' . $string]), etc...
Quote
Well, it's sort of required, if you're not calling getInstance(), you need to do something else to instantiate it and its content. Just loading it isn't enough.
It's very odd. If I just call we::init_user() and we::init_browser(), it works. If I load wedb without initializing it, it doesn't work. Does that mean we need to call a random method on the object in order for PHP to initialize it..?!
Quote
So if you don't get the instance, how exactly does it get any of its content? Just loading it is not enough.
Well, as it's a static object (at least static public methods...), with static variables in it, technically I guess PHP doesn't need to instantiate the object in the first place..? I don't know. I'm trying to learn.
Quote
For example, the template list can only be modified from within the wetem class.
Yup, it's my only case of building a 'true' object, and making a 'clean' use of method visibility to simplify life for plugin/theme authors. It's actually what convinced me that objects can sometimes be more beneficial than procedural programming (I was fiercely opposed to objectifying anything before that... :P), but in the case of the system object, it's only static, it's not a 'real' object per se, although if you start moving allowedTo() over there, I guess it'll have to be... (Oh, how about a generic we::can(...) function? Lol.)
Quote
In the case of user information and permissions, I'd argue that we::* should be keeping that as a private member if it isn't already, because there is no reason the permissions need to be exposed outside the we object except for allowedTo(), and arguably that should be a method of we::* anyway, as should loading permissions really.
I have no qualms with $user['permissions'] being private, actually I have no qualms with perms being moved to their own array outside $user, etc...
Quote
I've been tempted more than once to rewrite that in some fashion to clean it up, it's mostly a thinly veiled port of how it was done before.
I thought the comment next to that line sounded like you... What was the original implementation? I mean, if it's not using static late binding (because of compatibility), how did it do it? Multiple lines I guess? Can't bother to check it out...
Quote
I give you http://www.whatsmyip.org/
That's not what I meant... I had interest in seeing my IP's evolution over multiple messages, rather than my IP at the current moment. For instance, these days, my IP has been very static, it hasn't changed in weeks, perhaps months actually, even though officially I'm supposed to be on a dynamic IP... Things like that, I like being able to check. And I shall check that one. :P
Quote
That's mostly just a mental lapse. It's hard work for me to consciously use bastardised English.
I feel for you. But just as my fellow Québecois cousins managed to gently bastardize French their own way, the 'main' language in here (as in 'used by the most people') is metropolitan French, i.e. they're the ones who have to take it on themselves to 'speak French' rather than Québecois when they want to address an international French audience. Same for the British... Because Americans can't stop thinking about sex, today the British have to speak American when they want to adopt a 'neutral tone'. Reminds me of that skit in The Meaning of Life... :lol:

Anyway! Can you check it out?
Quote from Arantor on January 4th, 2013, 01:05 AM
Also, I looked at r1825. Thanks for fixing my typo :)
You're welcome. I like to think my annoying diff reading sessions can sometimes help me catch a bug we wouldn't have found until much later otherwise. ;)
Quote
As to the other changes regarding the we object, the change of __clone, yes, technically it can be a void method though returning false is more 'correct'.
Shorter function = more space for 'public' keywords, the very ones I complained about... :P
Quote
There should never be any reason to check permissions prior to permissions being loaded, other than the fact topic privacy is currently fatally broken.
Do you mean that this particular issue is caused by my topic privacy implementation...? Ooops. (Well, it's not even 'officially implemented' yet... And I doubt it'll ever be, because of all the performance issues we discussed?!)
Title: Re: Context object?
Post by: Arantor on January 4th, 2013, 06:46 PM
Quote
It's very odd. If I just call we::init_user() and we::init_browser(), it works. If I load wedb without initializing it, it doesn't work. Does that mean we need to call a random method on the object in order for PHP to initialize it..?!
I don't know how you're calling wedb...
Quote
Well, as it's a static object (at least static public methods...), with static variables in it, technically I guess PHP doesn't need to instantiate the object in the first place..? I don't know. I'm trying to learn.
That's the thing... if it is a object with static variables, the variables don't exist until they are set as such.
Quote
It's actually what convinced me that objects can sometimes be more beneficial than procedural programming
They're a tool, nothing more. What they really do is allow common groups of procedural functions, especially if they have data that is common to those functions, to be grouped together in one place. Especially if that data that the functions want to share doesn't need to go outside the group - e.g. DB connection resource.
Quote
That's not what I meant... I had interest in seeing my IP's evolution over multiple messages, rather than my IP at the current moment. For instance, these days, my IP has been very static, it hasn't changed in weeks, perhaps months actually, even though officially I'm supposed to be on a dynamic IP... Things like that, I like being able to check. And I shall check that one.
Therein lies the subtlety. If you're the admin, you have the ability to issue bans, therefore you can see IP addresses... it's really only an issue for those who can't issue bans, and most of the time those people aren't the webmaster ;)
Quote
Anyway! Can you check it out?
Sure I can, when I handle my next commit. This one's a bastard, though. If I were to say that I made a synopsis of what it needs to do and that was a list of 46 items in a row to be executed. I'm barely 6 lines into the list and already that's another 100 lines of code on top of the 18K class I already wrote... I could be here a while.
Quote
I thought the comment next to that line sounded like you... What was the original implementation? I mean, if it's not using static late binding (because of compatibility), how did it do it? Multiple lines I guess? Can't bother to check it out...
The original implementation was all about $smcFunc. Back in $smcFunc days, $smcFunc was an array containing the names of functions to call in certain circumstances. db_extend would load the file referenced, then extend the contents of $smcFunc to refer to the newly loaded functions. I pretty much just turned that into some crazy class thing, rather than doing what I should have been doing, which was trimming what wasn't necessary and making a more sane method of calling those extra functions.
Quote
Do you mean that this particular issue is caused by my topic privacy implementation...? Ooops. (Well, it's not even 'officially implemented' yet... And I doubt it'll ever be, because of all the performance issues we discussed?!)
I'm not entirely convinced it's 100% right in SMF either. The problem is that post approval is checked very, very early - and before permissions are loaded. This has actually been an issue for months, I first documented it here back in November (private topic, id 7677 in the team board), but back then there were no visible signs, because allowedTo() just returned false for it.

But now the bug is more visible. Checking whether we is defined won't fix it, because it will be defined, it just won't have had permissions loaded (which should *really* be a method of the class anyway)

There is a sort of cyclic dependency issue - we can't load permissions until we know what board we're trying to access, and we can't load the board without knowing something about permissions (since loading the board is when we figure out topic privacy and that's dependent on permissions). We could juggle the ordering around a bit, I guess, but really what we should be doing is overhauling it entirely and that would have other consequences that need to be attended to.

I've already outlined how I think it should be overhauled, both structurally and semantically but when I'm not stuffed up with cold and overflowing with zip file craziness, I'll explain how I think it should work, what the consequences are for the admin panel / permissions UI and the rest of the codebase are etc.
Title: Re: Context object?
Post by: godboko71 on January 4th, 2013, 11:50 PM
I hate colds
Title: Re: Context object?
Post by: Nao on January 5th, 2013, 02:38 AM
Quote from Arantor on January 4th, 2013, 06:46 PM
I don't know how you're calling wedb...
I meant wesql.
And it works really... Just rename __construct() to getInstance(), and remove the other getInstance() function... Voilà, it works perfectly that way too.
As long as you only access an object with static methods or variables, you don't need to instantiate it. That's why I'm tempted to remove getInstance() calls and replace them either with nothing, or with init() functions when needed. It makes things clearer IMHO.
Quote
That's the thing... if it is a object with static variables, the variables don't exist until they are set as such.
Really, you should try... I was the first surprised. Just include Class-System.php in a blank PHP file, and then immediately do:

echo we::$is_admin === null; // returns 1
echo we::$non_existent_variable === null; // returns error

This means an object's static members can be accessed as soon as the object is declared.

Also, I'm becoming serious about doing we::can('moderate_forum') instead of we::allowedTo(), it does seem very readable and blends in nicely with the we::is() function.
Quote
Therein lies the subtlety. If you're the admin, you have the ability to issue bans, therefore you can see IP addresses... it's really only an issue for those who can't issue bans, and most of the time those people aren't the webmaster ;)
Yeah, that's what I was saying: it's pretty much a moot point because I've been doing something only geeks would do, and most forum geeks already have a forum of their own...
Quote
Sure I can, when I handle my next commit. This one's a bastard, though. If I were to say that I made a synopsis of what it needs to do and that was a list of 46 items in a row to be executed. I'm barely 6 lines into the list and already that's another 100 lines of code on top of the 18K class I already wrote... I could be here a while.
Well, as long as it doesn't reach the size you had before..?
I'd be tempted to say, why not just use the default zip loading classes and be done with it..? What do you need that they don't support?
Quote
But now the bug is more visible. Checking whether we is defined won't fix it, because it will be defined, it just won't have had permissions loaded (which should *really* be a method of the class anyway)
Can't we just do a backtrace on allowedTo() and catch the place where it's done wrongly, and then add a flag to disable permission testing if they're not loaded in the first place...? Then maybe call that function again later when permissions are loaded, to 'confirm' the actual user rights. Seems feasable to me, and most importantly, it saves time. I don't like seeing you waste time reinventing the wheel just to avoid a minor hack... SMF/Wedge are full of hacks, that never killed anyone.
Title: Re: Context object?
Post by: Arantor on January 5th, 2013, 02:58 AM
Quote
And it works really... Just rename __construct() to getInstance(), and remove the other getInstance() function... Voilà, it works perfectly that way too.
I'm sure there was a specific reason for NOT doing it that way, but I forgot what it is.
Quote
As long as you only access an object with static methods or variables, you don't need to instantiate it. That's why I'm tempted to remove getInstance() calls and replace them either with nothing, or with init() functions when needed. It makes things clearer IMHO.
So instead of having getInstance() calls, we're going to have init() calls. Means the same thing, yes? But I'm still sure there's a reason why it was done the way it was done rather than what you're doing. I'm also a little annoyed at the sake of change for the saving of a handful of bytes with no other benefit as far as I can see.
Quote
Also, I'm becoming serious about doing we::can('moderate_forum') instead of we::allowedTo(), it does seem very readable and blends in nicely with the we::is() function.
At this stage I don't really care. The whole permissions system needs to be rewritten anyway.
Quote
Well, as long as it doesn't reach the size you had before..?
I'd be tempted to say, why not just use the default zip loading classes and be done with it..? What do you need that they don't support?
Well, 199KB for a badly written and unmaintained class. 18KB, given proper documentation, is quite pleasant, not to mention the fact that I will be able to ditch parts of the old package manager in return.

As for the default zip loading classes... I guess I'll just repeat this yet again.

1. They all seem to rely on having various extensions for PHP which may or may not be included. Usually they are not included.
2. I explicitly need to be able to retrieve files from the zip file without creating ANY temporary files. I absolutely need to be able to step through the zip and extract individual files without ever writing anything to the filesystem anywhere, because I need to extract a zip file by file, specifically so I can use FTP to upload it.

I have spent many hours on this now, and I'm getting tired of people questioning why I'm doing it or what I feel I need to do, especially given that I have explained this multiple times, as well as the fact that I've had enough people telling me I should just take the easy option and strip it out (which also removes any possibility of easy patching from the admin panel, completely and utterly outright).

So, I will say this one more time. I am doing what I am doing with zip files and FTP. If you leave me alone to do it, we get nice and convenient uploads of plugins, including mostly magic updating of packages (i.e. upload a new version, it figures out, disables the old one, cleans up its files, then adds the new one), and that opens the door for patching Wedge with periodic updates as and when they come out.

If I keep getting people suggesting that what I'm doing is not worth the effort and that I should rely on methods that might not be available for users, I will end up just cutting all that functionality entirely because I know from experience that I can't rely on the ftp or zip extensions to be available.[1]

Also, if you're shitting yourself about a couple of hundred KB in the install package now, you're going to go fucking nuts in a few weeks when I update phpseclib and use an unflattened copy of the code, where I haven't stripped all its extra spaces and whatnot, because I won't spend two days manually patching phpseclib, I'll just include it wholesale.
Quote
Can't we just do a backtrace on allowedTo() and catch the place where it's done wrongly, and then add a flag to disable permission testing if they're not loaded in the first place...?
What would be the point? I know exactly where it's done wrongly. I've known for months where it's done wrongly. I even documented it and explained what has to be done to fix it being called wrongly. You might as well just replace the one expression with false for all the good it will do - yes, it will stop throwing an error but it doesn't fix the problem that's been there. The broken logic will still be broken, it just won't show you an error about it, like it hasn't been doing since forever.

I will say this a fourth time. THIS IS NOT A NEW BUG SUDDENLY BECAUSE OF YOUR CHANGES TO WE::*. This bug is months old. The only reason you're even noticing it is because now the call is being made before permissions are loaded and it won't be trapped by the old test in allowedTo(). I noticed the error in logic in November, but it's months older than that. The logic is still fundamentally wrong, the fact it throws an error now is merely the result of changes that made an already existing bug more obvious.
Quote
Then maybe call that function again later when permissions are loaded, to 'confirm' the actual user rights. Seems feasable to me, and most importantly, it saves time.
Are you not reading the words I'm writing? Am I talking to myself here about how all this stuff works? Did you read the topic I have mentioned (twice now in this topic alone) that spells out the problem, why it's a problem and how it can be fixed?

It's not going to save time to have to re-figure out all the permissions for boards and topics. The only way to fix this is to rewrite, once and for all, how permissions works.
Quote
I don't like seeing you waste time reinventing the wheel just to avoid a minor hack... SMF/Wedge are full of hacks, that never killed anyone.
How is it reinventing the wheel to avoid going through the entire permissions stuff twice because it's fucking broken?!

Oh jesus I can tell how furious I am right now about how much effort I've spent and how much of a waste of time it feels like. It is what it is. Good night.
 1. And if anyone so much as suggests that I don't need to worry about FTP and that I can rely on chmod, I will visit them in the small hours, cut their heart out with a spoon, then stick their head on a spike, above a sign saying "This is what happens to people who think making software insecure is a good idea." I won't of course, but there is absolutely NO WAY IN HELL I will encourage this sort of behaviour. It's FTP/SFTP or not at all.
Title: Re: Context object?
Post by: Nao on January 5th, 2013, 03:07 AM
Oh, please... -_-
Title: Re: Context object?
Post by: Arantor on January 5th, 2013, 04:23 AM
I'm tired, I'm pissed off and I keep hearing the same things over and over: why don't you use <x>, why don't you do it <this way>? If I thought using <x> was a good idea or doing it <this way> was a good idea, I'd have done it.

I wouldn't have spent the time and effort I have spent, chasing the most ass-backward solution I couldn't even have dreamed of in my darkest nightmares, if I thought for one moment there was a better way that had any reliability without compromising security. The fact that I've documented this many times in the last 18 months is just icing on the cake to me, only to now effectively be told that I'm wasting my time. It's like an architect spending a year of his life designing the most amazing palace and then just getting a shed from IKEA and knocking it together in the afternoon so he could go down the pub. That isn't how I work, you know me well enough by now to know that that isn't how I work.

Yes, I could use these other methods, but I don't like compromise. I won't trade security for anything, and I won't trade performance for laziness - calling something twice because the first time it couldn't be done properly just says we need to fix it so it would work the first time as far as possible, and that means doing what I've been saying for 2 1/2 years about overhauling permissions anyway.

This is why I'm so pissed off. It feels like no-one's listening to what I'm saying. None of this is new, none of this is suddenly out of nowhere. It's not like all of a sudden I'm springing things on you or anyone else. I feel like my posts are on global ignore because what I'm saying is not being taken into account even if I explain them multiple times at great length.

It hurts. It hurts that I feel like this. It hurts that I feel like I'm wasting my time, that I've spent hours and hours researching this stuff to be able to build the best that it can be. It hurts that you don't seem to trust my judgement enough, because if you did, you wouldn't be questioning the rationale behind my thoughts (doubly so since I've already explained most of them multiple times)

I've been tempted to throw the towel in, but we've come a long way and I don't want to waste that. Not for anything or anyone, no matter how frustrated I get. But there's no point in my documenting what I'm going to do, why I'm going to do it or how I think it should just be done - because no-one's reading it anyway. Instead I'm just going to do it and say what I've done. I'm not even going to bother writing *why* any of it was done, because there's clearly no point in doing that beyond the changelog, I'll just wait to be asked in future, because then I'll only write it all out 1 1/2 times (there are of course comments in the source for everything), and save my energy for trying to write code, because I clearly suck at anything else like explaining what I'm doing in a way that anyone reads or cares about.
Title: Re: Context object?
Post by: Nao on January 5th, 2013, 01:15 PM
Quote from Arantor on January 5th, 2013, 02:58 AM
Quote
And it works really... Just rename __construct() to getInstance(), and remove the other getInstance() function... Voilà, it works perfectly that way too.
I'm sure there was a specific reason for NOT doing it that way, but I forgot what it is.
I think I know why... There are two ways of making a singleton. One is static (the ones we usually use), one is dynamic (I think the editor somehow uses instances, would have to dig into it). Here's an example:
http://www.matthewelliston.com/php-singleton-database-class/
As you can see, this one has the getInstance() function too (it seems to be a common name for class init functions...), but it also uses $this inside the object itself. I haven't tried it, but perhaps it could also work if replacing all $this-> call with self::, I don't know, what I'm interested right now, is in the fact that I'm still learning about OOP and as a geek, I need to *understand* the inner workings of objects, rather than just "copy and paste code that I saw elsewhere and worked perfectly" (which, I'll admit, is something I've been doing a lot when it comes to objects... Trial and error is my thing, rather than reading docs :P)

So, I'm thinking that we could simplify these objects, maybe not even care about singles instances, because what's the worse that could happen...? A plugin calling for another instance of an object? Why? At best, it would simply not work. They can't "hurt" Wedge as far as I know by doing that. Generally speaking, my pushing wetem methods to public or protected statuses was only done to help plugin authors understand what methods are there for them to use, and what methods are part of the magic trick that they don't *need* to call (not that they can't look into it... They just don't need it.)

Actually, until a few months ago, I thought that ::getInstance() was some sort of magic function without the double underscore convention. It's only after making a google search on this that I realized it's not a feature, it's just a naming convention. And in my humble opinion (you don't see that one spelled out entirely a lot these days :P), it was created for objects that are actually instantiated (either once or several times), and just re-used by developers who made a copy and paste and rewrote the code to prevent further instances -- without really thinking about the fact that the function itself may not be needed. If you'll kindly look into our code, none of the Wedge files call ::getInstance() for anything else than object initialization. And some of these initializations are absolutely not needed. Again, just try removing all of the new self() calls, most objects will not only initialize fine, they will work the way they're expected to. And that's with PHP 5.2 enabled on my dev platform (I'll admit that it's best to use the lowest common platform for my testing, otherwise I'm bound to have issues in the future.)
Quote
So instead of having getInstance() calls, we're going to have init() calls. Means the same thing, yes?
I can sense the tongue in cheek, but really it isn't the same thing. getInstance() means to me "get a pointer to that object", while init() means "initialize that object". The fact that getInstance() initializes the singleton isn't something we are to 'expect', it's a convention. If you're just a rookie programmer, you'll be puzzled by that call. I know I was when you started implementing it for wesql and others. I just didn't know what it was about. I let you do that magic because frankly it's quite harmless and I'll admit I didn't want to seem like a complete OOP rookie (which I was, I've never been comfortable with objects), but I know better now, at least when it comes to singleton concepts, and I think that we should cut rookies some slack and rename that to init() and only call it if the object actually needs some filling before being used ;)
Quote
But I'm still sure there's a reason why it was done the way it was done rather than what you're doing. I'm also a little annoyed at the sake of change for the saving of a handful of bytes with no other benefit as far as I can see.
Mostly clarity, in my mind. And making me more comfortable with OOP, which in turns encourages me to use objects even more (given that I've already created quite a handful of critical objects for Wedge, such as wess, wetem and we, it's good time that I get comfortable with developing them further without relying on pre-existing code.)
Quote
At this stage I don't really care. The whole permissions system needs to be rewritten anyway.
Do I have your go for moving allowedTo and isAllowedTo to we ASAP? (i.e. are you working on this right now yourself?)
Quote
Well, 199KB for a badly written and unmaintained class. 18KB, given proper documentation, is quite pleasant, not to mention the fact that I will be able to ditch parts of the old package manager in return.
I thought you'd said that you'd managed to reduce it to something like 80KB but that it was still messy. So I figured, if it starts like Wess (an easily manageable 15KB file which progressively got new features added and ended up at 55KB, although not a mess this time ahah), I'm just trying to help and save you time.
I must say though, what you committed yesterday looks great, and I also forgot about some of the requirements you had for your object.
Quote
I have spent many hours on this now, and I'm getting tired of people questioning why I'm doing it or what I feel I need to do, especially given that I have explained this multiple times, as well as the fact that I've had enough people telling me I should just take the easy option and strip it out (which also removes any possibility of easy patching from the admin panel, completely and utterly outright).
I need to make a few things clearer, I guess.
- This month hasn't been easy on either of us.
- After your leave of absence (in terms of commits-ment) of several months, I kinda grew accustomed to being the 'guy in charge', so it's proven difficult for me to dive again into something I've never liked (proof-reading others' code), because eventually I'll always start nit-picking about this or that, not because it NEEDS to be said, but because I feel I'm wasting my time if I don't have at least a line or two to change. I don't know how you do it yourself, maybe you don't proof-read much of my code, I don't know, maybe you just don't feel the need to add your touch, in which case you're lucky, but in the end that's what I am: an annoying partner who's full of good intentions, but not exactly good at explaining them or justifying them other than saying it 'makes more sense'.

Your architect analogy reminded me of The Fountainhead... Or was it How I Met Your Mother :lol:
Quote
Also, if you're shitting yourself about a couple of hundred KB in the install package now,
No, actually I don't give a damn about filesize. ESPECIALLY when it comes to the admin area -- go crazy and waste as many bytes as you like over there, because it's a private area that has absolutely zero impact on overall server performance or bandwidth. You didn't see me complain about the addition of jQuery UI, did you? :P Nah, really what I thought is that maybe you shouldn't kill yourself over rewriting a class if there's already an acceptable solution out there. Then again, we're both all about challenge, aren't we..? We're long past the work-hour efficiency stage, otherwise we'd have released Wedge back in 2011, and our lives would be less complicated ;)
Quote
you're going to go fucking nuts in a few weeks when I update phpseclib and use an unflattened copy of the code, where I haven't stripped all its extra spaces and whatnot, because I won't spend two days manually patching phpseclib, I'll just include it wholesale.
Again, do as you like in the admin area. I'm just conservative on general forum page bytesize ;)
For instance, it's your job to determine that you'd rather use jQuery UI for the badge manager. Which is great. Then it's my job to determine that if plugin authors want to use that copy, they should access it through 'jquery-ui.js' in case we update the file.

Oh, by the way this reminds me... Why not follow the CDN setting for jQuery UI too? I mean, the same file is available through here as well...
ajax.googleapis.com/ajax/libs/jqueryui/1.8.24/jquery-ui.min.js (latest hosted version is 1.9.2)
And other CDNs like code.jquery.com, of course.
Or directly use that one only. I'm not 100% sure about it though, I'm not even 20% sure about it, because if we encourage plugin authors to use the CDN version, there's hardly a way to determine that they're not double-loading it -- IIRC Wedge deletes duplicate URLs, but we can't be sure they're not going to use a different CDN or version.
(Then again, the most likely conflict to happen is that people start making a plugin out of a JS script that also requires jQuery UI, and then they add another JS script that also requires it, and voilà, conflict...)

Oh, my head...!
What was I talking about already..?
Quote
What would be the point? I know exactly where it's done wrongly. I've known for months where it's done wrongly. I even documented it and explained what has to be done to fix it being called wrongly. You might as well just replace the one expression with false for all the good it will do - yes, it will stop throwing an error but it doesn't fix the problem that's been there. The broken logic will still be broken, it just won't show you an error about it, like it hasn't been doing since forever.
But permission error = security error, right...? Doesn't that warrant an immediate hack fix?
Quote
I will say this a fourth time. THIS IS NOT A NEW BUG SUDDENLY BECAUSE OF YOUR CHANGES TO WE::*.
I *did* understand that part, at the very least ;)
Quote
Are you not reading the words I'm writing? Am I talking to myself here about how all this stuff works? Did you read the topic I have mentioned (twice now in this topic alone) that spells out the problem, why it's a problem and how it can be fixed?
As I said at the beginning of my post, ever since you went back in full gear, I've been having a very hard time catching up with your topics... And I actually stopped trying a couple of weeks after your numerous new topics. I just couldn't keep up, so I just focused on the new ones. It's hard. I guess I'm more of a "code first, ask questions later" type...

Actually, I think you should do that as well. Your code is always of the utmost quality, you have great ideas, you don't have to explain them and ask for opinions because we're always here telling you to do it. And whatever comes later -- well, at least you'll have done it, which is not something many people can brag about.
Title: Re: Context object?
Post by: Arantor on January 5th, 2013, 03:43 PM
Quote
I think I know why... There are two ways of making a singleton. One is static (the ones we usually use), one is dynamic (I think the editor somehow uses instances, would have to dig into it). Here's an example:
The editor shouldn't be a singleton, if it is that's a bug. There are some functions that are callable without an instance of the editor, and there some functions that rely on instantiation (i.e. creating an instance with specific content etc.)
Quote
A plugin calling for another instance of an object?
It's more a semantic thing than anything else.
Quote
I can sense the tongue in cheek, but really it isn't the same thing. getInstance() means to me "get a pointer to that object", while init() means "initialize that object"
It is sort of initialisation, but what it also does is quasi-instantiate the object in the process. And yes, it does get a pointer to the object - and promptly stores in the object too.
Quote
because eventually I'll always start nit-picking about this or that, not because it NEEDS to be said, but because I feel I'm wasting my time if I don't have at least a line or two to change.
I understand this. There's a need to feel like you've justified yourself. That's entirely human, too.
Quote
I don't know how you do it yourself, maybe you don't proof-read much of my code, I don't know, maybe you just don't feel the need to add your touch, in which case you're lucky, but in the end that's what I am: an annoying partner who's full of good intentions, but not exactly good at explaining them or justifying them other than saying it 'makes more sense'.
I generally tend to trust your instinct, and I look over it to make sure there's nothing horrific or train-wreck about it, and I go through and debug it if there's a problem, but other than that, I tend to leave it alone, partly because I don't like touching other peoples' things and partly because it doesn't *need* much effort.
Quote
No, actually I don't give a damn about filesize. ESPECIALLY when it comes to the admin area -- go crazy and waste as many bytes as you like over there, because it's a private area that has absolutely zero impact on overall server performance or bandwidth.
So why the push to remove 'public' everywhere? Seemed to me as though it wasn't about readability but saving space - at least that's what I took from it.
Quote
Oh, by the way this reminds me... Why not follow the CDN setting for jQuery UI too? I mean, the same file is available through here as well...
ajax.googleapis.com/ajax/libs/jqueryui/1.8.24/jquery-ui.min.js (latest hosted version is 1.9.2)
And other CDNs like code.jquery.com, of course.
Or directly use that one only. I'm not 100% sure about it though, I'm not even 20% sure about it, because if we encourage plugin authors to use the CDN version, there's hardly a way to determine that they're not double-loading it -- IIRC Wedge deletes duplicate URLs, but we can't be sure they're not going to use a different CDN or version.
(Then again, the most likely conflict to happen is that people start making a plugin out of a JS script that also requires jQuery UI, and then they add another JS script that also requires it, and voilà, conflict...)
It probably should use the CDN setting, and perhaps we need some kind of function to handle this. Normally jQuery is loaded every page as far as I remember, be that from local or from CDN, but I can see the logic of having a flag somewhere to include just jQuery or jQuery + jQuery UI that a plugin can call for?
Quote
Nah, really what I thought is that maybe you shouldn't kill yourself over rewriting a class if there's already an acceptable solution out there
This is one of the things that annoyed me a lot. I'd already explained about the existing solutions and why they're not exactly acceptable. Zip_Archive doesn't work properly on 5.3+ (the PEAR one), the various extensions may or may not be installed, so either I craft a solution that only works on a minority of servers (and thus isn't worth the effort), or I look at PclZip or roll my own. PclZip was horrific, weighing in at 199KB, with tons of options that I didn't really see a need for, with properly ugly code.[1] So in the end I just concluded that rolling my own was quite simply the best approach as it allowed me to do exactly what I needed - and I can. The fact that the plugin manager is capable of receiving uploads and extracting just the plugin manifest is proof of that.
Quote
But permission error = security error, right...? Doesn't that warrant an immediate hack fix?
Not necessarily, no. It's not a security error, in the sense that it doesn't allow the user to do anything they couldn't do before. All the error means is we're checking a permission but the permission isn't loaded - the permission doesn't get granted or anything. There's no way to exploit that to escalate privileges or indeed do anything but add to the error log.

But this has been present for months, it's present on this very site right now for all users who are not you. The difference is, it doesn't have any visible sign that it's happening here, there's nothing going to the error log. It's the same class of error that you could stuff a @ in front of, knowing that it's probably going to fail and you don't care if it does. And there are times when that's acceptable; there's plenty of cases in wextr where I've done that, with the expectation that it's going to fail, but I didn't want any kind of error being thrown by PHP when I will be cleaning it up myself.

In this particular case, though, putting a @ in it will stop the error being thrown but it won't actually fix the problem. It's not like the error must always be thrown and there's no way to fix that; I used it with extreme prejudice in wextr because I'm dealing with fopen/fread etc, where they're relying on things outside of Wedge's control to behave, but here, everything is under Wedge's control and there is no reason why we shouldn't fix it once and for all - properly.

The danger of doing a hack is much like putting a band-aid on a problem; it doesn't fix the problem. It just prevents it getting obviously worse. What we should be doing is fixing the root problem instead.
Quote
As I said at the beginning of my post, ever since you went back in full gear, I've been having a very hard time catching up with your topics... And I actually stopped trying a couple of weeks after your numerous new topics. I just couldn't keep up, so I just focused on the new ones. It's hard. I guess I'm more of a "code first, ask questions later" type...
I get that - probably more than most. And it would have been fine, had these issues suddenly come out of nowhere. But the zip stuff I've been talking about on and off for 18 months, and the permissions stuff I documented months ago, so it just felt like I'd wasted time in doing those things.
Quote
Actually, I think you should do that as well. Your code is always of the utmost quality, you have great ideas, you don't have to explain them and ask for opinions because we're always here telling you to do it. And whatever comes later -- well, at least you'll have done it, which is not something many people can brag about.
I think I might just do that. I'm usually happier working with code - except for last night when nothing seemed to be bloody working properly, even the stuff I did after fighting with zip files and plugin management. Yup, last night I tried to make another game in Impact, except that the player's ship image isn't showing up for some reason. Except there's no reason I can see why not. :(
 1. Crazy indentation, and C-style return values, e.g. sending everything into a function by reference and returning zero on success or non-zero for an error. Even when options were set, you'd pass them in as $class->function(PCLZIP_OPT_SOMETHING, its_value, PCLZIP_OPT_SOMETHINGELSE, its_value, PCLZIP_OPT_WITHOUTVALUE, PCLZIP_OPT_SOMETHING, its_value), it was horrendous. I understood the mentality, but I didn't like it. I spent maybe a week on a partial rewrite, cleaning up the code, trimming methods I didn't see a need for like duplicate (what's wrong with copying the damn file?) and restructuring the API but in the end I accepted that a general purpose zip library didn't really need to be written, Wedge already had a crude zip maker library, I just needed a zip extraction library that allowed me to work without unpacking the entire archive at once.